先决条件: I/O系统调用
从概念上讲,管道是两个进程之间的连接,因此一个进程的标准输出成为另一个进程的标准输入。在UNIX操作系统中,管道用于相关进程之间的通信(进程间通信)。
- 管道是单向通信,也就是说,我们可以使用一个管道,一个进程写入管道,另一个进程读取管道。它会打开一个管道,这是主内存中被视为 “虚拟文件” .
- 管道可以被创建进程及其所有子进程用于读写。一个进程可以写入这个“虚拟文件”或管道,另一个相关进程可以从中读取。
- 如果某个进程试图在某个内容写入管道之前读取,则该进程将暂停,直到某个内容被写入。
- 管道系统调用在进程的open file表中查找前两个可用位置,并为管道的读写端分配它们。
int pipe(int fds[2]); Parameters : fd[0] will be the fd(file descriptor) for the read end of pipe. fd[1] will be the fd for the write end of pipe. Returns : 0 on Success. -1 on error.
管道的行为 先进先出 (先进先出),管道的行为就像 队列 数据结构。这里的读写大小不必匹配。我们可以写作 512 但在管道中,我们一次只能读取1个字节。
// C program to illustrate
// pipe system call in C
#include <stdio.h>
#include <unistd.h>
#define MSGSIZE 16
char
* msg1 =
"hello, world #1"
;
char
* msg2 =
"hello, world #2"
;
char
* msg3 =
"hello, world #3"
;
int
main()
{
char
inbuf[MSGSIZE];
int
p[2], i;
if
(pipe(p) < 0)
exit
(1);
/* continued */
/* write pipe */
write(p[1], msg1, MSGSIZE);
write(p[1], msg2, MSGSIZE);
write(p[1], msg3, MSGSIZE);
for
(i = 0; i < 3; i++) {
/* read pipe */
read(p[0], inbuf, MSGSIZE);
printf
(
"% s"
, inbuf);
}
return
0;
}
输出:
hello, world #1 hello, world #2 hello, world #3
父母和孩子共享一个管道
当我们使用 叉 在任何进程中,文件描述符在子进程和父进程之间保持打开状态。如果我们在创建管道后调用fork,那么父级和子级可以通过管道进行通信。
以下程序的输出。
// C program to illustrate
// pipe system call in C
// shared by Parent and Child
#include <stdio.h>
#include <unistd.h>
#define MSGSIZE 16
char
* msg1 =
"hello, world #1"
;
char
* msg2 =
"hello, world #2"
;
char
* msg3 =
"hello, world #3"
;
int
main()
{
char
inbuf[MSGSIZE];
int
p[2], pid, nbytes;
if
(pipe(p) < 0)
exit
(1);
/* continued */
if
((pid = fork()) > 0) {
write(p[1], msg1, MSGSIZE);
write(p[1], msg2, MSGSIZE);
write(p[1], msg3, MSGSIZE);
// Adding this line will
// not hang the program
// close(p[1]);
wait(NULL);
}
else
{
// Adding this line will
// not hang the program
// close(p[1]);
while
((nbytes = read(p[0], inbuf, MSGSIZE)) > 0)
printf
(
"% s"
, inbuf);
if
(nbytes != 0)
exit
(2);
printf
(
"Finished reading"
);
}
return
0;
}
输出:
hello world, #1 hello world, #2 hello world, #3 (hangs) //program does not terminate but hangs
在这里,在完成读/写后的代码中,父进程和子进程都被阻塞,而不是终止进程,这就是程序挂起的原因。发生这种情况的原因是,读取系统调用获取的数据量与它请求的数据量或管道拥有的数据量相同,以较小者为准。
- 如果管道是空的,我们调用读取系统调用,那么管道上的读取将返回 EOF(返回值0) 如果没有进程打开写端。
- 如果其他进程打开了管道进行写入,read将阻塞,以等待新的数据,因此此代码输出将挂起,因为此时写入结束父进程,而子进程也不会关闭。
有关父级和子级共享管道的更多详细信息,请参阅 C程序演示fork()和pipe() . 本文由 卡丹·帕特尔 .如果你喜欢GeekSforgek,并且想贡献自己的力量,你也可以使用 贡献极客。组织 或者把你的文章寄到contribute@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。
如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。