众所周知,在Linux的进程间通信过程中,进程通过名为“Pipe”的特殊文件相互通信。
众所周知,一个进程对该文件执行的操作为 write ,而一个进程为 read 以便彼此通信。
现在,问题是:
这些写入和读取操作是否在通信过程中并行执行(并行执行操作)?如果不是,
当其中一个进程在通信期间进入 SLEEP状态时会发生什么?它是否首先执行写入操作,以便第二个进程读取,或者直接进入休眠状态而不执行任何写入和阅读操作?
答案 0 :(得分:2)
发送过程可以写入,直到管道缓冲区已满(Linux自2.6.11以来为64k)。之后,write(2)将阻止。
接收过程将阻止,直到read(2)的数据可用。
有关管道缓冲的更详细信息,请查看https://unix.stackexchange.com/a/11954。
例如,这个程序
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int
main(int argc, char *argv[])
{
int pipefd[2];
pid_t cpid;
char wbuf[32768];
char buf[16384];
/* Initialize writer buffer with 012...89 sequence */
for (int i = 0; i < sizeof(wbuf); i++)
wbuf[i] = '0' + i % 10;
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Child reads from pipe */
close(pipefd[1]); /* Close unused write end */
while (read(pipefd[0], &buf, sizeof(buf)) > 0);
close(pipefd[0]);
_exit(EXIT_SUCCESS);
} else { /* Parent writes sequence to pipe */
close(pipefd[0]); /* Close unused read end */
for (int i = 0; i < 5; i++)
write(pipefd[1], wbuf, sizeof(wbuf));
close(pipefd[1]); /* Reader will see EOF */
wait(NULL); /* Wait for child */
exit(EXIT_SUCCESS);
}
}
使用gcc pipes.c && strace -e trace=open,close,read,write,pipe,clone -f ./a.out
:运行时,将生成以下序列
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
close(3) = 0
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\3\2\0\0\0\0\0"..., 832) = 832
close(3) = 0
pipe([3, 4]) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f32117489d0) = 21114
close(3) = 0
write(4, "01234567890123456789012345678901"..., 32768) = 32768
write(4, "01234567890123456789012345678901"..., 32768) = 32768
write(4, "01234567890123456789012345678901"..., 32768strace: Process 21114 attached
<unfinished ...>
[pid 21114] close(4) = 0
[pid 21114] read(3, "01234567890123456789012345678901"..., 16384) = 16384
[pid 21114] read(3, <unfinished ...>
[pid 21113] <... write resumed> ) = 32768
[pid 21114] <... read resumed> "45678901234567890123456789012345"..., 16384) = 16384
[pid 21113] write(4, "01234567890123456789012345678901"..., 32768 <unfinished ...>
[pid 21114] read(3, "01234567890123456789012345678901"..., 16384) = 16384
[pid 21114] read(3, <unfinished ...>
[pid 21113] <... write resumed> ) = 32768
[pid 21114] <... read resumed> "45678901234567890123456789012345"..., 16384) = 16384
[pid 21113] write(4, "01234567890123456789012345678901"..., 32768 <unfinished ...>
[pid 21114] read(3, "01234567890123456789012345678901"..., 16384) = 16384
[pid 21114] read(3, <unfinished ...>
[pid 21113] <... write resumed> ) = 32768
[pid 21114] <... read resumed> "45678901234567890123456789012345"..., 16384) = 16384
[pid 21113] close(4) = 0
[pid 21114] read(3, "01234567890123456789012345678901"..., 16384) = 16384
[pid 21114] read(3, "45678901234567890123456789012345"..., 16384) = 16384
[pid 21114] read(3, "01234567890123456789012345678901"..., 16384) = 16384
[pid 21114] read(3, "45678901234567890123456789012345"..., 16384) = 16384
[pid 21114] read(3, "", 16384) = 0
[pid 21114] close(3) = 0
[pid 21114] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=21114, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++
您会注意到读取和写入是交错的,写入和读取过程会阻塞几次,因为管道已满或者没有足够的数据可供读取。