一 Linux进程间通信( 三 )

运行结果如下:

一 Linux进程间通信

文章插图
匿名管道读写规则
一 Linux进程间通信

文章插图
读写规则总结:
  • 当没有数据可读时O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止 。O_NONBLOCK enable:read调用返回-1,errno值为EAGAIN 。
  • 当管道满的时候O_NONBLOCK disable: write调用阻塞,直到有进程读走数据O_NONBLOCK enable:调用返回-1,errno值为EAGAIN
  • 如果所有管道写端对应的文件描述符被关闭,则read返回0
  • 如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE,进而可能导致write进程退出
  • 当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性
  • 当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性
注意:O_NONBLOCK是非阻塞的标志位,指定管道对我们的操作要么成功,要么立刻返回错误,不被阻塞 。
管道特点(了解)
  • 只能用于具有共同祖先的进程(具有亲缘关系的进程)之间进行通信;通常,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可应用该管道 。
  • 管道提供流式服务 。也就是你想往管道里读写多少数据是根据自身来定的
  • 一般而言,进程退出,管道释放,所以管道的生命周期随进程
  • 一般而言,内核会对管道操作进行同步与互斥
  • 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道
  • 半双工是指传输过程中同时只能向一个方向传输,一方的数据传输结束之后,另外一方再回应 。双方传输数据是不可以同时进行的
  • 全双工是指两方能同时发送和接受数据 。在这种情况下就没有拥堵的危险,数据的传输也就更快
命名管道概念:无名管道,由于没有名字,所以只能用于亲缘关系的进程通信 。为了克服这个缺点,提出了命名管道(FIFO) 。
命名管道不同于无名管道之处在于它提供了一个路径名与之关联,以FIFO的文件形式存在于文件系统中,这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信,因此,通过FIFO不相关的进程也能交换数据 。
  • FIFO在文件系统(磁盘上)中作为一个特殊文件而存在,但是FIFO中的内容却存放在内存中 。
  • 当使用FIFO的进程退出后,FIFO文件将继续保存在文件系统中以便以后使用 。
  • FIFO有名字,不相关的进程可以通过打开命名通道进行通信 。
创建命名管道1.通过命令创建命名管道
mkfifo filename
2.通过函数创建命名管道
int mkfifo(const char *pathname, mode_t mode);
功能:创建命名管道
参数:pathname:普通的路径名,也就是创建后FIFO的名字 。
?mode:文件的权限,与打开普通文件的open函数中的mode参数类似 。
返回值:成功:0 (状态码)失败:如果文件已经存在,则会出错返回-1
代码示例:
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#define FIFO "./fifo"int main(){umask(0);// 创建管道int ret = mkfifo(FIFO, 0666);if (ret == -1){perror("make fifo");exit(-1);}}运行结果如下:
一 Linux进程间通信

文章插图
上面说过,管道其实就是一种特殊的文件,管道文件大小是0,因为上面介绍过,管道文件的内容都存放在内存当中 。

经验总结扩展阅读