【发布时间】:2023-03-26 11:29:01
【问题描述】:
当子进程的数量很大时,我的程序停止运行。我不知道问题可能是什么,但我猜想子进程在运行时被阻塞了。
这是程序的主要工作流程:
void function(int process_num){
int i;
// initial variables for fork()
int status = 0;
pid_t child_pid[process_num], wpid;
int *fds = malloc(sizeof(int) * process_num * 2);
// initial pipes
for(i=0; i<process_num; i++){
if(pipe(fds + i*2) <0)
exit(0);
}
// start child processes to write
for(i=0; i<process_num; i++){
child_pid[i] =fork();
if(child_pid[i] == 0){
close(fds[i*2]);
// do something ...
// write(fds[i*2+1], something);
close(fds[i*2+1]);
exit(0);
}else if(child_pid[i] == -1){
printf("fork error\n");
exit(0);
}
}
// parent waits child processes and reads
for(i=0; i<process_num; i++){
pid_t cpid = waitpid(child_pid[i], &status, 0);
if (WIFEXITED(status)){
close(fds[i*2+1]);
// do something ...
// read(fds[i*2], something);
close(fds[i*2]);
}
}
free(fds);
while((wpid = wait(&status)) > 0);
}
我通过 htop 检查了进程的状态,有几个(例如,8 个,而 process_num 为 110)子进程的状态为 S。
现在我的问题来了:如果子进程的数量大于处理器的数量,在使用管道为子进程和当前进程进行通信时,子进程是否会被阻塞(父进程等待所有子进程执行) ?非常感谢!
编辑:我在使用read()和write()时打印了fds的Id,我发现读从4开始,写在5,我不知道为什么是案例,有人知道吗?
【问题讨论】:
-
不,处理器的数量不限制这个。您可以在单核机器上拥有(例如)100 个进程——没问题。更有可能的是,阻塞是由于您的代码中的错误造成的。具体来说,parent 进程应该在 进行任何等待之前关闭管道中间部分的 fd。我运行了您发布的程序,它在几分之一秒内完成,那么您发布的代码与您的实际程序有多接近?
-
你肯定有错误。当我将进程数设置为一个较小的数字(例如)10 但将缓冲区写入长度设置为 100,000 时,我被阻止了。
read电话在哪里?在每个阶段i,您必须从fds[(i - 1) * 2]读取并写入fds[i * 2 + 1]。第一阶段是特殊的(例如)从某个文件中读取。而且,最后一个阶段是特殊的(例如)写入标准输出。我会使用struct来控制每个阶段。有关 [在自定义外壳中] 工作管道的示例,请参阅我的回答:stackoverflow.com/questions/52823093/fd-leak-custom-shell/… -
@Craig Estey 嘿,非常感谢!我发现确实存在 read() 的错误。我的读取函数对其中一个数据长度为 0 的 fd 抛出错误。读取时
fds[(i - 1) * 2]是正确的,而不是fds[i*2]?但是当i =0时会发生什么? -
就像我说的,第一阶段(即
i == 0)很特别。i - 1有 no [有效]fds条目。并且,最后阶段同样没有有效的输出值。你正在做的是相当于一个shell pipe:| cat | cat | cat |而不是cat < infile | cat | cat > outfile -
@CraigEstey 哦,对不起,我不小心跳过了你提到的关于 i == 0 的部分。但我阅读了tldp.org/LDP/lpg/node11.html,并按照示例,i*2 用于阅读,i*2 + 1 写作
标签: c multiprocessing jenkins-pipeline pipe