【Linux】——进程间的通信之命名管道

前面博客我们讲述了进程间的一种通讯方式 匿名管道 今天我们来讲一下进程间的另一种通讯方式 命名管道

命名管道

1.什么是命名管道

  • 匿名管道是在缓存中开辟的输出和输入文件流的空间,只能用于父子关系的进程之间。因为父子进程的输入和输出文件描述符是一致的。
  • 命名管道是一种实际存在的FIFO文件,称作 管道文件,属于一种特殊类型的文件,用于不同进程之间,命名管道进程间打开同一个FIFO文件,进行数据传递。
  • 我们可以像普通文件一样操作FIFO文件。
  • 不同进程,引用同一个FIFO文件,进行数据传递

2.创建命名管道

mkfifo函数:创建一个命名管道

int mkfifo(const char *filename,mode_t mode);
  • filename:指定FIFO文件的名称
  • mode:指定文件的读写权限
  • man 手册查看mkfifo的功能
    mkfifo
  • 我们试着用一下我们的mkfifo命令,可以看到他创建了一个和普通文件不同的文件,文件类型是p,也就是我们说的管道文件。
    FIFO
  • 接下来我们往管道中写点东西,并且再起一个终端,看看终端2能否从管道中读取刚刚终端1往管道中写的数据在这里插入图片描述
  • 显然我们可以看到我们的实验是成功的,终端2成功读取了终端1往FIFO管道中写入的数据,而且进程在往FIFO中写入数据之后,若是无人读取的话就会阻塞,一直等到有进程来读取才会结束,就是我们看到的进程卡住了

3.访问命名管道

打开FIFO文件有四种方式:

open(const char *filename,O_RDONLY);
open(const char *filename,O_RDONLY|O_NONBLOCK);
open(const char *filename,O_WRONLY);
open(const char *filename,O_WRONLY|O_NONBLOCK);

需要注意的是,不能以O_RDWR模式打开FIFO文件
因为这样一个进程写入的数据会被该进程读取,FIFO一般只用做单向的数据传递。

  • open函数的第二个参数,表示是读管道,还是写管道。
  • O_NONBLOCK表示FIFO管道的读写是非阻塞的,默认的话,是阻塞的。

那么何为阻塞呢?

  • 一个进程写模式打开管道的时候,必须有另一个进程以读模式打开;

  • 或读模式的时候,必须有另一个进程写写模式打开,否则该进程open函数阻塞,直到满足以上关系。

  • 非阻塞,意味着open函数会立即返回,若没有其他进程以只读方式打开,open返回-1,并且FIFO也不会被打开。

4.匿名管道和命名管道的区别

  • 匿名管道有pipe函数创建并打开
  • 命名管道用mkfifo创建,由open打开
  • FIFO(命名管道)和pipe(匿名管道)之间唯一的区别就是他们在创建和打开的方式不同,一旦创建和打开这些工作完成,他们就具有相同的意义。

接下来举个栗子来看看命名管道的具体使用

用命名管道实现server和client的通信

  • 首先我们来写server.c 文件
    在这里插入图片描述
  • 再编写client.c文件,其实二者差别不大,为了能节省时间我们直接通过命令cat server.c > client.c将server.c文件中的内容重定向至client.c中,再进行修改即可
    client
  • 编写Mikefile文件
    Makefile
  • 最后起两个终端进行测试,一个终端运行server,另一个终端运行client,我们可以发现两个进程之间就实现了通信,这就是命名管道的使用。
    client和server

总结:命名管道其实比起匿名要更好理解一些,除了创建和打开的方式和匿名管道不同,其他使用上都是一样的,命名管道一样有着管道的所有特性。

发布了167 篇原创文章 · 获赞 175 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/chenxiyuehh/article/details/91047082