日期:2014-05-16  浏览次数:20671 次

UNIX下进程学习之管道和消息队列

 

 

linux多进程

僵尸进程是已经终止,但没有从进程表中清除的进程。
如果子进程先于父进程终止,而父经常没有调用wait接收子进程的信息,则子进程将转化为僵尸进程,直到父进程结束。
避免僵尸进程方法
1) wait     父进程主动调用wait(或收到信号后调用)接收子进程的死亡报告,释放子进程占用的系统进程表资源.
2) 托管法   父进程先于子进程死亡,则它的所有子进程转而由init进程领养
3) 忽略SIGC(H)LD信号  当父进程忽略此信号, 即使不执行wait,子进程结束时也不会产生僵尸进程。
4) 捕获SIGC(H)LD信号  父进程捕获SIGC(H)LD信号,并在捕获函数中等待wait子进程.

守护进程
守护进程是一个在后台长期运行的进程,独立于控制终端,周期性执行某项任务.
完成一个守护进程的编写至少包含以下几项
1)后台运行          托管法实现
2)独立控制终端      setsid()
3)清楚文件创建掩码  umask(0)
4)处理信号


查询IPC对象
ipcs
删除IPAC对象
ipcrm
IPC的三种对象在UNIX都存在限制,比如消息队列最大字节数.信号量最大信数.都可以更改内核参数来改变.

 

进程间通信
进程间通信有 管道  消息队列  信号量  共享内存
管道:
无名管道:int pipe(int fildes[2])  
在UNIX中,创建无名管道的函数有pipe,popen,关闭无名管道的函数有pclose.
创建有名管mknod和mkfifo,创建有名管道函数mkfifo.
无名管道应用于父子进程,有名管道以文件的形式储存于磁盘等外部储存设备中,可在任意两个进程中应用.


消息队列
ipcs -a -q
消息队列在UNIX内核中是一个先进先出的链表结构
UNIX用msgid_s结构管理消息队列
消息队列的创建 int msgget(key_t key,int msgflag)
消息队列发送   int msgsnd(int msgid,void *msgp,int msgsz,int msgflg)
消息队列接收   int msgrcv(int msgid,void *msgp,int msgsz,long msgtype,int msgflg)
消息队列控制   int msgctl(int msgid,int cmd,struct msgid_ds *buf)

采用消息队列通信比采用管道通信具有更多的灵活性.通信的进程,不但没有血缘上的要求,也不需要进行同步处理.发送进程可以在任意时刻写入消息,也可以在接收消息之前结束执行.而使用管道,无论是无名管道还是有名管道,通信的两个进程都必选正在运行.

消息队列是IPC对象中的一种,与同样提供先进先出服务的管道相比,有如下特点
1)消息队列提供了消息数据的自动拆分功能,同时不能接收两次发的消息
2)消息队列提供了不完全随机读取的服务,引入消息类型后,一个队列在逻辑上可以化身为不同消息类型的链表,用户可以自行选择接收某条逻辑链表上的消息,而不必依次接收队列的首条消息.
3)消息队列提供了完全异步的读写服务,管道在使用时要求读写两端同时被打开,而消息队列没有这个限制,进程可以在任意时刻打开队列,也可以从队列中读取暂时不存在的消息.

创建消息队列的函数有msgget,发送消息队列的函数有msgsnd,从消息队列中接收消息的函数有msgrcv,控制消息队列的函数有msgctl,它可以查询消息队列数据结构,改变消息队列访问权限,改变消息队列属主信息和删除消息队列等功能.