在c中使用pipe()时,我的文件描述符神秘地被设置为零



我是Stack Overflow的新手,在C中使用管道时遇到问题。该项目的目标是分叉为两个子进程,B和C,它们向管道写入。然后父进程从管道中读取,而不等待B和C终止。分叉必须使用exec系统调用来完成。这是我的代码

int main()
{  
    printf("Starting process A, PID: %dn",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 %dn", 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 %dn", 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 %dn", 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 %dn", 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 %dn", fd[0], fd[1]);

    int errCheck=execv("PipeW2", strArg);
    if (errCheck==-1)
    {
        printf("Error execv Cn");
    }
    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]='';
  printf("%sn", 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 %dn", fd[0], fd[1]);
printf("Exiting An");
exit(EXIT_SUCCESS);

我遇到的问题是,在执行代码时,我的文件描述符fd[0]和fd[1]分别从[3,4]更改为[0,0],尽管我显然没有操作它们。我遇到的教程都没有很好地解释这一点。

奇怪的是,如果我等待b和c终止,代码就会工作。这是输出

  • 启动过程A,PID:27457
  • Forked b说fd[0]是3,fd[1]是4
  • Forked c说fd[0]是3,fd[1]是4
  • 初始化字符串后,b表示fd[0]为0,fd[1]为0
  • 即将执行B,fd[0]为0,fd[1]为0
  • 即将执行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
  • 结束时调试fd[0]为3,fd[1]为4
  • 退出A

因此,当我们在fork中操作字符串参数时,文件描述符会更改为等于零。注意,这似乎发生在execv之前,所以我认为这是在孩子们的其他代码可能影响任何事情之前。

请注意,在使用sprintf将整数转换为字符串之前,整数本身为零。

据我所知,我并没有在任何地方直接操作数组中的整数。因此,我的最佳猜测是,不知何故,管道在某一点上被认为是关闭的,当这种情况发生时,操作系统将所有文件描述符设置为零,但我很难详细找到这一点。

我曾考虑将fd[]文件描述符数组的元素保存为单个整数,以避免指针出现问题,但我怀疑它们存储在数组中是有充分理由的。

我真的很感谢任何关于这个话题的建议!非常感谢。

代码行

strArg[4] = NULL;

足以说明所有观察到的行为。数组的大小为4,这会覆盖末尾,并可能达到fd值。

解决这个问题,如果不起作用,请重新提交您的问题。

strArg[3] = NULL;

相关内容

  • 没有找到相关文章

最新更新