【发布时间】:2015-11-05 22:34:44
【问题描述】:
我现在正在学习 C,并负责在 Minix 虚拟机中创建一个 shell,我正在使用 Minix 中已有的库函数来完成这项工作,例如 ls、cd 等。 ..
我遇到了一个问题,在 fork 子进程后,我导致核心转储,而不是执行我的命令
#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
/*Initialise variables*/
int pid;
char *envp[] = { NULL };
char userInput[256];
void isParent(){
int stat;
waitpid(-1, &stat, 0);
}
int main(int argc, char *argv[]) {
/*Infinite loop to cause shell to be "permenant"*/
while(1){
/*"*" to lead every line*/
printf("%s","*");
/*Get user input*/
scanf("%s", userInput);
/*Leave an exit clause, to not be permenantly stuck in loop*/
if(strcmp(userInput, "exit") == 0){
exit(1);
}
/*create my child process*/
pid = fork();
/*if process is parent, wait*/
if (pid != 0){
isParent();
}
/*Perform function typed by the user*/
execve(userInput, &argv[1], envp);
}
}
这是我目前正在使用的代码,当将 /bin/ls 作为我的 shell 的参数传递时,我可以让它在一个用户输入中打印 ls,两次,但是它在执行时退出 shell采取行动,这是不应该的。我希望能够使用其他功能,让它们打印一次,然后返回等待用户输入。
当不传递参数时,shell 将只接受“退出”,不接受其他命令。如果我从我的主方法、execve 或两者中删除参数子句 (argv[]),它们会引发错误,这是您所期望的。
我已经阅读了有关我使用过的所有功能的文档,并专门选择了它们,因此我希望不必更改它们,除非我正在做的事情实际上无法使用它们。
仍在学习 C,因此我希望使用更小的技术术语或更易于理解的短语。我不确定我的问题之前是否曾提出过问题,但我已经用大约 20 种不同的方式搜索了我的问题,并且我的问题的大多数版本都是为 c++、c# 编写的,或者与我的不相似问题,据我了解。
我还要待几个小时,所以如果我错过了任何信息,请随时发表评论并要求澄清、信息或其他任何事情。
【问题讨论】:
-
isParent()返回时你认为会发生什么?如果没有else,它将运行evecve(),它永远不会返回。 -
@EOF 我希望
isParent()陷入无限循环,这样我的 shell 可以在孩子为我执行我的功能时继续运行,然后一旦孩子完成了它的事情,就可以返回 shell 执行另一个功能。 -
在检查命令行参数时,永远不要访问
argv[0]以外的地方,直到检查argc以确保命令行参数确实存在。访问不存在的参数将导致通过 NULL 指针访问的段错误或访问某些随机区域。无论哪种情况,结果都是未定义的行为。 IE。在访问 argv[] 之前检查argc -
这条线:
scanf("%s", userInput);有几个问题:1) 始终检查返回值(而不是参数值)以确保操作成功。 2) 格式说明符%s没有大小限制,因此用户很容易超出输入缓冲区userInput[]。为避免此问题,请在 %s 格式说明符上放置一个最大长度修饰符,该修饰符比输入缓冲区的长度小一。 (请记住,带有 %s 的 scanf() 总是在缓冲区末尾附加一个 NUL 字节)在这种情况下,建议:`scanf("%255s", userInput); -
fork()函数可以有以下三种返回指示中的任何一种:>0 表示在父项中 ==0 表示在子项中,pid = fork(); if( pid ==0 ) { // then child execve(); perror( "exeve() failed"); exit( EXIT_FAILURE )' } else if( pid > 0 ) { then parent ... } else { // fork() failed perror( "fork() failed" ); exit( EXIT_FAILURE ); }