Fork永远不会进入孩子的过程

我正在编写一个模仿shell行为的代码,特别是&和|。

我的函数接收用户命令,并检查是否有&在最后,然后子进程应该在后台运行,父进程不应该等待它完成并继续执行命令。

它也应该检查是否有| 在输入数组中运行两个子进程,同时管道他们的stdin和stdout。

我已经实现了&的行为,但每当我编译并运行我的代码时,我只从父进程中获取printf语句。

我想听听如何解决这个问题的想法,此外,我将不胜感激任何关于|的实施的建议 (管道)以及如何防止僵尸。

int process_arglist(int count, char** arglist) { int pid = fork(); printf("%d", pid); switch (pid) { case -1: fprintf(stderr, "ERROR: fork failed\n"); return 1; break; case 0: // Son's proccess printf("I got to son"); //check last arglist argument if (strcmp(arglist[count - 1], "&") == 0) { setpgid(0, 0); arglist[count - 1] = NULL; if (execvp(*arglist, arglist) < 0) { //execute the command fprintf(stderr, "ERROR: execvp failed\n"); exit(1); } } else { //There's no & at the end, look for pipes int i = 0; while (i < count) { if (strcmp(arglist[i], "|") == 0) { int pid2 = fork(); if (pid2 < 0) { //fork failed, handle error } if (pid2 == 0) { // Son's proccess } else { //Parent's code } } } } break; //in case no & and no |, call execvp default: //Parent's code printf("I go to parent"); return 1; break; } return 0; 

}

输出总是“我去父母”

我假设您的代码适用于Linux或其他POSIX系统。 阅读一些关于Linux编程的好书(可能是旧的高级Linux编程 ,可以免费下载,或者更新的东西)。

stdio(3)被缓冲stdoutprintf经常(但不总是)行缓冲。 出于效率原因进行缓冲(经常调用write(2) ,例如每个输出字节一次, 非常慢;您应该更喜欢在几千字节的块上进行write )。

顺便说一下,你可以通过使用errno(3) thru perror(3) (或errno上的strerror(3))来更好地处理系统调用失败(参见intro(2)和syscalls(2) )。 您(以及您的shell的用户)需要被告知失败原因(并且您当前的代码没有显示它)。

我建议经常用\n结束你的printf格式控制字符串(这在stdout是行缓冲时有效)或在适当的地方调用fflush(3) 。

根据经验,我建议做fflush(NULL); 在每次调用fork之前(2) 。

您观察到的行为与某些printf -ed数据停留在缓冲区(例如stdout )中的假设一致。

您可以在程序(或其他程序,例如某些现有的shell进程)上使用strace(1)来了解完成的系统调用 。

您应该使用所有警告和调试信息进行编译(例如gcc -Wall -Wextra -g和GCC ),改进代码以获取警告,并使用调试器gdb (小心,它可以用于分叉过程)。

我正在编写一个模仿shell行为的代码

你可能正在编写一些shell。 然后研究现有自由软件 shell的源代码(大多数 – 可能是所有Linux shell都是自由软件)。

我将不胜感激任何关于|的实施的建议 (管道)以及如何防止僵尸。

解释所有这些需要大量空间(书的几个章节,或者可能是整本书)并且不适合这里或任何其他论坛。 所以阅读一本很好的Linux或POSIX 编程书 。 关于管道,读管(7) (应在fork 用管(2)创建)。 关于避免僵尸进程 ,您需要仔细调用waitpid(2)或类似的调用。