我必须编写一个 C 代码:
- 接受 'n' 个命令行参数(unix 命令)
- 对于每个参数,主程序启动两个子进程
- 每个子进程将随机延迟并使用 popen 执行 unix 命令 (args[i]),然后将答案发送给父进程 父进程将仅打印收到的前 n/2 个响应
- 父进程与子进程之间的通信只能使用管道 channel
我编写了如下源代码:
#include <stdio.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <wait.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#define DIM 100
int main(int argc, char *args)
{
int t, nrR=argc-1,f,p[2],prID,d;
FILE *fd1, *fd2;
//PIPE channel creation
if(pipe(p)<0)
{
perror("PIPE channel creation error!");
exit(1);
}
for(i=1;i<argc;i++)
{
d=strlen(args[i]);
if((f=fork())==0)
{ //FIRST CHILD PROCESS
char *buffer = malloc(DIM*sizeof(char));
//The child process will only write to the parent process
close(p[0]);
//Delay the process execution
srand(time(NULL));
int s=rand()%2;
sleep(s);
fd1 = popen(args[i],"r");
//Writing the PID to the parent process
prID=getpid();
if(write(p[1],&prID,sizeof(int))!=sizeof(int))
{
perror("PIPE writing error!");
exit(3);
}
//Writing the command string length
if(write(p[1],&d,sizeof(int))!=sizeof(int))
{
perror("PIPE writing error!");
exit(3);
}
//Writing the command string
if(write(p[1],args[i],sizeof(args[i]))!=sizeof(args[i]))
{
perror("PIPE writing error!");
exit(3);
}
//Writing the command output result string
while(fread(buffer,DIM,1,fd1)>0)
{
if(write(p[1],buffer,sizeof(buffer))!=sizeof(buffer))
{
perror("PIPE writing error!");
exit(3);
}
}
free(buffer);
pclose(fd1);
exit(i+1);
}
else if((f=fork())==0)
{ //SECOND CHILD PROCESS
char *buffer = malloc(DIM*sizeof(char));
//The child process will only write to the parent process
close(p[0]);
//Delay the process execution
srand(time(NULL));
int s=rand()%2;
sleep(s);
fd2 = popen(args[i],"r");
//Writing the PID to the parent process
prID=getpid();
if(write(p[1],&prID,sizeof(int))!=sizeof(int))
{
perror("PIPE writing error!");
exit(3);
}
//Writing the command string length
if(write(p[1],&d,sizeof(int))!=sizeof(int))
{
perror("PIPE writing error!");
exit(3);
}
//Writing the command string
if(write(p[1],args[i],sizeof(args[i]))!=sizeof(args[i]))
{
perror("PIPE writing error!");
exit(3);
}
//Writing the command output result string
while(fread(buffer,DIM,1,fd2)>0)
{
if(write(p[1],buffer,sizeof(buffer))!=sizeof(buffer))
{
perror("PIPE writing error!");
exit(3);
}
}
free(buffer);
pclose(fd2);
exit(i+2);
}
}
if(f>0)
{
//Parent process behavior
close(p[1]); //The parent process will not write to the child processes
for(i=0;i<nrR;i++)
{
//we will read and print only the first 'n' responses received through the pipe channel from the child processes
waitpid(-1,NULL,0);
char *cmd,*buffer;
//Read the pid of the child process
if(read(p[0],&prID,sizeof(int))!=sizeof(int))
{
perror("PIPE reading error!")
exit(2);
}
//Read the command string length
if(read(p[0],&d,sizeof(int))!=sizeof(int))
{
perror("PIPE reading error!")
exit(2);
}
//Read the command
cmd = malloc(d*sizeof(char));
if(read(p[0],cmd,sizeof(cmd))!=sizeof(cmd))
{
perror("PIPE reading error!")
exit(2);
}
printf("\nProcess %d -> %s:\n",prID,cmd);
//Read and print the unix command result
buffer = malloc(DIM*sizeof(char));
while(read(p[0],buffer,sizeof(buffer))>0)
{
printf("%s",buffer);
}
free(buffer);
free(cmd);
//Wait for other n/2 child processes to terminate
while(waitpid(-1,NULL,0)>0)
{
if(errno == ECHILD)
break;
}
}
}
return 0;
}
我的代码编译并运行;我试过“ls”作为参数。该程序没有显示预期的输出。我介绍了一些支票打印,并检测到以下问题:
- 在子进程中,我无法读取 fd1 和 fd2 的整个“ls”输出
- 父进程没有收到任何东西/没有正确收到子进程通过管道发送的“ls”输出字符串(它虽然正确收到了子进程 ID 和命令名称)。
多个子进程尝试(可能同时)写入同一个 PIPE channel 是否会导致问题?还是有其他一些我没有想到的问题?
非常感谢。
最佳答案
每个 child 都需要它自己的管道返回父级,所以 p 应该是一个二维数组,p[child][file id]。 您绝不会尝试收集命令数据,也不会访问与命令的标准输出相关的管道。您打算如何将命令输出发送回父级。您需要告诉 parent 有多少字节的文本即将到来,然后将其全部写入可能是最好的解决方案。它允许您 malloc 准备好将其存储为字符串的缓冲区,并且它也可以被 block 读取而不是一次读取一个字节,直到 '\0'
关于c - 多个子进程将使用 popen 执行的 unix 命令的结果写入父进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29926927/