进程间的通信-管道,信号,消息队列,共享存储,套接字

进程间的通信

进程间通信(IPC)是在同一个操作系统内的不同进程之间交换信息的接口,每个IPC方法都有自己的优缺点。

IPC的目的:
信息传输:一个进程需要将一定量的数据发送给另一进程。
通知消息:一个进程需要将某个事件发送给另一进程(子进程终止时通知父进程)
资源共享:因为进程间相互独立,想在多个进程中实现资源共享,就需要内核的同步机制。
进程间控制:有些进程在运行过程中需要控制其他进程(debug),控制进程需要知道被控制进程的状态状态改变(发生异常)。进程间通过内核和进程间的通信来协调进程间的行为。

五种IPC方法:管道,系统IPC(消息队列,共享存储,信号),套接字(socket).

1.管道

管道是半双工的,数据只能往一个方向流动,如果需要双向流动,需要建立两个管道。
管道只可用于具有亲缘关系的进程间的通信,命名管道克服了这一缺陷,它可用于无亲缘关系的进程间通信。

管道分为三种:普通管道(也叫匿名管道),流管道,命名管道
1)普通管道PIPE, 通常有两种限制,一是单工,只能单向传输;二是只能在父子或者兄弟进程间使用.
2)流管道s_pipe: 去除了第一种限制,为半双工,可以双向传输.
3)命名管道:name_pipe, 去除了第二种限制,可以在许多并不相关的进程之间进行通。

管道的实质是一个内存缓冲区,采用先进先出的方式从缓冲区读出数据,管道一端将进程数据写入缓冲区,另一端按照写入顺序读出数据,读出后缓冲区中的数据也就不存在了。

2.信号

操作系统通过信号来通知进程系统中发生了某种预先规定好的事件(一组事件中的一个),它也是用户进程之间通信和同步的一种原始机制。一个键盘中断或者一个错误条件(进程试图访问它的虚拟内存中不存在的位置)都有可能产生一个信号。

一个信号的生命周期:
内核产生信号,用来相应某些事件,这些事件就是信号源,产生的信号由进程发送给进程。

几个常见的信号:
SIGHUP: 从终端上发出的结束信号;
SIGINT: 来自键盘的中断信号(Ctrl-C);
SIGQUIT:来自键盘的退出信号(Ctrl-\);
SIGFPE: 浮点异常信号(例如浮点运算溢出);
SIGKILL:该信号结束接收信号的进程;
SIGALRM:进程的定时器到期时,发送该信号;
SIGTERM:kill 命令发出的信号;
SIGCHLD:标识子进程停止或结束的信号;
SIGSTOP:来自键盘(Ctrl-Z)或调试程序的停止执行信号;

收到信号的进程可以选择接受或者忽略这些信号,这些信号都有缺省动作,当进程没有对信号作出回复,内核会对信号进行操作:
异常终止(abort):在进程的当前目录下,把进程的地址空间内容、寄存器内容保存到一个叫做core的文件中,而后终止进程。
退出(exit):不产生core文件,直接终止进程。
忽略(ignore):忽略该信号。
停止(stop):挂起该进程。
继续(continue):如果进程被挂起,则恢复进程的运行。否则,忽略信号。

对信号的任何处理,都只能由收到信号的进程进行,进程要执行信号处理程序,必须等到该进程开始进行,所以对信号的处理可能会有延迟。

消息列表

系统IPC都存在一个ipc_perm数据结构,里面定义了该IPC的认证信息,只有通过认证的进程间才可进行通信。

struct ipc_perm
{
__kernel_key_t key;
__kernel_uid_t uid;
__kernel_gid_t gid;
__kernel_uid_t cuid;
__kernel_gid_t cgid;
__kernel_mode_tmode;
unsigned short seq;
};

消息列表就是消息的列表,列表允许一个或多个进程写入消息,也允许一个或多个进程读出消息。
消息列表的数据结构如下

struct msqid_ds {
struct ipc_perm msg_perm;
struct msg *msg_first; /* 列表头 */ 
struct msg *msg_last; /* 列表尾 */
__kernel_time_t msg_stime; /*最后发送时间 */
__kernel_time_t msg_rtime; /* 最后接受时间 */
__kernel_time_t msg_ctime; /* 最后修改事件*/
struct wait_queue *wwait;  //写入等待队列
struct wait_queue *rwait;  //读取等待队列
unsigned short msg_cbytes; /* 队列中当前字节数 */
unsigned short msg_qnum; /* 队列中消息数 */
unsigned short msg_qbytes; /*队列中最大字节数 */
__kernel_ipc_pid_t msg_lspid; /* 最后发送消息进程的pid */
__kernel_ipc_pid_t msg_lrpid; /* 最后接受消息进程的pid */
}

在这里插入图片描述
当进程想要向消息队列中写入消息时,首先对比该进程和消息队列的ipc_perm,若认证成功,该进程从地址空间中拷贝一份到消息队列中,进入消息队列的队尾。
读出消息与写入类似,认证成功的可以从列表中读取第一条消息或特殊类型消息,若没有要读取的消息,进入等待队列。

共享存储

共享存储可以使得多个进程共享同一存储区,这多个进程将存储区映射到地址空间中。
当这些进程间需要通信时,将消息写入共享存储区。

套接字

套接字(socket)用于不同主机进程间的通信,通过ip地址找到进行通信的主机,端口号找到通信的进程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值