Linux进程间通信IPC

1. 管道pipe (无名管道)

本质是一个伪文件,实际为内核缓冲区。由两个文件描述符引用,一个表示读端,一个表示写端,数据单向流动。

原理:管道实为内核使用环形队列机制,借助内核缓冲区(4K)实现。

磁盘读写的单位是一个扇区,大小为512byte,即文件最小为512byte。

局限性:数据自己读不能自己写;数据一旦被读走便不在管道中,不可反复读取;由于管道采用(单向)半双工通信方式,所以数据只能在一个方向上流动;只能在有公共祖先的进程间使用管道(有血缘关系)

int pipe(int pipefd[2]); --> 创建一个管道,将打开的两个文件描述符(对应管道的两端)放入参数pipefd中。

返回值:成功返回0, 失败返回-1.

pipefd[0] --> 读; pipefd[1] --> 写

读管道:管道中有数据时返回实际读到的字节数;管道中无数据时,如果写端全关闭则返回0,若仍有写端打开则阻塞等待

写管道:读端全关闭则进程异常终止(SIGPIPE信号);有读端打开时,若管道未满则返回写入字节数,管道已满时阻塞。

2. fifo(命名管道):提供了一个路径名与之关联,以 FIFO 的文件形式存在于文件系统中,这样,即使与 FIFO 的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过 FIFO 相互通信,因此,通过 FIFO 不相关的进程也能交换数据。

fifo和pipe的不同之处:

(1)、FIFO 在文件系统中作为一个特殊的文件而存在,但 FIFO 中的内容却存放在内存中。
(2)、当使用 FIFO 的进程退出后,FIFO 文件将继续保存在文件系统中以便以后使用。
(3)、FIFO 有名字,不相关的进程可以通过打开命名管道进行通信。

int mkfifo(const char* pathname, mode_t mode);

 pathname: 普通的路径名,也就是创建后 FIFO 的名字。
mode: 文件的权限,与打开普通文件的 open() 函数中的 mode 参数相同

fifo在open时默认阻塞。open() 以只读方式打开 FIFO 时,要阻塞到某个进程为写而打开此 FIFO open() 以只写方式打开 FIFO时,要阻塞到某个进程为读而打开此 FIFO。 简单一句话,只读等着只写,只写等着只读,只有两个都执行到,才会往下执行。如果不想在open时阻塞,可以以可读可写的方式open。

如果FIFO中没有数据,而且有写端打开时,read函数会阻塞,和无名管道相同。如果写进程先退出了,就算命名管道内没有数据,read函数也会不阻塞直接返回0;若写进程又重新运行,则read函数恢复阻塞;

若读进程先退出后,写进程向FIFO中写数据时,写进程会收到SIGPIPE信号退出。

注:一个进程mkfifo,不能同时mkfifo,不然会重复。

程序不能以O_RDWR(读写)模式打开FIFO文件进行读写操作,而其行为也未明确定义,因为如一个管道以读/写方式打开,进程就会读回自己的输出,同时我们通常使用FIFO只是为了单向的数据传递。

就是传递给open调用的是FIFO的路径名,而不是正常的文件。(如:const char *fifo_name = "/tmp/my_fifo"; )。

第二个参数中的选项O_NONBLOCK,选项O_NONBLOCK表示非阻塞,加上这个选项后,表示open调用是非阻塞的,如果没有这个选项,则表示open调用是阻塞的。

阻塞问题:

对于以只读方式(O_RDONLY)打开的FIFO文件,如果open调用是阻塞的(即第二个参数为O_RDONLY),除非有一个进程以写方式打开同一个FIFO,否则它不会返回;如果open调用是非阻塞的的(即第二个参数为O_RDONLY | O_NONBLOCK),则即使没有其他进程以写方式打开同一个FIFO文件,open调用将成功并立即返回

对于以只写方式(O_WRONLY)打开的FIFO文件,如果open调用是阻塞的(即第二个参数为O_WRONLY),open调用将被阻塞,直到有一个进程以只读方式打开同一个FIFO文件为止;如果open调用是非阻塞的(即第二个参数为O_WRONLY | O_NONBLOCK),open总会立即返回,但如果没有其他进程以只读方式打开同一个FIFO文件,open调用将返回-1,并且FIFO也不会被打开

1 #include <stdio.h>                                                                                        2 #include <sys/types.h>
  3 #include <sys/stat.h>
  4 #include <stdlib.h>
  5 #include <unistd.h>
  6 #include <fcntl.h>
  7
  8 int main()
  9 {
 10         int ret = mkfifo("myFifo", 0644);
 11         if (ret < 0)
 12         {
 13                 perror("mkfifo");
 14                 exit(1);
 15         }
 16         printf("Before open.\n");
 17         int fd;
 18         if ((fd = open("myFifo", O_RDONLY)) < 0)
 19         {
 20                 perror("open");
 21                 exit(1);
 22         }
 23         printf("After open.\n");
 24         printf("Going to read.\n");
 25         char buf[1024] = { 0 };
 26         if ((ret = read(fd, buf, sizeof(buf))) < 0)
 27         {
 28                 perror("read");
 29                 exit(1);
 30         }
 31         printf("Read over, %s\n", buf);
 32
 33         return 0;
 34 }
1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/stat.h>
  4 #include <fcntl.h>
  5 #include <unistd.h>
  6 #include <string.h>
  7 #include <stdlib.h>
  8
  9 int main()
 10 {
 11         if (access("myFifo", W_OK) == -1)
 12         {
 13                 printf("file not exists.\n");
 14                 exit(1);
 15         }
 16         printf("Before open.\n");
 17         int fd, ret;                                                                                    
 18         if ((fd = open("myFifo", O_WRONLY)) < 0)
 19         {
 20                 perror("open");
 21                 exit(1);
 22         }
 23         printf("After open.\n");
 24
 25         printf("Before write.\n");
 26         char* buf = "Hello fifo";
 27         if ((ret = write(fd, buf, strlen(buf))) < 0)
 28         {
 29                 perror("write");
 30                 exit(1);
 31         }
 32         close(fd);
 33
 34         return 0;
 35 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值