1.进程间通信方式概述
进程间通信是在不同进程之间传播或者交换信息。
进程间通信方法有:管道(无名和有名管道),消息队列,信号量,共享内存,信号,套接字等
进程间通信的目的:
1、数据传输,2、共享数据,3、通知事件,4、资源共享,5、进程控制
2.管道通信
管道有无名管道和有名管道,无名管道是适用于父子进程或者兄弟进程之间,进程之间存在联系的,可以用管道。 有名管道,不仅父子,兄弟进程可以使用,没有关系的两个进程也可以使用,有名管道克服了管道没有名字的限制。所以才可以字无关系的进程之间建立通信。传递的数据是无格式字节流。
无名管道是单向的先进先出(与队列相似),数据只能从一个方向流入,另一个方向流出。属于 半双工通信,就是在同一时刻不能两个同时在传数据,只能一个一个来。只能用在父子进程或者兄弟进程之间。(有亲缘关系的进程)
管道属于一个特殊的系统文件,也可以说是特殊的设备文件。管道存在于内核之中,是由进程创建的,需要先创建子进程在创建管道,才会使父子之间可以通过管道通信,不然子进程不会继承文件描述符。管道的读写时分开的,读在管道头(fd[0]),写在管道尾(fd[1]),管道创建成功,头部和尾部用文件描述符来表示。创建成功返回值是0,失败是-1;错误原因存在于errno中
管道中的数据读出后就被从管道中删除,其他读进程将不能再读到这些数据。管道提供了简单的流控制机制。
读的时候,如果管道是空的,则阻塞等待。
写的时候,如果管道是满的,则阻塞等待。
当管道写端关闭之后,写入的数据将一直存在,直到被读出为止。
在向管道写入数据时,至少应该存在某个进程,其中管道读端没有关闭,否则会出现管道破裂,进程会收到SIGPIPE信号,默认动作为终止进程。
pipe() 函数包含在 unistd.h文件中
有名管道(命名管道)
mkfifo()会依第一个参数建立特殊的FIFO文件,该文件必须不存在,mode是描述该文件的权限。
(1)当使用O_NONBLOCK 时,打开FIFO文件来读取的操作会立即返回,但是如果没有其他进程打开FIFO文件来读取,则写入操作会返回ENXIO错误代码。
(2)当不使用O_NONBLOCK 时,打开FIFO文件来读取的操作会等到其他进程打开FIFO文件写入才能正常返回,同样的,打开FIFO文件来写入的操作会等到其他进程打开FIFO文件进行读取后才能正常返回。
返回值:成功返回 0 ,失败返回 -1;
3.信号通信
信号通信时唯一异步的方式
信号事件的发生来源:硬件来源和软件来源。最常用发送信号的系统函数时kill,raise,alarm,setitimer,sigqueue。
kill 发出的信号有
SIGINT :是中断(ctrl + c)
信号的处理方式有三种:
1.忽略信号 (有两种信号不可以被忽略,SIGKILL SIGSTOP)提供向超级用户一种终止或者停止进程的方法。
2.捕捉信号 (执行用户希望的动作)
3.执行默认操作(大多数默认动作是终止进程)
alarm
pause
发送信号后就要处理信号
信号的处理主要有两种 signal函数 和 使用信号集函数组
4.共享内存
共享内存是被多个进程共享的一部分物理内存,共享内存是进程间共享数据的一种最快的方法。
共享内存在内核中,有两种方法
一种是在内存中实实在在的分配内存
一种是由内核创建同名的设备文件来处理
key是共享内存的键值,有三种设置方法
一是IPC_PRIVATE 告诉内核共享内存创建后自己用,由系统创建给键值
二是自己设置键值
三是给定路径让系统给他一个键值
ket_t ftok(char *pathname, char proj)
size:是指定大小,分配空间以页为单位。
shmflg:不存在就创建这块空间。
第二个参数是不知道地址是哪一个,系统给我找,函数返回值告诉地址在哪里。失败是-1(转为指针类型)
flag = 0时表示共享内存可读可写
5.消息队列
6.信号量