c管道读取字符串为空

时间:2015-11-17 14:31:53

标签: c string pipe fork

我只想创建2个新的forks(子进程),他们将名称后续。首先,他们需要在管道中使用一些字符串来检查某些东西。我们来看看代码:

char myname[] = "ALOAA";

int main ()
{

    int fds[2];
    pid_t pid;
    pipe(fds);
    pid = fork();

    if(pid == 0)
    {
        strcpy(myname, "first");
    }
    else
    {
        pid = fork();
        if(pid == 0)
        {
            strcpy(myname, "second");
        }
    }




    if(strcmp(myname, "ALOAA") != 0)
    {

        char    readbuffer[1025];

        int i;
        for (i = 0; i < 2 ; i++)
        {
            //printf("%s\n", myname);
            close(fds[0]);
            write(fds[1], myname, strlen(myname));
            while(1)
            {
                close(fds[1]);
                int n = read(fds[0], readbuffer, 1024);
                readbuffer[n] = 0;
                printf("%s-alihan\n", readbuffer);
                if(readbuffer != myname)
                    break;
                sleep(1);
            }
            //printf("%s\n", myname);
        }



    }




    return 0;

}

所以第一个进程会将她的名字写入管道。然后,将检查管道中是否有新的字符串。第二个也一样。但是我从read()函数得到了空字符串。所以它打印就像那样

-alihan
-alihan

我无法解决问题。

1 个答案:

答案 0 :(得分:0)

  

但是我从read()函数中获取了空字符串[...]我无法解决问题。

@MikeCAT在评论中发现了这个问题,即每个孩子在尝试阅读之前关闭fds[0]。没有其他文件被分配相同的FD,因此读取失败。你没有测试失败。

不测试读取失败是一个重大问题,因为您的程序不仅无法识别它 - 因此它会显示未定义的行为。出现(至少)两个原因:

  1. read()将通过返回-1表示失败,并且您的程序将通过尝试越界写入(readbuffer[-1])来响应。

  2. 如果我们忽略由(1)产生的UB,我们仍然让程序从完全未初始化的数组readbuffer读取(因为read()调用和赋值都不会设置该数组中任何元素的值。)

  3. 总的来说,你需要学习检查库函数调用的返回值是否存在错误条件的规则,至少在出错的地方(对于大多数调用来说都是重要的)。例如,您对pipe()fork()write()的使用也会出现此问题。在某些情况下,您希望检查printf() - 族函数的返回值,并且通常要检查输入函数的返回值 - 不只是read(),而是scanf(),{ {1}}等等。

    暂时,您对fgets()read()的使用不正确。你犯了一个常见的错误:假设(成功时)write()将可靠地写入指定的所有字节,并且write()将读取已写入的所有字节,直到指定的缓冲区大小。虽然这通常适用于通过管道交换短消息,但无法保证。通常,read()可能只执行部分写入,write()可能只执行部分读取,原因不明,不可预测。

    要成功写入,通常必须准备好在循环中重复read()次调用,使用返回值来确定开始下一次写入的位置(或是否)。要成功读取完整的消息,通常必须准备好类似于循环中重复write()调用,直到已将所需的字节数读入缓冲区,或者直到满足某些其他终止条件,例如结束正在联系的文件。我认为不会因为许多形式需要提前知道要读取的字节数而丢失。