进程间通讯

1.无名管道

定义linux

           无名管道是一种特殊类型的文件,在内核空间中对应的资源便是一段内存空间,内核在这段空间以循环对列的方式临时存入一个进程发送给另外一个进程的信息,这段内核空间彻底由操做系统管理和维护,应用程序只须要,也只能经过系统调用来访它。编程

无名管道和普通的文件有很大的差别:数据结构

  • 无名管道的内核资源在通讯两进程退出后会自动释放。跟普通文件不一样。
  • 存储大量常规信息,可是编程方式,具备和普通文件同样的特色,可使用read/write等函数进行读写操做,只是注意:特殊的文件只能用文件IO操做
  •  读写的特色有必定的差别,另外,不能用lseek函数来修改当前的读写位置,由于FIFO须要知足FIFO的原则。

特色:异步

  1. 使用条件:只能用于具备亲缘关系(父子进程,兄弟进程等)的进程之间的通讯
  2. 通讯模式:半双工模式,fd[0]做为读端fd[1]做为写端
  3. 读写方式:对于它的读写采用文件IO不支持lseek函数)
  4. 读操做会阻塞(等待):在管道中无数据状况下。写操做会阻塞(等待):当管道被写满时,无名管道的大小为64K
  5. 管道破裂:管道读端关闭,再向管道中写数据时,即向管道中写入数据的进程将收到内核传来的SIGPIPE信号。

函数接口:函数

/*
 * 函数的功能:在内核空间建立一个无名管道        
 * 参数:pipefd 固定的读写端 pipefd[0]---无名管道读端,
 *                        pipefd[1]---写端
 * 返回值:成功返回0,失败-1
 */

#include <unistd.h>
int pipe(int pipefd[2]);

无名管道的4种特殊形式:ui

  1. 阻塞的方式读无名管道:spa

    若是当前没有进程(包括当前进程)访问写端读操做当即返回,管道中无数据:当即返回0操作系统

    注意:若是写端关闭,而且管道中实现没有数据的话,读端没有任何意义。code

  2. 以阻塞的方式读无名管道,若是某个进程(包括当前进程)能够访问写端,管道端阻塞(等待)接口

    注意:读写端打开,当前管道中没有数据,阻塞等待。

  3. 若是以阻塞的方式写无名管道,若是没有某个进程(包括当前进程)能够访问读端,写操做会收到SIGPIPE信号,write函数返回-1,若是当前有某进程能够访问读端,且管道中有空间,则写入成功。

  4. 若是以阻塞的方式写无名管道,若是当前管道已经满,则阻塞等待当前进程,若是有多个进程试图写,当进程读管道唤醒写操做时 ,唤醒哪一个进程未知,须要多个进程同时写入时,须要相应的避免竞争机制。

    注意:无名管道只有全部进程都结束的时候,管道内的资源才彻底释放,不然一直存在
     

2.有名管道

 定义:有名管道:有本身的名字,可是有名管道名称保存在磁盘上,可是内容保存在内核中,有名管道和普通的文件同样具备磁盘存放路径,文件的权限和其余的属性信息,可是有名管道和普通文件又有区别,有名管道没有在磁盘上存真正的信息,而是在内存中存放,2个进程结束后自动丢失,通讯结束后有名管道的文件路径自己存在,这是和无名管道区别的地方。

特色:

  1. 有名管道可使互不相关的两个进程互相通讯。
  2. 有名管道能够经过路径名来指出,而且在文件系统中可见。
  3. 读写方式:对于它的读写采用文件IO(不支持lseek函数)
  4. 其它与无名管道同样
  5. 有名管道读端写端不固定。一段读,另外一端写。固然某一端既能够读也能够写,要用父子进程实现。

函数接口:

/*
 * 函数的功能:建立一个有名管道
 * 参数:pathname 有名管道的路径加名称
 *      mode 打开权限 0664
 *      mode & ~umask
 * 返回值:成功返回0,失败-1
 */
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);

有名管道的4种特殊形式:

  1. 若是但愿以写的方式打开管道,则须要另外一进程以读的方式打开管道。即若是以某种方式打开有名管道,则系统将阻塞进程,直到另外一个进程(包括本身)以另外一种方式打开该管道后才会继续运行,显然一个进程能够经过可读可写的方式打开管道,当前进程充满了读写2个身份,此时进程入会阻塞。
  2. 两进程已经彻底打开管道,阻塞读操做,无数据,阻塞读,有数据,读出来
  3. 两进程已经完成打开管道的操做,阻塞写操做,管道中没空间,阻塞,有空间写入,写满阻塞。
  4. 两进程已经彻底打开管道操做,中途其中一个进程退出,未退出一端是写操做,将返回SIGPIPE信号,未退出一端是读操做,读操做将再也不阻塞,直接返回0(父子进程)

3.信号---进程间惟一的一种异步通讯方式

函数接口:

/*
 * 函数的功能:向执行的进程发送信号
 * 参数:pid 执行的进程号
 *      pid <-1 发送当前的进程|id|等于调用进程组id下的任意一个子进程
 *      pid=-1 发送给全部的进程,除了init(1号进程)
 *      pid =0 发送给同组下的全部进程
 *      pid >0 发送给指定的进程
 *      sig 指定的信号(kill -l)
 * 返回值:成功返回0,失败-1;
 */
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);

        

4. 消息队列

  消息对列是消息的链式队列,消息队列的FIFO原则仅仅适用于同类型的消息,在消息队列进行以下规定,不一样系统的限制值能够经过msgctl函数使用IPC_INFO参数得到,注意不一样的linux版本此值不一样。消息队列即知足的管道的先进先出的原则,用户又能够按照指定的消息类型去存取,消息队列存在于内存当中,在使用消息队列的时候,经过指定消息对列的标识符。默认的状况下:整个系统最多容许有16个消息队列。每一个消息对列最大为16384字节 消息对列中每一个消息最大为8192字节。
消息对列的使用步骤:

  1. ftok----使外部不相关的进程创建联系
  2. msgget---建立一个消息队列
  3. msgctl---删除消息队列
  4. msgsnd--发送消息
  5. msgrcv----接收消息

5. 共享内存-----进程间最高效的通讯方式

定义:共享内存进程间通讯机制主要用于实现进程间的大量数据的传输。共享内存是在内存中单独开辟的一段内存空间,这段内存空间有本身特有的数据结构,包括访问权限大小最近的访问的时间。

两个进程在使用此共享内存空间以前,须要在进程地址空间和共享内存空间之间创建联系,即将共享内存空间挂载到进程中。在使用共享内存进行数据存取时,有必要使用二元信号量来同步两个进程以实现对共享内存的写操做。

/*
 * 函数的功能:建立或者打开一个共享内存
 * 参数:key 外部键值
 * size 设置共享内存大小
 * shmflg 标志位 IPC_CRAT   (flag)
                IPC_EXCL    0664
 * 返回值:成功返回共享内存的标识符  失败:-1
 */
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);

/*
 * 函数的功能:将共享内存映射到各自进程空间
 * 参数:shmid 进程标识符
 * shmaddr 映射后进程的地址
 * shmflg 0 可读可写
 * SHM_RDONLY 只读
 * 返回值:成功返回映射后地址,失败NULL===(void *)-1
 */
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);

/*
 * 函数的功能:解除映射
 * 参数:shmaddr 映射的地址
 * 返回值:成功返回0,失败-1       
 */
int shmdt(const void *shmaddr);

/* 
 * 函数的功能:删除共享内存
 * 参数:shmid 共享内存的标识符
 * cmd IPC_STAT :获得共享内存的状态,把共享内存的shmid_ds结构复制到buf中.
 * IPC_SET :改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内.
 * IPC_RMID :删除这片共享内存。
 * buf 共享内存的属性信息 NULL
 * 返回值:IPC_RMID 成功返回0,失败-1
*/
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
 

6.信号灯集----同步互斥机制

相关文章
相关标签/搜索