




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
LINUX应用编程–
进程间通讯2009年12月22日2LINUX应用编程-目录IPC概述管道FIFO共享存储套接字信号量消息队列3进程间通讯–IPC概述信号(signal)亲缘进程和非亲缘进程都可以,也可以进程自己给自己递送信号。信号量(semaphore)主要是线程间和亲缘和非亲缘的进程间的同步手段,不做数据传输之用。管道只允许亲缘进程间的通讯。命名管道(FIFO)除了亲缘进程可以通讯外,非亲缘进程也可以通讯。共享内存多个进程可以访问同一块内存空间,是最快的IPC方式。在进程间传递数据时无须任何内存的拷贝。可以在亲缘和非亲缘的进程间使用。套接字最通用的进程间通讯方式,它提供了一种让不同机器上进程间通讯方式。消息队列可以用在非亲缘关系的进程之间使用4进程间通讯–
管道管道是UNIXIPC的最老形式,并且所有UNIX系统都提供此种通信机制,管道有两种限制;(1)它们是半双工的。数据只能在一个方向上流动。(2)它们只能在具有公共祖先的进程之间使用。通常,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可应用该管道。管道的写和读有两个特性:(1)数据写入时,放在管道的结尾。(2)数据读取时,从管道的头开始读取。5进程间通讯–pipe函数管道是由调用pipe函数而创建的。#include<unistd.h>intpipe(intfiledes[2]);参数filedes返回两个文件描述符:filedes[0]为读而打开,filedes[1]为写而打开。filedes[1]的输出是filedes[0]的输入。由于管道是单向的,所以通常一个进程需要关闭写端或者读端,而另一个进程则关闭相应的读端或写端。写端不存在时,读端会收到文件结束符。读端不存在时,写端会收到SIGPIPE信号。如果忽略该信号或者捕捉该信号并从其处理程序返回,则write出错返回,errno设置为EPIPE成功返回0,失败返回-1.缺点:只能用于亲缘进程间通讯,在一个进程内管道几乎是没有实际用处的在写管道时,常数PIPE_BUF规定了内核中管道缓存器的大小。如果对管道进行write调用,而且要求写的字节数小于等于PIPE_BUF,则此操作不会与其他进程对同一管道(或FIFO)的write操作穿插进行。但是,若有多个进程同时写一个管道(或FIFO),而且某个或某些进程要求写的字节数超过PIPE_BUF字节数,则数据可能会与其他写操作的数据相穿插。6进程间通讯–fork前后管道关系fork之后做什么取决于我们想要有的数据流的方向。对于从父进程到子进程的管道,父进程关闭管道的读端(fd[0]),子进程则关闭写端(fd[1])Fork后的半双工管道从父进程到子进程的管道对于从子进程到父进程的管道,父进程关闭fd[1],子进程关闭fd[0]7进程间通讯–popen和pclose函数我们常用到的一个操作是创建一个连接到另一个进程的管道,然后读其输出或向其发送输入,所以标准I/O库为实现这些操作提供了两个函数popen和pclose。这两个函数实现的操作是:创建一个管道,fork一个子进程,关闭管道的不使用端,exec一个shell以执行命令,等待命令终止。#include<stdio.h>FILE*popen(constchar*command,constchar*type);返回:若成功则为文件指针,若出错则为NULLintpclose(FILE*stream);返回:command的终止状态,若出错则为-1函数popen先执行fork,然后调用exec以执行command,并且返回一个标准I/O文件指针。如果type是"r",则文件指针连接到command的标准输出。如果type是“w”,则文件指针连接到command的标准输入。pclose函数关闭标准I/O流,等待命令执行结束,然后返回shell的终止状态。如果shell不能被执行,则pclose返回的终止状态与shell执行exit一样。8进程间通讯–FIFOFIFO有时被称为命名管道。管道只能由相关进程使用,它们共同的祖先进程创建了管道。但是,通过FIFO,不相关的进程也能交换数据。创建FIFO类似于创建文件。确实,FIFO的路径名存在于文件系统中。#include<sys/types.h>#include<sys/stat.h>intmkfifo(constchar*pathname,mode_tmode);返回0成功,返回-1失败mkfifo函数中mode参数的规格说明与open函数中的mode相同。一旦已经用mkfifo创建了一个FIFO,就可用open打开它。确实,一般的文件I/O函数(open、close、read、write、unlink等)都可用于FIFO。FIFO有两种用途:(1)FIFO由shell命令使用以便将数据从一条管道线传送到另一条,为此无需创建中间临时文件。(2)FIFO用于客户机-服务器应用程序中,以在客户机和服务器之间传递数据9进程间通讯–FIFO当打开一个FIFO时,非阻塞标志(O_NONBLOCK)产生下列影响:(1)在一般情况中(没有说明O_NONBLOCK),只读打开要阻塞到某个其他进程为写打开此FIFO。类似,为写而打开一个FIFO要阻塞到某个其他进程为读而打开它。(2)如果指定了O_NONBLOCK,则只读打开立即返回。但是,如果没有进程已经为读而打开一个FIFO,那么只写打开将出错返回,其errno是ENXIO。类似于管道,若写一个尚无进程为读而打开的FIFO,则产生信号SIGPIPE。若某个FIFO的最后一个写进程关闭了该FIFO,则将为该FIFO的读进程产生一个文件结束标志。一个给定的FIFO有多个写进程是常见的。这就意味着如果不希望多个进程所写的数据互相穿插,则需考虑原子写操作。正如对于管道一样,常数PIPE_BUF说明了可被原子写到FIFO的最大数据量。10进程间通讯–
共享存储共享存储允许两个或多个进程共享一给定的存储区。因为数据不需要在客户机和服务器之间复制,所以这是最快的一种IPC。使用共享存储的唯一窍门是多个进程之间对一给定存储区的同步存取。若服务器将数据放入共享存储区,则在服务器做完这一操作之前,客户机不应当去取这些数据。通常,信号量被用来实现对共享存储存取的同步。11进程间通讯–mmapvoid*mmap(void*addr,size_tlength,intprot,intflags,intfd,off_toffset)mmap在进程地址空间创建一个映射。它既可以把一个文件映射到内存,也可以映射一块内存,实现进程间内存共享。addr为共享内存的起始地址,为NULL时,内核会自动选择一个起始地址。length为共享内存的长度。prot指明了共享内存保护状态:PROT_EXEC,PROT_READ,PROT_WRITE,PROT_NONEflagsMAP_SHARED共享此内存MAP_PRIVATE只有该进程可见。MAP_ANONYMOUS为匿名映射。参数fd为即将映射到进程空间的文件描述字,一般由open()返回,同时,fd可以指定为-1,此时须指定flags参数中的MAP_ANON,表明进行的是匿名映射(不涉及具体的文件名,避免了文件的创建及打开,很显然只能用于具有亲缘关系的进程间通信)。12进程间通讯–
内存共享内核为每个共享存储段设置了一个shmid_ds结构。#include<sys/ipc.h>#include<sys/shm.h>#include<sys/types.h>key_tftok(constchar*pathname,intproj_id);intshmget(key_tkey,size_tsize,intshmflg);void*shmat(intshmid,constvoid*shmaddr,intshmflg);intshmdt(constvoid*shmaddr);intshmctl(intshmid,intcmd,structshmid_ds*buf);共享内存1314进程间通讯–shmget函数调用的第一个函数通常是shmget,它获得一个指定大小的共享存储标识符。intshmget(key_tkey,size_tsize,intshmflg);key参数用来标识共享内存size参数该共享存储段的最小值,如果正在创建一个新段(一般在服务器中),则必须指定其size。如果正在存访一个现存的段(一个客户机),则将size指定为0。shmflg参数有IPC_CREAT和IPC_EXCL,最为重要的是在shmflg中指明访问权限,跟open的mode参数一样。否则会出现permissiondenied等错误。返回:若成功则为共享内存ID,若出错则为-1key可由ftok()生成。pathname必须为调用进程可以访问的。proj_id的低8bit有效。pathname和proj_id共同组成一个key。15进程间通讯–shmat一旦创建了一个共享存储段,进程就可调用shmat将其连接到它的地址空间中。void*shmat(intshmid,constvoid*addr,intshmflg);返回:若成功则为指向共享存储段的指针,若出错则为-1共享存储段连接到调用进程的哪个地址上与addr参数以及在flag中是否指定SHM_RND位有关。(1)如果addr为NULL,则此段连接到由内核选择的第一个可用地址上。(2)如果addr非NULL,并且没有指定SHM_RND,则此段连接到addr所指定的地址上。(3)如果addr非0,并且指定了SHM_RND,则此段连接到(addr-(addrmodSHMLBA))所表示的地址上。SHM_RND命令的意思是:取整。SHM_LBA的意思是:低边界地址倍数,它总是2的乘方。该算式是将地址向下取最近1个SHMLBA的倍数。一般应指定addr为0,以便由内核选择地址。16进程间通讯–shmctlshmctl函数对共享存储段执行多种操作。intshmctl(intshmid,intcmd,structshmid_ds*buf);cmd参数指定下列5种命令中一种,使其在shmid指定的段上执行:IPC_STAT对此段取shmid_ds结构,并存放在由buf指向的结构中。IPC_SET按buf指向的结构中的值设置与此段相关结构中的下列三个字段:shm_perm.uid、shm_perm.gid以及shm_perm.mode。此命令只能由下列两种进程执行:一种是其有效用户ID等于shm_perm.cuid或shm_perm.uid的进程;另一种是具有超级用户特权的进程。
IPC_RMID从系统中删除该共享存储段。因为每个共享存储段有一个连接计数(shm_nattch在shmid_ds结构中),所以除非使用该段的最后一个进程终止或与该段脱接,否则不会实际上删除该存储段。不管此段是否仍在使用,该段标识符立即被删除,所以不能再用shmat与该段连接。此命令只能由下列两种进程执行:一种是其有效用户ID等于shm_perm.cuid或shm_perm.uid的进程;另一种是具有超级用户特权的进程。SHM_LOCK
锁住共享存储段。此命令只能由超级用户执行。(禁止换出)SHM_UNLOCK解锁共享存储段。此命令只能由超级用户执行。返回:若成功则为0,若出错则为-117进程间通讯–shmdt当对共享存储段的操作已经结束时,则调用shmdt脱接该段。注意,这并不从系统中删除其标识符以及其数据结构。该标识符仍然存在,直至某个进程(一般是服务器)调用shmctl(带命令IPC_RMID)特地删除它。intshmdt(constvoid*shmaddr);shmaddr参数是以前调用shmat时的返回值。返回:若成功则为0,若出错则为-1Shmex.c例子展示了在亲缘关系的进程中内存共享wshm.c例子往一片共享内存内写入数据,而rshm.c则从该共享内存中读取数据信号量信号量是一个计数器,用于多进程对共享数据对象的存取访问控制。为了获得共享资源,进程需要执行下列操作:(1)测试控制该资源的信号量。(2)若此信号量的值为正,则进程可以使用该资源。进程将信号量值减1,表示它使用了一个资源单位。(3)若此信号量的值为0,则进程进入睡眠状态,直至信号量值大于0。若进程被唤醒后,它返回至(第(1)步)。18信号量intsemget(key_tkey,intnSemes,intflag)函数说明:创建信号量,如果引用一个现存的集合(一个客户机),则将nsems指定为0参数说明:key-标识信号量的关键字,有三种方法:1、使用IPC-PRIVATE让系统产生,2、挑选一个随机数,3、使用ftok从文件路径名中产生nSemes-信号量集中元素个数,对客户机,此参数设为0Flag-IPC_CREAT;IPC_EXCL只有在信号量集不存在时创建,对客户机,此参数设为019信号量intsemctl(intsemid,intsemnum,intcmd,/*unionsenumarg*/...)函数说明:
控制信号量参数说明:
semid-信号量集的句柄semnum-信号量集的某个成员cmd-命令IPC_RMID删除一个信号量IPC_SET设置信号量的许可权
SETVAL
设置指定信号量的元素的值为agc.val
GETVAL
获得一个指定信号量的值
GETPID获得最后操纵此元素的最后进程ID
GETNCNT
获得等待元素变为1的进程数
GETZCNT
获得等待元素变为0的进程数20信号量unionsenun定义如下:unionsenun{
intval;
structsemid_ds*buf;
unsignedshort*array;}agc;其中semid_ds
定义如下:structsemid_ds{
structipc_pemsem_pem;//operationpemission
structtime_tsem_otime;//lastsemop()time
time_tsem_ctime;//lasttimechangedbysemctl()
structsem*sembase;//ptrtofirstsemaphoreinarray
structsem_queue*sem_pending;//pendingoperations
structsem_queue*sem_pending_last;//lastpendingoperations
structsem_undo*undo;//undorequestsonthisarraryunsigned
shortintsem_nsems;//numberofsemaphoresinset};21信号量intsemop(intsemid,struct
sembuf*sops,unsigned
shortnsops)函数说明:对信号量+1或-1或测试是否为0函数参数:semid–sops-指向元素操作数组
structsembuf{
shortintsem_num;//semaphorenumber
shortintsem_op;//semaphoreoperaion,0,+1,-1
shortintsem_flg;//operationflagSEM_UNDO,IPC_NOWAIT};nsops-数组中元素操作的个数2223信号量(1)最易于处理的情况是sem_op为正。这对应于返回进程占用的资源。sem_op值加到信号量的值上。如果指定了SEM_UNDO标志,则当该进程终止的时候会自动将信号量的值恢复回之前的值。(2)若sem_op为负,则表示要获取由该信号量控制的资源。如若该信号量的值大于或等于sem_op的绝对值(具有所需的资源),则从信号量值中减去sem_op的绝对值。这保证信号量的结果值大于或等于0。如果指定了undo标志,则sem_op的绝对值也加到该进程的此信号量调整值上。如果信号量值小于sem_op的绝对值(资源不能满足要求),则:(a)若指定了IPC_NOWAIT,则出错返回EAGAIN;(b)若未指定IPC_NOWAIT,则该信号量的semncnt值加1(因为将进入睡眠状态),然后调用进程被挂起直至下列事件之一发生:i.此信号量变成大于或等于sem_op的绝对值(即某个进程已释放了某些资源)。此信号量的semncnt值减1(因为已结束等待),并且从信号量值中减去sem_op的绝对值。如果指定了undo标志,则sem_op的绝对值也加到该进程的此信号量调整值上。ii.从系统中删除了此信号量。在此情况下,函数出错返回ERMID。24信号量iii.进程捕捉到一个信号,并从信号处理程序返回,在此情况下,此信号量的semncnt值减1(因为不再等待),并且函数出错返回EINTR.(3)若sem_op为0,这表示希望等待到该信号量值变成0。如果信号量值当前是0,则此函数立即返回。如果信号量值非0,则:(a)若指定了IPC_NOWAIT,则
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 声音的频率与音高的关系试题及答案
- 2024年多媒体应用设计常考知识试题及答案
- 二级建造师考试项目计划试题及答案
- 2024年电网运行管理考题试题及答案
- 势能与高度关系探讨试题及答案
- 公务员省考模拟考试技巧试题及答案
- 力学中的能量守恒试题及答案
- 2024年档案信息化发展趋势试题及答案
- 完美复习资料的省考试题与答案
- 2024年考试策略试题及答案汇编
- 陕西省西安市高新一中2024-2025学年九年级3月份学业水平考试模拟历史试题(含答案)
- 《商务沟通与谈判》全套教学课件
- 广东省2025年普通高等学校招生全国统一考试模拟测试(一)地理及答案
- 土方平衡方案
- 全国第三届职业技能大赛(无人机驾驶(植保)项目)选拔赛理论考试题库(含答案)
- 危险化学品目录(2024版)
- 北京市土地一级开发项目管理工作流程图
- 安全工器具及设施发放登记台账(共3页)
- 小学生安全教育研究课题结题报告
- 盗墓笔记地图
- 粉色可爱生日快乐邀请函.doc
评论
0/150
提交评论