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

时间:2017-12-02 08:18:16

标签: c shell process operating-system 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;

}

输出始终是“我去父母”

1 个答案:

答案 0 :(得分:2)

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

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

顺便说一句,您最好使用system callsintro(2)(或syscalls(2)来处理errno(3)(请参阅perror(3)strerror(3))的失败在errno)。您(以及您的shell的用户)需要被告知失败原因(并且您当前的代码没有显示它)。

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

根据经验,我建议在每次拨打fork(2)之前执行fflush(NULL);

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

您可以在程序中使用strace(1)(或在其他程序上使用{3}},以了解system calls已完成的内容。

您应编译所有警告和调试信息(例如gcc -Wall -Wextra -gGCC),改进您的代码以获取警告,use the debugger gdb(小心,它可以用于分叉过程)。

  

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

你可能正在编写一些shell。然后研究获取现有free software shell的源代码(大多数 - 可能是所有Linux shell都是免费软件)。

  

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

解释所有需要大量空间(书的几个章节,或者整本书)和不适合或任何其他论坛。所以阅读一本好的Linux 或POSIX 编程书。关于管道,请阅读pipe(7)(应在<{em> fork之前使用pipe(2) 创建。{关于避免zombie processes,您需要仔细拨打waitpid(2)或类似的电话。