2012-07-11 56 views
1

我有一个任务是从命令行中取出一个字符串,并使用fork()将其逆转并在单独的子进程中输出每个字符。我只是没有从fork()调用获取正确的输出。问题是索引在输出上混乱了,比如3,1,2,0,当它应该是3,2,1,0 ...等等......什么让它更容易混淆,它是随机成功的单词长度为3个字符(但不总是),但对于4个字符以上的单词而言,通常不正确。没有fork()调用,循环正常工作。使用fork()为每个孩子输出1个数组元素,C++

这是我的主要功能,问题存在于for循环中。

int main(int argc, char **argv){ 
    pid_t childpid = 0; 
    int i; 
    char* invert = new char[strlen(argv[1])+1]; 
    int invert_length = strlen(argv[1]); 
    strcpy(invert, argv[1]); 
    for(i=invert_length-1; i>=0; i--){ 
     childpid = fork(); 
     if(childpid==(pid_t) 0){ 
      //I am the child    
      cout<<"Child ["<< i <<"] = " << invert[i] <<"."<<endl; 
      break; 
     } 
    } 
    return 0; 
} 

回答

2

程序的简单修改使得它的工作。让孩子做下一个叉子。每个进程都等待它产生的进程。

int main(int argc, char **argv){ 
    pid_t childpid = 0; 
    int i; 
    char* invert = new char[strlen(argv[1])+1]; 
    int invert_length = strlen(argv[1]); 
    strcpy(invert, argv[1]); 
    for(i=invert_length-1; i>=0; i--){ 
     childpid = fork(); 
     if(childpid==(pid_t) 0){ 
      //I am the child 
      cout<<"Child ["<< i <<"] = " << invert[i] <<"."<<endl; 
      continue; 
     } 
     break; 
    } 
    wait(0); 
    return 0; 
} 

编辑: Skizz反对,认为每个进程启动下一个之前执行的工作。在问题中没有要求所有的流程都是首先推出的,但下面的版本是这样做的。

int main(int argc, char **argv){ 
    pid_t childpid = 0; 
    int i; 
    char* invert = new char[strlen(argv[1])+1]; 
    int invert_length = strlen(argv[1]); 
    strcpy(invert, argv[1]); 
    for(i=0; i<invert_length; ++i){ 
     childpid = fork(); 
     if(childpid!=(pid_t) 0){ 
      wait(0); 
      break; 
     } 
    } 
    if (i-->0) cout<<"Child ["<< i <<"] = " << invert[i] <<"." <<endl; 
    return 0; 
} 
+0

非常感谢!我正准备在使用睡眠(5 /(i + 1))方法后才能注销,并且每次都有效地计时,但是看到了您的帖子并认为这样会更好。 – Nibirue 2012-07-11 11:05:09

+0

尽管这确实解决了原始问题,但它实际上是一个单一的流程解决方案。每个新进程在前一个进程完成时创建。如果我是一位设置这个问题的老师,我可能会因此失败,因为中心概念是协调并发进程而不是如何对它们进行序列化。对它们进行串行化使得使用多个进程的整个过程失败。 – Skizz 2012-07-11 15:57:55

+0

@Skizz:任何形式的协调都可以有效地序列化它们。考虑到问题的参数,我提出的解决方案是最有效的方法。 Regards – jxh 2012-07-11 16:03:51

0

这和pthreads一样。没有保证,这些孩子将按照产卵的顺序执行。心智SIGCHLD。

0

问题是fork调用产生一个新进程,复制调用进程。正如你在一个循环内部做的那样,你现在有很多进程都想同时执行。它们执行的顺序(因为CPU一次只能执行一个进程*)取决于操作系统,因为这是选择执行哪个进程的事情,所以输出变得不确定。

为了解决这个问题,每个产生的进程都需要知道何时输出使用进程之间某种类型的同步的手段。

注:

  • 我忽略了超线程/多内核的简单性。
0

编辑:

你可以叉,然后调用wait,从而满足硬件需求。 我原来下面的答案是你如何能在更复杂的环境(一个真正的应用程序)运行这个和上面

指出你将如何能够采取从运行一些代码,在一个单独的进程

添加wait优势

int main(int argc, char **argv){ 
    pid_t childpid = 0; 
    int i; 
    char* invert = new char[strlen(argv[1])+1]; 
    int invert_length = strlen(argv[1]); 
    strcpy(invert, argv[1]); 
    for(i=invert_length-1; i>=0; i--){ 
     childpid = fork(); 
     if(childpid==(pid_t) 0){ 
      //I am the child    
      cout<<"Child ["<< i <<"] = " << invert[i] <<"."<<endl; 
      break; 
     } 
     else { 
      int stat; 
       wait(&stat); 
     } 
    } 
    return 0; 
} 

我同意@illusionoflife,但如果它的功课,那么它必须能够

你可以设置一个事件处理程序(例如用libevent的)为SIGCHLD,然后启动下一子AFTE r接收到第一个SIGGCHLD等

此练习的要点可能不是跨多个CPU的负载均衡,而是显示您可以使用Copy On Write执行的操作。

Here是我提出的问题在几个月前,让你开始

相关问题