【问题标题】:Problem creating multiple child processes创建多个子进程的问题
【发布时间】:2011-09-24 10:56:21
【问题描述】:

我是流程创建等方面的新手。所以可能是一个基本问题。
我创建了固定数量的子进程,每个子进程除了打印它们的 pid 什么都不做。问题出在我得到的输出中。看看:

int main(){  
pid_t pid=0;  
int i=0,status=0;

    for(i=0;i<3;i++){
            pid=fork();
            switch(pid){
                    case 0:{        //Child
                            printf("\nChild pid: %d",getpid());
                            exit(0);
                            break;
                            }
                    case -1: {//Error
                            printf("Error occured in fork");
                            exit(1);
                            break;
                            }
                    default:{
                            printf("\nParent id: %d",getpid());
                            printf("\nIts child id: %d",pid);
                            wait(NULL);
                            }
            }

输出:
Child pid: 1450
Parent id: 1445
Its child id: 1450
Child pid: 1455Its child id: 1450
Parent id: 1445
Its child id: 1455
Child pid: 1460Its child id: 1455
Parent id: 1445
Its child id: 1460

问题是我不知道为什么只出现父进程的第二个打印语句而不是第一个,如果有的话。我知道我没有等待我的子进程结束(坦率地说我不知道​​我会怎么做),但是如果父进程在结束其子进程之前执行,为什么它的打印语句都没有出现,为什么\n在该行中也被忽略了。
任何帮助将不胜感激。
谢谢。

更新:如果我用printf("\n%d\n",wait(NULL)) 替换wait(NULL),它会给我一个完美的输出,没有杂散的打印。知道什么可以解决吗?毕竟他们都做同样的事情。

【问题讨论】:

    标签: linux shell process


    【解决方案1】:

    问题是有多个进程同时写入同一个文件(您的控制台),而没有任何并发​​控制或任何锁定。那,以及 tty 是奇怪的生物,充其量只会让奇怪的事情发生。除此之外,请记住 printf 已被缓冲。

    你的输出应该这样读:

    Child pid: 1450    <- Child #1
    Parent id: 1445    <- Parent #1.1
    Its child id: 1450 <- Parent #1.2
    
    Child pid: 1455[Its child id: 1450] <- Child #2 with garbage at the end
    Parent id: 1445                     <- Parent #2.1
    Its child id: 1455                  <- Parent #2.2
    
    Child pid: 1460[Its child id: 1455] <- Child #3 with garbage at the end
    Parent id: 1445                     <- Parent #3.2
    Its child id: 1460                  <- Parent #3.2
    

    您可以尝试将输出重定向到文件,看看不是 tty 是否有任何区别。

    无论如何,要做到正确,您应该使用任何保证多进程正确性的机制。

    更新

    是的,现在我明白了。您在打印行的开头有“\n”,而不是像往常一样在结尾处。标准输出通常是行缓冲的,这意味着当它看到“\n”时,缓冲区会被刷新到设备。而且由于您一开始就有它们,因此缓冲区中总是有一行等待输出。

    现在,当您 fork 您的进程时,输出缓冲区会被复制,并且父级的最后一行由子级打印(为什么它在 之后 打印,而不是之前,仍然是对我来说很神秘)。

    无论如何,您添加的新 printf 末尾有一个 '\n',所以它会刷新缓冲区,fork 发现它是空的,一切正常。你也可以打电话给fflush(stdout),但是很麻烦。

    故事的主旨是:“当你printf 用于调试目的时总是在每一行的末尾加上\n,否则你可能会得到部分、混合的内容。

    【讨论】:

    • ok..所以无论如何都不会等待子进程的帮助?如果可以的话,你能解释一下我会怎么做吗?
    • 但是您正在等待,请查看wait() 函数调用。有了孩子的pid,我个人更喜欢waitpid(),以防万一。
    • 是的,我确实放了那个,但我真的不知道它是否放在了正确的位置,或者它是否可以工作......无论如何。
    • 嗯,正确的地方取决于你想做什么,但对我来说似乎是正确的。您可以查看wait() 的返回值来检查它是否有效:它应该是结束进程的 pid。
    【解决方案2】:

    问题在于标准输出的缓冲和刷新。

    正在打印两行,但不会在您期望的时间刷新到输出....取决于输出的位置,(文件、管道、终端、stderr 等)printf 使用不同的缓冲区策略。

    我猜在你的情况下它只刷新换行符(检查man setbuf

    将换行符移到末尾而不是开头,例如....

           printf("Parent id: %d\n",getpid());
           printf("Its child id: %d\n",pid);
    

    并且始终将 \n 放在所有 printf 的 printf 末尾。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-23
      • 1970-01-01
      • 2016-07-11
      • 1970-01-01
      • 1970-01-01
      • 2014-05-11
      相关资源
      最近更新 更多