1、 5.1 Linux下进程间通信概述Linux下的进程间通信方式主要有:(1)管道(pipe)管道分为无名管道和有名管道,无名管道只能用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信,而有名管道除具有无名管道具有的功能外,还能用于无亲属关系的进程间的通信。(2)信号(signal)信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身。Linux除了支持Unix早期信号语义函数signal外,还支持语义符合Posix.1标准的信号函数sigaction。(3)消息队列 消息队列是消息的链接表,包括Posix
2、消息队列system V消息队列。它克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点,使具有写权限的进程可以向队列中添加消息,具有读权限的进程可以读取队列中的消息。(4)共享内存 共享内存是最有用的进程间通信方式,它使得多个进程可以访问同一块内存空间。它往往需要与其它通信机制结合,如与信号量结合使用可实现进程间的同步与互斥。(5)内存映射(mapped memory)内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间来实现它。(6)信号量(semaphore)主要作为进程间以及同一进程不同线程之间的同步手段。(7)套接字(
3、socket)应用更为广泛的进程间通信机制,可用于不同机器之间的进程间通信。所有提供了TCP/IP协议栈的操作系统几乎都提供了套接字,而所有这样操作系统,对套接字的编程方法几乎是完全一样的。5.2 管道通信5.2.1 管道概述管道是Linux支持的最初Unix IPC形式之一,具有以下特点:(1)管道是半双工的通信模式,数据只能向一个方向流动。(2)只能用于具有亲缘关系的进程间的通信,即父子进程或者兄弟进程之间。(3)管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是单独构成一种文件系统,并且只存在与内存中。5.2.2 管道创建与关闭创建管道可以通过调用p
4、ipe函数来实现。pipe函数的语法要点如下:头文件:#include 函数原型:int pipe(int fd2)pipe函数通过传入两个文件描述符来创建管道,调用成功时返回0,否则返回-1。5.2.3 管道读写一般文件的I/O函数都可以用于管道,如close、read、write等等。5.2.4 标准流管道 系统提供了一个popen函数来完成标准流管道的一系列创建过程;popen函数的使用可大大减少代码的编写量,但是创建管道时缺少灵活性,该函数只能支持标准的I/O函数,不能使用read、write这类不带缓冲的I/O函数。关闭标准流管道使用pclose函数来完成,该函数关闭标准I/O流,并
5、等待命令执行结束。5.2.5 FIFO命名管道(named pipes),因为这种管道的操作方式基于“先进先出”原理,也称为FIFO(First In First Out)在程序中调用mkfifo函数创建FIFO管道,mkfifo函数调用的原型为:#include#include int mkfifo(const char *filename,mode_t mode);5.3 信号机制5.3.1 信号概述1信号及信号来源 信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是异步的。信号事件的发生有两个来源:硬件来源(比如我们按下了
6、键盘或者其它硬件故障);软件来源,最常用发送信号的系统函数是kill、raise、alarm、setitimer和sigqueue函数,软件来源还包括一些非法运算等操作。2信号的种类可以从两个不同的分类角度对信号进行分类:(1)可靠性方面:可靠信号与不可靠信号;(2)与时间的关系上:实时信号与非实时信号。3进程对信号的响应进程对信号的响应有以下三种方式:(1)忽略信号,即对信号不做任何处理,但是有两个信号不能忽略,即SIGKILL和 SIGSTOP。(2)捕捉信号,定义信号处理函数,当信号发生时,执行相应的处理函数。(3)执行缺省操作,Linux对每种信号都规定了默认操作。5.3.2 信号的发
7、送1kill()和raise()kill函数和kill系统命令一样,可以发送信号给进程或者进程组。它不仅可以终止进程,还可以向进程发送其他信号。与kill函数不同,raise函数允许向其自身发送信号。kill函数相关语法要点:头文件:#include 和#include 函数原型:int kill(pid_t pid,int signo)raise函数相关语法要点:头文件:#include 和#include 函数原型:int raise(int signo)2alarm()和pause()alarm函数可以在进程中设置一个定时器,当定时器指定的时间到达时,它就向进程发送SIGALARM信号。
8、一个进程只有一个闹钟时间,如果在调用alarm之前已经设置过闹钟时间,则新设置的闹钟时间会替代以前设置的闹钟时间。alarm函数相关语法要点:头文件:#include 函数原型:unsigned int alarm(unsigned int seconds)pause函数是用于将调用进程挂起直至捕捉到信号为止,通常可用于判断信号是否已到。pause函数相关语法要点:头文件:#include 函数原型:int pause(void)函数返回值:返回值为-1,并把error值设为EINTR。3sigqueue()sigqueue函数是比较新的发送信号系统调用,主要是针对实时信号提出的(当然也支持前
9、32种),支持信号带有参数,与函数sigaction()配合使用。sigqueue函数相关语法要点:头文件:#include 和#include 函数原型:int sigqueue(pid_t pid,int signo,const union sigval val)4setitimer()sigqueue函数是比较新的发送信号系统调用,主要是针对实时信号提出的(当然也支持前32种),支持信号带有参数,与函数sigaction()配合使用。sigqueue函数相关语法要点:头文件:#include 函数原型:int setitimer(int which,const struct itimer
10、val*value,struct itimerval*ovalue)5.3.3 信号的处理Linux主要有两个函数实现信号的处理:signal()、sigaction()。1signal函数signal函数相关语法要点:头文件:#include 函数原型:void(*signal(int signum,void(*handler)(int)(int)2信号集函数组信号集被定义为一种数据类型:typedef struct unsigned long sig_NSIG_WORDS;sigset_t 信号集用来描述信号的集合,Linux所支持的所有信号可以全部或部分的出现在信号集中,主要与信号阻塞相
11、关函数配合使用。5.4 共享内存5.4.1 共享内存概述System V 进程间通信(IPC)包括3种机制:消息队列、信号量、共享内存。System V共享内存把共享数据放在共享内存区域,任何想要访问该数据的进程通过共享该内存区域来获得访问权。System V共享内存通过shmget获得或创建一个IPC共享内存区域,并返回相应的标识符。5.4.2 共享内存的实现1接口函数 System V 为共享内存主要定义了fork()、shmget()、shmat()、shmdt()和shmctl()几个API接口函数 fork 函数用于生成一个键值:key_t key;shmget 函数用于创建(或者获
12、取)一个由key键值指定的共享内存对象;shmat 函数用于建立调用进程与由标识符shmid指定的共享内存对象之间的连接,返回被映射的段地址;shmdt 函数用于断开调用进程与共享内存对象之间的连接;shmctl 函数用于对已创建的共享内存对象进行查询、设值、删除等操作.2实例 5.5 消息队列5.5.1 消息队列概述消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级。用户可以从消息队列中添加消息、读取消息。下图说明了内核与消息队列是怎样建立起联系的。其中:struct ipc_ids msg_ids是内核中记录消息队列的全局数据结构;struct msg_qu
13、eue是每个消息队列的队列头。5.5.2 消息队列的实现1接口函数 System V 为消息队列的实现主要定义了msgget()、msgsnd()、msgrcv()和msgctl()几个 API接口函数 msgget函数用于创建或打开消息队列msgsnd函数用于发送消息 msgrcv函数用于读取消息 msgctl函数用于对由msqid标识的消息队列执行cmd操作 2实例 实例首先使用msgget函数创建一个新的消息队列,接着使用msgsnd函数添加一个消息到消息队列,然后使用msgrcv函数从消息队列中读取消息,最后使用msgctl函数删除该消息队列。5.6 信号量信号量用于保护系统中关键的代
14、码或者数据结构。Linux系统中使用信号量技术使得某一时刻只有一个进程可以存取关键区域的代码和数据。Linux系统中信号量的数据结构包括以下的信息:1.Count 记录希望使用此资源的进程个数。正值意味着此资源可用,负值或零值意味着进程正在等待此资源。其初始值为1,说明此时有一个且仅有一个进程可以使用此资源。2.waking 等待此资源的进程个数,同时也表示当此资源空闲时,可以唤醒以便被执行的进程个数。3.wait queue 当进程等待此资源时,它们将会被放入此等待队列。4.Lock用于存取waking 字段时所用的锁。System V的每个IPC信号量对象都对应一个信号量数组,在Linux中用semid _ ds数据结构来表示它。系统中所有的semid _ ds数据结构都被一个叫semary的指针向量指向。当一个进程进入了关键段,改变了信号量的值后,由于进程崩溃或被中止等原因而无法离开关键段时,就会造成死锁。Linux通过为信号量数组维护一个调整项列表来防止死锁。
侵权处理QQ:3464097650--上传资料QQ:3464097650
【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。