我是 Stack Overflow 的新手,在使用 C 中的管道时遇到问题。 该项目的目标是 fork 成两个子进程 B 和 C,它们写入管道。然后父进程从管道中读取数据,而无需等待 B 和 C 终止。 fork 必须使用 exec 系统调用来完成。 这是我的代码
int main()
{
printf("Starting process A, PID: %d\n",getpid());
int fd[2];//file descriptors we're using in pipe
int i;//used for while loops
//start the pipe
pipe(fd);
//Spawn process B
int childB=fork();
if (!childB)
{
//Now we're in process B
printf("Forked b says fd[0] is %d and fd[1] is %d\n", fd[0], fd[1]);
char *strArg[4];//string array for arguments
//Set up the arguments we'll be using.
strArg[0]= (char*) malloc(1000*sizeof(char));
strArg[1]= (char*) malloc(1000*sizeof(char));
strArg[2]= (char*) malloc(1000*sizeof(char));
strArg[4]=NULL;
printf("After initiliazing strings b says fd[0] is %d and fd[1] is %d\n", fd[0], fd[1]);
sprintf(strArg[0], "%s", "PipeW1");
int count=sprintf(strArg[1], "%d", fd[0]);
count=sprintf(strArg[2], "%d", fd[1]);
//We need to close the read end of the pipe before executing the writing code
close(fd[0]);
printf("About to execv B and fd[0] is %d and fd[1] is %d\n", fd[0], fd[1]);
//Do the execv call to switch to the different process.
int errcheck=execv("PipeW1", strArg);
if (errcheck==-1)
{
printf("Error opening PipeW1.\n");
}
}
//Still in process A. Going to start process C
int childC=fork();
if (!childC)
{
printf("Forked c says fd[0] is %d and fd[1] is %d\n", fd[0], fd[1]);
//We're in child C
//Close the read end of pipe before doing any write code
close(fd[0]);
char *strArg[4];//string array for arguments
//Set up the arguments we'll be using.
strArg[0]= (char*) malloc(1000*sizeof(char));
strArg[1]= (char*) malloc(1000*sizeof(char));
strArg[2]= (char*) malloc(1000*sizeof(char));
strArg[4]=NULL;
//Put the name of the program into the appropriate argument
sprintf(strArg[0], "%s", "PipeW2");
int count=sprintf(strArg[1], "%d", fd[0]);
count=sprintf(strArg[2], "%d", fd[1]);
printf("About to execv C and fd[0] is %d and fd[1] is %d\n", fd[0], fd[1]);
int errCheck=execv("PipeW2", strArg);
if (errCheck==-1)
{
printf("Error execv C\n");
}
printf("I should have already made C..problem!\n");
}
close(fd[1]);//close output, we only read here
//If I wait for B and C to terminate, the program works without incident.
// int retCode;
//wait(&retCode);
//wait(&retCode);
int count=1;
char buffer[110];
i=0;
while(count)//stop the loop when count=0
{
count= read(fd[0], buffer, 100);
buffer[count]='\0';
printf("%s\n", buffer);
i++;
if (i%50==0)
{
usleep(200000);
}
}
close(fd[0]);
close(fd[1]);
printf("DEBUG when ending A fd[0] is %d and fd[1] is %d\n", fd[0], fd[1]);
printf("Exiting A\n");
exit(EXIT_SUCCESS);
我遇到的问题是,在执行代码时,我的文件描述符 fd[0] 和 fd[1] 分别从 [3,4] 更改为 [0,0],尽管我显然没有操作它们。我遇到的教程都没有很好地解释这一点。
奇怪的是,如果我等待 b 和 c 终止,代码就会工作。 这是输出
- 启动进程A,PID:27457
- fork b 表示 fd[0] 为 3,fd[1] 为 4
- fork 的 c 表示 fd[0] 为 3,fd[1] 为 4
- 初始化字符串 b 后,fd[0] 为 0,fd[1] 为 0
- 即将执行 B 且 fd[0] 为 0,fd[1] 为 0
- 即将执行 execv C,fd[0] 为 0,fd[1] 为 0
- 现在我们处于进程 C,pid:27459
- 起始B
- 将字符串导入B后,fd[0]为0,fd[1]为0
- 退出 C
- B 退出
- B结束后,fd[0]为0,fd[1]为0
- 当结束 A fd[0] 为 3 并且 fd[1] 为 4 时进行调试
- 退出A
因此,当我们处于 fork 状态并操作字符串参数时,文件描述符有时会更改为零。请注意,这似乎发生在任一 execv 之前,因此我认为这是在子级的其他代码影响任何内容之前。
请注意,在使用 sprintf 将整数转换为字符串之前,整数本身为零。
据我所知,我没有在任何地方直接操作数组中的整数。因此,我最好的猜测是,管道在某个时刻被认为是关闭的,并且操作系统在发生这种情况时将所有文件描述符设置为零,但我很难详细找到该点。
我考虑过将 fd[] 文件描述符数组的元素保存为单独的整数,以避免指针出现问题,但我怀疑它们存储在数组中是有充分理由的。
我非常感谢有关该主题的任何建议!谢谢!
最佳答案
代码行
strArg[4] = NULL;
足以解释所有观察到的行为。该数组的尺寸为 4,这会覆盖末尾,并且可能会达到 fd 值。
修复该问题,如果不起作用,请重新提交您的问题。
strArg[3] = NULL;
关于c - 在c中使用pipe()时,我的文件描述符神秘地设置为零,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22951932/