gpt4 book ai didi

c - 将 execl 与多个子进程一起使用

转载 作者:太空狗 更新时间:2023-10-29 15:08:09 24 4
gpt4 key购买 nike

我正在尝试创建一个创建多个子进程的进程,每个子进程调用 file()功能。

这是我目前所拥有的:

  • 父级将文件列表写入管道
  • 子进程将管道重定向到 stdin,将 stdout 重定向到另一个管道和每个 exec file
  • 父进程使用 select 等待子进程终止,并从相关管道中读取(包含文件函数的输出)。

当我只使用一个子进程时,一切都运行良好:子进程终止,所有输出都在管道中,父进程读取它。但是,当我使用 2 个子进程时,它们不会终止;文件函数进入“休眠”模式,等待更多输入。然后父级也被阻塞,等待子级终止。

我创建了两个管道版本的最小包含示例:

#define NUM_CHILDREN (2)
//pipes from parent to children
int pipeP2C[NUM_CHILDREN][2];
//pipes from children to parent
int pipeC2P[NUM_CHILDREN][2];

int children_ids[NUM_CHILDREN];

int main()
{
//create pipes from parent to children and vice versa
for (int i = 0; i < NUM_CHILDREN; ++i){
pipe(pipeP2C[i]);
pipe(pipeC2P[i]);
}

//create first child
//Create initial g_parLevel child processes
pid_t pid;
int numForks = 0;
do
{
pid = fork();
// Parent process should count how many children it has
if (pid > 0) {
children_ids[numForks] = pid;
++numForks;
}
//child process also writes its' own pid to children_ids.
else {
children_ids[numForks] = (int)getpid();
}
}
//Call fork again from parent process, if it doesn't have g_parLevel children already.
while (pid > 0 && numForks < NUM_CHILDREN);

//Now we have NUM_CHILDREN child processes, their ids are kept in the parent process, and each
//of them has (at least) it's own id kept in the suitable index in children_ids.

//parent - write to the children
if (pid > 0){
//Iterate over all children
for (int i = 0; i < NUM_CHILDREN; ++i)
{
std::string str = "/bin/ls";
//close reading end
close(pipeP2C[i][0]);
//write to child
write(pipeP2C[i][1], str.c_str(), (int)str.length());
close(pipeP2C[i][1]);
}

//wait for the children to terminate
int terminatedChildren = 0;
while (terminatedChildren < NUM_CHILDREN)
{
int status;
int terminatedChild = wait(&status);
++terminatedChildren;

//read from the terminated child
int childIndex = children_ids[0] == terminatedChild ? 0 : 1;

//close writing end
close(pipeC2P[childIndex][1]);
char buf[2048];
read(pipeC2P[childIndex][0], buf, sizeof(buf));
close(pipeC2P[childIndex][0]);
std::cerr<<"output from child "<<childIndex<<" is:\n"<<buf<<std::endl;
}
}

//child process
if (pid == 0)
{
//find the pipe to read from.
int childPid = getpid();
int childIndex = children_ids[0] == childPid ? 0 : 1;
std::cerr<<"in child "<<childPid<<" index "<<childIndex<<std::endl;
//wait until the parent has written data
fd_set rfds;
int ready;
while(true)
{
FD_ZERO(&rfds);
//we are interested in the reading end
FD_SET(pipeP2C[childIndex][0], &rfds);
ready = select(pipeP2C[childIndex][0] + 1, &rfds, NULL, NULL, NULL);
if (ready > 0){
std::cerr<<"ready"<<std::endl;

//close the relevant writing end of the pipe from parent to child
close(pipeP2C[childIndex][1]);
//redirect input to stdin
dup2(pipeP2C[childIndex][0], 0);
close(pipeP2C[childIndex][0]);

//close relevant reading end of the pipe from child to parent
close(pipeC2P[childIndex][0]);
//redirect output from stdout
dup2(pipeC2P[childIndex][1], 1);
close(pipeC2P[childIndex][1]);

execl("/usr/bin/file","file", "-n", "-f", "-", (char *)NULL);

//should never get here
std::cerr<<"file failed"<<std::endl;
exit(1);
}
}
}
}

为什么不等

最佳答案

您没有关闭来自其他进程的文件描述符。当您 fork 时,您的 child 仍然可以引用其他 child 的文件描述符。

在处理之前关闭它们。像这样的东西:

for(int k=0;k<NUM_CHILDREN;k++){
if(k!=childIndex){
close(pipeP2C[k][0]);
close(pipeP2C[k][1]);
close(pipeC2P[k][0]);
close(pipeC2P[k][1]);
}
}

子部分中的 while(true) 位应该可以解决问题。所以:

//child process
if (pid == 0)
{
//find the pipe to read from.
int childPid = getpid();
int childIndex = children_ids[0] == childPid ? 0 : 1;
std::cerr<<"in child "<<childPid<<" index "<<childIndex<<std::endl;
//wait until the parent has written data
fd_set rfds;
int ready;
for(int k=0;k<NUM_CHILDREN;k++){
if(k!=childIndex){
close(pipeP2C[k][0]);
close(pipeP2C[k][1]);
close(pipeC2P[k][0]);
close(pipeC2P[k][1]);
}
}
while(true)
{
FD_ZERO(&rfds);
//we are interested in the reading end
FD_SET(pipeP2C[childIndex][0], &rfds);
ready = select(pipeP2C[childIndex][0] + 1, &rfds, NULL, NULL, NULL);
if (ready > 0){
std::cerr<<"ready"<<std::endl;

//close the relevant writing end of the pipe from parent to child
close(pipeP2C[childIndex][1]);
//redirect input to stdin
dup2(pipeP2C[childIndex][0], 0);
close(pipeP2C[childIndex][0]);

//close relevant reading end of the pipe from child to parent
close(pipeC2P[childIndex][0]);
//redirect output from stdout
dup2(pipeC2P[childIndex][1], 1);
close(pipeC2P[childIndex][1]);

execl("/usr/bin/file","file", "-n", "-f", "-", (char *)NULL);

//should never get here
std::cerr<<"file failed"<<std::endl;
exit(1);
}
}
}

关于c - 将 execl 与多个子进程一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22286390/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com