weiqi7777

进击吧,linux(十四) 无名管道编程

0
阅读(1958)

 

         Linux进程和进程之间有多种通讯方式。Linux进程间通讯的主要方式有:

1、  无名管道

2、  有名管道

3、  信号

4、  消息队列

5、  共享内存

6、  信号量

7、  套接字

管道操作是比较简单的通讯方式,一个进程在管道中写入数据,另一个进程从管道中读出数据。管道包括无名管道和有名管道。前者只能用于父进程和子进程间的通信,后者可用于任意两个进程之间。

无名管道的操作,其实就是对文件的操作。无名管道一旦创建完成后,我们可以认为linux自动创建了两个文件,一个文件对应无名管道的写端,一个文件对应无名管道的读端,当然这两个文件我们是看不到的。这样操作无名管道就等同于操作文件。无名管道的读端被视作一个文件,无名管脚的写端也被视作一个文件。写管道对写端文件进行写,读管道对读端文件进行读。管道文件和普通文件的区别是管道文件读取数据后,数据就从管道文件中消失了。普通文件读取后,数据依然还是在文件中的。

以下是无名管道通信的示意图。

clip_image002

首先在内核中创建一个无名管道,将父进程或者子进程分别对应上读端或者写端。对于发数据的进程,就往管道写端中写数据,对于读数据的进程,就从管道读端中读数据。

同样,无名操作也是由函数操作。

主要要学习的函数是创建无名管道

5.1 创建无名管道

5.1.1 函数名

   pipe

5.1.2 函数原形

   int pipe(int pipefd[2])

5.1.3 函数功能

   创建无名管道

5.1.4 所属头文件

   <unistd.h>

5.1.5 返回值

   成功: 0

   失败: -1

5.1.6 参数说明

   pipefd[2]:返回读端和写端的文件的文件描述符

         pipefd[0]: 无名管道的读端的文件描述符

         pipefd[1]: 无名管道的写端的文件描述符

无名管道创建后,会得到两个文件描述符,对应无名管道的读端和写端。那写数据和读数据就比较简单了,参照之前学习的文件操作的函数。使用read,write,close等函数来对无名管道操作即可。

以下是代码:

clip_image004

代码也比较简单,首先使用pipe创建无名管道,得到无名管道的读端和写端的文件描述符。然后使用fork创建子进程,因为无名管道只能是父子进程间数据通信。

在父进程中,使用pipefd[1]文件描述符,对应无名管道的写端,使用write函数,将数据写入到写端文件中。然后等待子进程读取数据,在关闭写端文件。

在子进程中,使用pipefd[0]文件描述符,对应无名管道的读端,使用read函数,将无名管道的数据读入,然后再关闭读端文件。

运行结果:

clip_image005

可见,无名管道写入数据和读取数据成功。

使用无名管道,要注意要在fork创建子进程前,创建无名管道,这样父子进程看到的管道才是同一个,操作的也是同一个。如果是在fork创建子进程后,创建无名管道,那就是父子进程各自创建一个管道,就实现不了通信了。