【发布时间】:2016-02-07 08:02:59
【问题描述】:
我目前正在创建自己的命令行 shell,但在尝试接收管道时遇到了问题。我的程序从父进程开始。它检查用户是否输入了退出或历史记录。如果是这样,它会使用这些命令,但这并不重要。如果用户输入的不是退出或历史记录,那么它会创建一个执行当前任务的子进程。
但是,如果用户输入一个只有一个管道的命令,那么我们从父进程开始,它会创建一个子进程,称之为子进程,子进程 1。子进程 1 看到有一个管道并使用 fork 来创建另一个孩子,称此孩子 2。孩子 1 创建另一个孩子,称其为孩子 3(注意:孩子 2 和 3 使用共享内存)。现在,孩子 2 执行第一个命令,孩子 3 使用孩子 2 的输出执行命令。但由于某种原因,我没有得到任何输出。
我不确定这是否是执行任务的最有效方式,但这是我的教授所说的。
如果您想在这里查看我的所有代码,请访问:http://pastebin.com/YNTVf3XP
否则这是我从孩子 1 开始的代码:
//Otherwise if we have a single pipe, then do
else if (numPipes == 1) {
char *command1[CMD_MAX]; //string holding the first command
char *command2[CMD_MAX]; //string holding the second command
int fds[2]; //create file descriptors for the parent and child
pid_t new_pid; //create new pid_t obj
onePipeSplit(tokens, command1, command2, numTokens); //Getting each command for pipe
if (pipe(fds) < 0) { //use the pipe command. If < 0
perror("Pipe failure."); //we have an error, so exit
exit(EXIT_FAILURE);
}
//Creating child 2
new_pid = fork();
//if pid < 0 then we have an error. Exit.
if (new_pid < 0) {
perror("Fork failure.");
exit(EXIT_FAILURE);
}
//Else we have the child (2) process
else if (new_pid == 0) {
close(fds[0]); //Close read
//sending stdin to the shared file descriptor
if (dup2(fds[1], STDOUT_FILENO)<0) {
perror("Can't dup");
exit(EXIT_FAILURE);
}
execvp(command1[0], command1); //Execute the next command
perror("Exec failure");
exit(EXIT_FAILURE);
}
//Else if we have the parent process
else {
pid_t child = fork(); //Creating child 3
if (new_pid < 0) { //if pid < 0, error, exit
perror("Fork failure.");
exit(EXIT_FAILURE);
}
//else if pid > 0 we have the parent wait until children execute
else if (new_pid > 0) {
wait(NULL);
}
//else we have the child (3)
else {
close(fds[1]); //Close write
//Sending stdout to the shared file descriptor
if (dup2(fds[0], STDIN_FILENO) < 0) {
perror("Can't dup");
exit(EXIT_FAILURE);
}
execvp(command2[0], command2); //Execute the command
perror("Exec failure");
exit(EXIT_FAILURE);
}
}
}
【问题讨论】:
-
我觉得你的孩子太多了。如果您有
foo | bar,您需要一个管道和另外两个进程(除了您的程序已经存在的那个)。所以父母创建了一个管道,p父母派生了第一个孩子(这将是bar)。孩子:close(p[1]); dup2(p[0], 0); exec("bar");现在父母第二次分叉(这将是foo)。孩子:close(p[0]); dup2(p[1], 1); exec("foo");父母:close(p[0]); close[p[1]); wait for children. -
@J.V.A.我在问题中添加了一张图片,显示了我的教授给了我什么。这不是意味着总共应该有3个孩子吗?不过我可能是错的。
-
我不确定 shell(1) 的功能是什么,但如果教授希望这样做,那就是正确的答案:)
-
@j.v.a 好的,你明白为什么它没有打印到标准输出了吗?
标签: c debugging process pipe pid