sav*_*v0h 9 c fork pipe parent-child
在下面的程序(不是我的程序,但是我修改过的程序)中,子进程对管道进行了两次写入.当我运行该程序时,我得到以下输出:
Received string: Hello, world!
This is the child process.
Run Code Online (Sandbox Code Playgroud)
如何由父进程执行的读取从管道缓冲区中捕获这两个字符串?什么(如果有的话)阻止父进程在读取第一个字符串(或第一个字符串的第一个字符串)之后假设没有其他内容可以从缓冲区中读取并退出?
有问题的计划:
int main(void)
{
int fd[2], nbytes;
pid_t childpid;
char string[] = "Hello, world!\n";
char string2[] = "This is the child process.\n";
char readbuffer[80];
pipe(fd);
if((childpid = fork()) == -1)
{
perror("fork");
return 1;
}
if(childpid == 0)
{
/* Child process closes pipe's input file descriptor */
close(fd[0]);
/* Send "string" through the output side of pipe */
write(fd[1], string, (strlen(string)));
write(fd[1], string2, (strlen(string2)+1));
return 1;
}
else
{
/* Parent process closes pipe's output file descriptor */
close(fd[1]);
/* Read in a string from the pipe */
nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
printf("Received string: %s", readbuffer);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
父级最多读取 80 个字节。因此,第一个write系统调用(也是第二个)会将第一个字符串放置在相对于管道的内核缓冲区中。系统read调用最多会读取80个字节,所以它会向内核请求数据,内核会返回缓冲区中的前80个字节的数据(所以不可能只读取字符串的第一个字符整个字符串的单次写入和 80 字节的单次阻塞读取)。
正如您所说,子级和父级之间没有同步。事实上,在我的 Linux 系统上,你的程序有时只打印第一个字符串,有时则打印两个字符串。
该问题是一个经典的竞争条件问题,有时子进程只会写入第一个字符串,然后父进程被调度,它将读取第一个字符串,然后程序将结束(或者控制权将返回到子进程之后)read, child 会将第二个字符串写入管道缓冲区,但没有人会真正读取数据)。
您应该在程序中放置一些同步函数,例如在close(fd[1]);
[...]
else
{
/* Parent process closes up output side of pipe */
close(fd[1]);
/* Synchronize parent and child */
wait(NULL);
/* Read in a string from the pipe */
nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
printf("Received string: %s", readbuffer);
}
[...]
Run Code Online (Sandbox Code Playgroud)
然后,只有当两个字符串正确放置在缓冲区中时,父级才会读取数据。
| 归档时间: |
|
| 查看次数: |
9881 次 |
| 最近记录: |