1、进程间通信主要有四种形式:管道(pipe)、消息队列、信号量、共享内存。
2、首先说一下最基本的管道,管道分:命名管道和匿名管道;
3、匿名管道主要用在具有亲缘关系的进程之间通信,调用pipe函数创建匿名管道,一端用于写另一端用于读,当进程之间在进行读写的时候会发生阻塞,即当写端没有再向管道里写数据时,读端读完最后一个数据后就会阻塞,而且匿名管道是半双工的,意思是在同一时刻只能进行单项通信,
4、由于匿名管道缺点所以就提出命名管道,命名管道的实现是创建一个实实在在存在的文件,然后不同的进程可以往里写数据也可以从里读数据,进程之间可以不具有亲缘关系,创建命名管道的函数有两个:mknode和mkfifo,但用得比较多的是mkfifo。
5、刚才说的是最基本的进程间通信的管道,现在说一下system V 标准的消息队列,消息队列也打开了一个文件,一端用于写一端用于读,但是它和命名管道不同之处是命名管道是基于字节流,而消息队列是基于数据报的传输,它们都有一个共同的缺点是传输的数据都有最大值的限制,消息队列的实现主要有msgget(创建线性队列)、msgsend(发送消息队列)、msgrecv(接受消息队列)、msgctl(设置消息队列属性)这四个函数来完成的。
6、第二个进程间通信是信号量:信号量其实本质就是一把数据锁,它并没事实实在在的传输数据,只是给传输的数据上锁,然后让它们安全可靠的输出而已,它是实现主要靠:semget(创建信号量)、semop(主要为了加锁和解锁)、semctl(设置信号量属性),里面主要有一个P、V操作,P操作:如果有资源,那么资源数减一,给操作这块资源的操作上锁,V操作:如果有资源,资源数加一,等待被访问。当请求不到资源是时候会阻塞式的等待。
7、第三个要说的进程间通信是共享内存:它是通过打开一个文件,让所有的进程都共享这个文件,从而时间进程间通信。它其实会出现一个安全性问题,就是没有同步机制,如果在多线程访问的话就很可能出安全性问题,所以一般共享内存通常会和信号量搭配使用,它主要实现靠shmget(创建共享内存)、shmat(刚创建的共享内存还不能被所有进程访问,必须调用shmat才可以被进程访问)、shmdt(让访问共享内存的进程分离)、shmctl(对共享内存的属性进行设置),
既然共享内存有安全性问题为什么还有用它呢???因为共享内存的通信很快,而且它的接口函数很简单,只要加上同步机制在安全方面就没问题了。
8、说到安全性问题,这里说一下为什么不加锁的话就不安全了,因为当程序需要改变一个数的时候,它的操作是这样的:先去内存里读数据到寄存器里,然后从寄存器里把数据取出来,修改后在先写会寄存器,然后在写会内存。试想一下,当对一个数进行加一的时候,因为加一的操作不是原子性的,所以当把数据加一了后写会寄存器时刚好进程或者线程被切换出去了,而切换出去的进程或线程刚好要用到以为被加后的数据,其实没加,所以最后得到是值不是预期的值。
9、以上这些就是我所掌握的进程间通信。