现在在Linux系统下进程之间的通信方式有如下几种:管道通信(有名管道、无名管道),信号通信,消息队列,
共享内存,信号灯以及套接字(socket)通信。socket套接字通信主要涉及的是两台主机之间的网络通信,其它通
信机制主要用于一台主机之间的不同进程之间。
通信的方式:
单工模式:数据只能单向的发送
双工模式:半双工,发送数据可以双向,但是不能同时进行,某一时刻只能发送或者接收。
全双工,发送数据可以双向,并且可以同时进行,某一时刻可以发送和接收数据。
一、管道通信
管道是Linux下进程间通信方式的一种,管道类似于文件,但是与文件不同点在于:管道里的数据被读取之后就
不存在了,而文件里的数据被读取之后依然存在。Linux管道主要包括两种:无名管道和有名管道。
管道读写时需要注意:
1)读端未打开时,写阻塞;读写端都打开时,无数据,读阻塞。
2)关闭读端,写阻塞;关闭写端,读不会阻塞,会一直返回0。
1、无名管道
(1)无名管道具有以下特点:
1、无名管道只能用于具有亲缘关系的进程之间的通信(即父子进程或兄弟进程之间的通信)。
2、无名管道是一个单工的通信模式,数据只能单向发送,数据只能从管道的一段写入,从管道的另一端读取。
即管道有固定的读端和写端。
3、无名管道不存在与任何的文件系统中,它只存在于内存中。可以看做为一种特殊的文件,可以利用read和write
函数进行读和写。
特点分析:
1)无名管道不存在与文件系统中,因此无法用open等函数打开无名管道获取无名管道的文件描述符。只可以通过
fork函数建立子进程,从父进程中获取到无名管道的文件描述符。
2)无名管道是单工模式,有固定的读端和写端,且在任意时刻,是能读或写。
无名管道创建之后,管道的读写端文件描述符默认是打开的。
(2)pipe函数
函数原型:int pipe(int fd[2]);
函数参数:fd 包含两个元素的整型数组,存放管道对应的文件描述符。
返回值:=0 成功创建无名管道
=-1 创建无名管道失败
说明:无名管道是基于文件描述符的通信方式。当一个无名管道建立时,它会创建两个文件描述符:fd[0]和fd[1],
其中fd[0]固定用于读管道,而fd[1]固定用于写管道。
**注意:
需要注意的是应该现在父进程中调用pipe函数创建无名管道,然后在调用fork函数创建子进程。如果pipe与
fork函数的调用顺序相反,则子进程无法从父进程中继承到无名管道。
例1:通过无名管道,实现父子进程之间的通讯。父进程向无名管道中写入数据,子进程从无名管道中读取数据。
2、有名管道
(1)有名管道的特点
1、它可以使互不相干的两个进程之间实现通信。
2、该管道可以通过路径名来指出,并且有名管道值文件系统中是可见的,有名管道的类型是P,但是数据为0,数据
只存在于内存中。
3、有名管道严格的遵守先进先出的规则,因此有名管道不支持lseek等文件操作。
4、可以实现双工通信,但是需要两个管道文件。
有名管道创建成功之后默认是关闭的,可以通过open、write、read等函数对有名管道进行操作。对于有名
管道的操作要注意以下几点:
1、当读端未打开时,写阻塞;因此有名管道的操作应该先打开读端。
2、读写段都打开时,如果没有数据则读阻塞;如果无空间,则写阻塞。
3、如果先关闭读端,则写端阻塞;如果先关闭写端,则读端不会阻塞,会一直返回0。因此应该先关闭读端。
==》有名管道应该注意优先打开或关闭读管道端。
2、mkfifo函数
函数原型:int mkfifo(const char *filename, mode_t mode);
函数参数:filename 创建有名管道的管道名(文件名:可以是相对或绝对路径)
mode 创建的管道的访问权限
返回值:=0 表示有名管道创建成功;
=-1 表示创建失败。
FIFO出错的相关信息:
EEXIST 参数filename所指定的文件已经存在
EACCESS 参数filename所指定的目录路径无可执行权限
ENOENT 参数filename包含的文件不存在
================================================================
例2:通过有名管道实现两个进程之间的通信,一个写管道,一个读管道。
1、源代码如下:
2、先运行读进程程序,再运行写进程程序:
3、读写管道此时都打开了:有数据,则读取;无数据,读阻塞等待。
4、如果先运行写管道进程,管道阻塞,数据不能写入管道,直至读管道打开。
3、先退出写管道程序,写端关闭:
在有名管道中应该注意:优先打开或者关闭读管道端口。