[OS] 进程间通信--管道

管道单向的、先进先出的、无结构的、固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起。写进程在管道的尾端写入数据,读进程在管道的首端读出数据。数据读出后将从管道中移走,其它读进程都不能再读到这些数据。管道提供了简单的流控制机制。进程试图读空管道时,在数据写入管道前,进程将一直阻塞。同样,管道已经满时,进程再试图写管道,在其它进程从管道中移走数据之前,写进程将一直处于阻塞状态。
管道主要用于不同进程间通信。

下面介绍管道的使用方法:

管道创建:

1 #include <unistd.h>
2 int pipe(int fd[2]);

它接收一个参数,也就是包括两个整数的数组。如果系统调用成功,此数组将包括管道使用的两个文件描述符。创建一个管道之后,一般情况下进程将产生一个新的进程。
系统调用:pipe();
原型:int pipe(int fd[2]);
返回值:成功返回0,失败返回-1。

fd[1]写,fd[0]读。

如下图所示,管道是在内核空间的内存中创建的。

单个进程的管道几乎没有任何用处,通常,调用pipe的进程接着调用fork,这样就创建了父子进程间的管道。

 1 #include <unistd.h>
 2 #include<stdio.h>
 3 #include<sys/types.h>
 4 #include<sys/wait.h>
 5 
 6 int main()
 7 {
 8     int fd[2];
 9     char buf[80];
10     pid_t pid;
11     pipe(fd);
12     pid = fork();
13     if(pid>0)
14     {//父进程
15         printf("Father thread
");
16         char s[]="Hello
";
17         write(fd[1],s,sizeof(s));
18         close(fd[0]);
19         close(fd[1]);
20     }
21     else if(pid==0)
22     {
23         printf("Child Thread
");
24         read(fd[0],buf,sizeof(buf));
25         printf("%s
",buf);
26         close(fd[0]);
27         close(fd[1]);
28     }
29     waitpid(pid,NULL,0);//等待子进程结束
30     return 0;
31 }

运行结果:

Father thread
Child Thread
Hello

当管道的一端关闭时:
当读一个写端关闭的管道时,则认为已经读到了数据的末尾,读函数返回的读出字节数为0;
当写一个读端关闭的管道时,向管道中写入数据的进程将收到内核传来的SIFPIPE信号,应用程序可以处理该信号,也可以忽略(默认动作则是应用程序终止)。

从管道中读取数据:
当管道的写端存在时,如果请求的字节数目大于PIPE_BUF,则返回管道中现有的数据字节数,如果请求的字节数目不大于PIPE_BUF,则返回管道中现有数据字节数(此时,管道中数据量小于请求的数据量);或者返回请求的字节数(此时,管道中数据量不小于请求的数据量)。注:PIPE_BUF在include/linux/limits.h中定义。

向管道中写入数据:
向管道中写入数据时,linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。

管道因为没有名字所以只能用于具有亲缘关系的进程,而命名管道(FIFO)则克服了这个限制。

命名管道和一般的管道基本相同,但也有一些显著的不同:
·命名管道是在文件系统中作为一个特殊的设备文件而存在的。
·不同祖先的进程之间可以通过管道共享数据。
·当共享管道的进程执行完所有的I/O操作以后,命名管道将继续保存在文件系统中以便以后使用。
·通过FIFO,不相关的进程也可以交换数据。

下面是命名管道的使用方法:

命名管道创建:

1 #include <sys/types.h>
2 #include<sys/stat.h>
3 Int mkfifo(const char * pathname, mode_t mode);

返回:成功返回0,出错返回-1。
注:一旦已经用mkfifo创建一个FIFO,就可以用open打开。一般的文件I/O函数close, read , write等都可以用于FIFO。

原文地址:https://www.cnblogs.com/lca1826/p/6538221.html