使用fork()为每个子输出1个数组元素,C ++

时间:2012-07-11 10:32:13

标签: c++ fork

我有一个赋值,即从命令行接收一个字符串,反转它并使用fork()在单独的子进程中输出每个字符。我只是没有从fork()调用得到正确的输出。问题是索引在输出上混杂起来,比如3,1,2,0,它应该只是3,2,1,0 ......等等......是什么让它更加混乱是当它随机成功时单词长度为3个字符(但并非总是如此),但对于4个以上字符的单词通常不正确。循环在没有fork()调用的情况下正常工作。

这是我的主要功能,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;
}

4 个答案:

答案 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;
}

答案 1 :(得分:0)

与pthreads一样,情况也是如此。不保证,孩子将按产生的顺序执行。 Mind SIGCHLD。

答案 2 :(得分:0)

问题是fork调用产生一个新进程,复制调用进程。当您在循环中执行此操作时,您现在有许多想要同时执行的进程。它们被执行的顺序(因为CPU一次只能执行一个进程*)取决于操作系统,因为它选择执行哪个进程,因此输出变得不确定。

要解决这个问题,每个衍生进程都需要知道何时输出,这意味着在进程之间使用某种同步方式。

注意:

  • 为简单起见,我忽略了超线程/多核。

答案 3 :(得分: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,但如果它的作业必须是可能的

您可以为SIGCHLD设置一个事件处理程序(例如使用libevent),然后在收到第一个SIGGCHLD后启动下一个孩子等。

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

Here是几个月前我问过的一个问题,让你开始