处理函数,并设置中断处理函数与该中断相关联.这样,用户进程在收到该 中断后,即调用用户定义的函数,处理完成后用户进程从被中断处继续运 行(若用户定义的中断函数没有长跳函数或退出运行等会改变运行指令地 址的系统调用).在中断信号被处理后,该中断的处理函数会恢复成上次缺 省处理函数而不是保持用户定义函数,故在用户定义的中断处理函数中一 般都再定义该中断和函数自己的关联.
3.4.4IPC的权限设置
在消息队列,共享内存和信号量的访问时有用户访问权限设置,类同 于文件的访问权限的设置如(777表示rwxrwxrwx),用命令ipcs即可看到在 系统中生成的消息队列,共享内存和信号量的访问权限.其意义也类似于 文件访问权限.只是执行位无效.
在有名管道和文件方式共享内存中以系统文件的方式定义了用户的 访问权限.用命令ls -l可以看到它们以系统文件方式存在并具有访问权 限值,并可以看到有名管道的文件类型为p,文件方式共享内存的文件类型 为s.
3.4.5信号中断对系统调用一级有效
系统在设计系统调用时就考虑了中断处理问题.当进程运行到一个系 统调用时发生了中断,则进程进入该中断处理,处理完成后,进程会跳过该 系统调用而进入下一条程序指令.
应该注意的是中断发生在系统调用一级而不是子程序或函数一级.比 如一个程序在一个子程序被调用前设置了超时中断,并在子程序中收到超 时中断,系统在处理完超时中断后接着处理该子程序被中断的系统调用之 后的指令,而不是从调用该子程序名指令的后一条指令继续处理.
3.4.6各种IPC方式的特点
. 消息队列:
通过消息队列key值定义和生成消息队列.
任何进程只要有访问权限并知道key即可访问消息队列. 消息队列为内存块方式数据段.
消息队列中的消息元素长度可为系统参数限制内的任何长度. 消息元素由消息类型分类,其访问方式为按类型访问.
在一次读写操作前都必须取得消息队列标识符,即访问权.访问后即 脱离访问关系.
消息队列中的某条消息被读后即从队列中删除.
消息队列的访问具备锁机制处理,即一个进程在访问时另一个进程 不能访问.
操作时要注意系统资源和效率.
在权限允许时,消息队列的信息传递是双向的.
. 共享内存
通过共享内存key值定义和生成共享内存.
任何进程只要有访问权限并知道key即可访问共享内存. 共享内存为内存块方式的数据段.
共享内存中的数据长度可为系统参数限制内的任何长度. 共享内存的访问同数组的访问方式相同.
在取得共享内存标识符将共享内存与进程数据段联接后即可开始对 之进行读写操作,在所有操作完成之后再做共享内存和进程数据 段脱离操作,才完成全部共享内存访问过程. 共享内存中的数据不会因数据被进程读取后消失.
共享内存的访问不具备锁机制处理,即多个进程可能同时访问同一 个共享内存的同一个数据单元.
共享内存的使用最好和信号量一起操作,以具备锁机制,保证数据的 一致.
在权限允许时,共享内存的信息传递是双向的. . 信号量
用于生成锁机制,避免发生数据不一致. 没有其他的数据信息.
不需要有父子关系或兄弟关系. . 信号
信号由系统进行定义.
信号的发送只要有权限即可进行.
信号是一个事件发生的信息标志,不带有其它信息. 信号不具备数据块.
信号的处理可由用户自己定义.
信号可能由用户进程,操作系统(软件或硬件原因)等发出. 有一些信号是不可被屏蔽的.
信号中断的是系统调用级的函数. 信号的信息传递是单向的.
. 管道
做为系统的特殊设备文件,可以是内存方式的,也可以是外存方式的. 管道的传输一般是单向的,即一个管道一向,若两个进程要做双向传 输则需要2个管道.管道生成时即有两端,一端为读,一端为写,两个 进程要协调好,一个进程从读方读,另一个进程向写方写. 管道的读写使用流设备的读写函数,即:read(),write.
管道的传输方式为FIFO,流方式的.不象消息队列可以按类型读取. * 有名管道
一般为系统特殊文件方式,使用的进程之间不一定要有父子关系 或兄弟关系. * 无名管道
一般为内存方式,使用的进程之间一定要有父子关系或兄弟关系. . 文件
文件是最简单的进程间通讯方式,使用外部存贮器为中介.
操作麻烦,定位困难.
保密程度低.
容易出现数据不一致问题. 占用硬盘空间.
只要有权限并知道文件名,任何进程都可对之操作. * 特殊处理
为避免出现保密问题,在打开文件,取得文件描述符后,调用 unlink()将硬盘上的文件路径名删除,则硬盘上就没有文件拷贝 了.但在进程中该文件描述符是打开的,由该进程生成的子进程中 该文件描述符也是打开的,就可以利用系统提供的文件缓冲区做 进程间通讯,代价是进程间必须有父子关系或兄弟关系. . 环境变量
信息的传送一般是单向的,即由父进程向子进程传送. 保密性较好.
双方必须约定环境变量名.
只占用本进程和子进程的环境变量区. . 共享数据段 操作比较复杂.
占用硬盘空间,生成系统特殊文件. 其他性质与共享内存相类似. . 流
文件描述符的操作方式.
进程间不一定要有父子关系或兄弟关系. 双向传送信息.
进程各自生成socket,用bind()联接.
其他性质与管道相类似.
流编程为TCP/IP网络编程范围,在本文中暂不阐述. . 传递参数
信息的传送一般是单向的, 即由父进程向子进程传送. 保密性较差,用进程列表即可显示出来. 双方必须约定参数位置. 只占用子进程的参数区.
四.进程通信与同步
4.1. 概述
Linux内核主要由五个子系统组成:进程调度,内存管理,虚拟文件系统,
网络接口,进程间通信。
Linux提供了多种进程间的通信机制,其中,信号和管道是最基本的两种,也提供 System V的进程间通信机制,包括消息队列、信号灯及共享内存等。
System V IPC对象权限包含在ipc_perm数据结构中,位于
include/linux/ipc.h。
System V的消息是在ipc/msg.c中实现、共享内存在ipc/shm.c中实现、信号灯在ipc/sem.c中,管道在/ipc/pipe.c中实现。
与Windows相比,在进程间通信机制上,Linux提供了标准的UNIX IPC机制,接近于IPC原语,比较底层,提供了最大的灵活性,也可以在此基础上建立更加复杂的高级IPC机制;Windows则在基本IPC机的基础上,提供了许多直接面向应用程序的高级IPC机制。
linux下进程间通信的几种主要手段简介:
1. 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程
间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;
2. 信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种
事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数);
3. 消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列
system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。 4. 共享内存:使得多个进程可以访问同一块内存空间,是单机最快的可用
IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
5. 信号灯(semaphore):主要作为进程间以及同一进程不同线程之间的同步
手段。
6. 套接口(Socket)和UINX域套接字:更为一般的进程间通信机制,可用
于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。
进程同步就是要协调好2个以上的进程,使之以安排好地次序依次执行。有时候,父进程要求子进程的运算结果进行下一步的运算,或者子进程的功能是为父进程提供了下一步执行的先决条件(如:子进程建立文件,而父进程写入数据),此时父进程就必须在某一个位置停下来,等待子进程运行结束,而如果父进程不等待而直接执行下去的话,会出现极大的混乱。
解决进程同步问题可用信号、管道、套接字、共享内存等多种方法。简单情况下也可以用wait系统调用简单的予以解决。请看下面这段程序:
#include
main() {
pid_t pc, pr; int status;
pc=fork(); if(pc<0)
printf(\else if(pc==0) {
/* 子进程的工作 */ exit(0); } else {
/* 父进程的工作 */ pr=wait(&status);
/* 利用子进程的结果 */ } }
当fork调用成功后,父子进程各做各的事情,但当父进程的工作告一段落,需要用到子进程的结果时,它就停下来调用wait,一直等到子进程运行结束,然后利用子进程的结果继续执行。
4.2. 管道
系统调用pipe ( ) 创建管道。管道是进程间通信最古老的方式,它包括无名管道和有名管道两种,前者用于父进程和子进程间的通信,后者用于运行于同一台机器上的任意两个进程间的通信。