linux进程间通信(消息队列、信号量、共享内存等)汇编课件.ppt
- 【下载声明】
1. 本站全部试题类文档,若标题没写含答案,则无答案;标题注明含答案的文档,主观题也可能无答案。请谨慎下单,一旦售出,不予退换。
2. 本站全部PPT文档均不含视频和音频,PPT中出现的音频或视频标识(或文字)仅表示流程,实际无音频或视频文件。请谨慎下单,一旦售出,不予退换。
3. 本页资料《linux进程间通信(消息队列、信号量、共享内存等)汇编课件.ppt》由用户(晟晟文业)主动上传,其收益全归该用户。163文库仅提供信息存储空间,仅对该用户上传内容的表现方式做保护处理,对上传内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(点击联系客服),我们立即给予删除!
4. 请根据预览情况,自愿下载本文。本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
5. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007及以上版本和PDF阅读器,压缩文件请下载最新的WinRAR软件解压。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- linux 进程 通信 消息 队列 信号量 共享 内存 汇编 课件
- 资源描述:
-
1、Company nameLinux培培训训主讲人:主讲人:肖勇军肖勇军桂电嵌入式交流群:156619189Linux进程间通信(下)Linux IPC programmeLinux 培培训训课程目标lSystem V IPC 接口简介System V 消息队列消息队列System V 信号量System V 共享内存lPOSIX IPC接口Posix 消息队列Posix 信号量信号量Posix 共享内存共享内存Company nameLinux培培训训主讲人:主讲人:肖勇军肖勇军桂电嵌入式交流群:156619189Linux 培培训训System V IPC 接口l由于历史原因,linux下的
2、进程通信手段基本上是从Unix平台上的进程通信手段继承而来的.lUnix发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间通信方面的侧重点有所不同 贝尔实验室对Unix早期的进程间通信手段进行了系统的改进和扩充,形成了“system V IPC”,通信进程局限在单个计算机内.BSD则形成了基于套接口(socket)的进程间通信机制,可以在跨机器进行通信.l由于Unix版本的多样性,电子电气工程协会(IEEE)开发了一个独立的Unix标准,这个新的ANSI Unix标准被称为计算机环境的可移植性操作系统界面(POSIX)。他也发展出一套新的I
3、PC接口.Linux 本身支持POSIX接口.因此也支持POSIX的IPC接口l最初Unix IPC包括:管道、FIFO、信号,System V IPC包括:System V消息队列、System V信号灯、System V共享内存区,Posix IPC包括:Posix消息队列、Posix信号灯、Posix共享内存区。l System V IPC通常在多个操作系统均实现,包括一般的嵌入式Linux系统,因此本课程主要介绍system V IPCLinux 培培训训Linux 的IPCLinux 培培训训lSystemV IPC指以下三种类型的IPC:SystemV消息队列 sys/msg.hS
4、ystemV信号灯 sys/sem.hSystemV共享内存区 sys/shm.hl创建或打开函数创建或打开函数msgget,semget,shmgetl控制操作函数控制操作函数msgctl,semctl,shmctll操作函数操作函数 msgsnd,msgrcv,semop,shmat,shmdtLinux 培培训训System V关键字l每一个System V 对象(消息队列,共享内存和信号量)创建时,需要的第一个参数是整数的Key值,头文件把key_t定义为一个整数lSystem V 创建对象时假设进行IPC通讯双方都取了相同的key值.这样将双方关联起来l生成key的方法有三种双方直接
5、设置为一个相同的整数为key值用IPC_PRIVA让系统自动产生一个key值,用ftok函数将一个路径转换为key值Linux 培培训训ftok函数lftok函数把一个已存在的路径名和一个整数标识符转换成一个key_t值,称为IPC键(IPC key):#include key_t ftok(const char*pahtname,int id);l如果pathname不存在,或者对调用进程不可访问,ftok返回-1 l不能保证两个不同的路径名与同一个id值的组合产生不同的键。l用于产生键的pahtname不能是服务器存活期间由它反复创建并删除的文件,否则会导致ftok多次调用返回不同的值 L
6、inux 培培训训System V IPC的类型l报文(Message)队列(消息队列):消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。l共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。l信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。Company n
7、ameLinux培培训训主讲人:主讲人:肖勇军肖勇军桂电嵌入式交流群:156619189Linux 培培训训消息队列l消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读走消息。l消息队列能够克服早期unix通信机制的一些缺点,如数据量小,没有实时性Linux 培培训训消息队列(2)l消息队列消息通常要以一个long mtype放在消息开始,mtype成员代表消息类型,从消息队列中读取消息的一个重要依据就是消息的类型struct msgbuf long mtyp
8、e;char mtext1;l消息队列与管道以及有名管道相比,具有更大的灵活性 它提供有格式字节流,有利于减少开发人员的工作量 消息具有类型,在实际应用中,可作为优先级使用。这两点是管道以及有名管道所不能比的 消息队列可以在几个进程间复用,而不管这几个进程是否具有亲缘关系,这一点与有名管道很相似;但消息队列是随内核持续的,与有名管道(随进程持续)相比,生命力更强,应用空间更大。Linux 培培训训消息队列编程l头文件#include#include#include lmsgget打开或创建消息队列int msgget(key_t key,int msgflg);返回线队列IDlmsgrcv从队
9、列接收消息int msgrcv(int msqid,struct msgbuf*msgp,int msgsz,long msgtyp,int msgflg);lmsgsnd 向队列发送消息int msgsnd(int msqid,struct msgbuf*msgp,int msgsz,int msgflg);lmsgctl 发送队列控制命令msgctl(int msqid,int cmd,struct msqid_ds*buf);共有三种cmd操作:IPC_STAT、IPC_SET、IPC_RMID。Linux 培培训训消息队列数据结构l对于系统中的每个System V消息队列,内核维护一个
10、如下的结构:struct msqid_ds struct ipc_perm msg_perm;/*operation permission struct*/struct msg*msg_first;/*ptr to first message on q*/struct msg*msg_last;/*ptr to last message on q*/unsigned short msg_cbytes;/*current#bytes on q*/msgqnum_t msg_qnum;/*#of messages on q*/msglen_t msg_qbytes;/*max#of bytes o
11、n q*/pid_t msg_lspid;/*pid of last msgsnd*/pid_t msg_lrpid;/*pid of last msgrcv*/time_t msg_stime;/*last msgsnd time*/time_t msg_rtime;/*last msgrcv time*/time_t msg_ctime;/*last change time*/;Linux 培培训训msgget函数 l#include lint msgget(key_t key,int oflag);返回:成功时为非负标识符,出错时为-1用于创建一个新的SystemV消息队列或访问一个已经
12、存在的消息队列。l参数key和oflag的说明见前。lOflag:取值取值,IPC_CREAT 创建新对象成功,IPC_EXCL检查新对象l返回值是一个整数标识符,其他三个msg函数用它来指代该队列。l当创建一个消息队列时,msqid_ds结构的如下成员被初始化:msg_perm结构的uid和cuid被设置为当前进程的有效用户ID,gid和cgid被设置为当前用户的有效组ID;oflag中的读写权限位存放在msg_perm.mode中;msg_qnum、msg_lspid、msg_lrpid、msg_stime和msg_rtime被置为0;msg_ctime被设置成当前时间;msg_qbyte
13、s被设置为系统限制值。Linux 培培训训msgsnd函数 l#include lint msgsnd(int msgid,const void*ptr,size_t length,int flag);l返回:成功时为0,出错时为-1l该函数用于往消息队列上放置一个消息。lmsgid是msgget返回的标识符,ptr是一个结构指针,该结构有如下的模板:struct msgbuf long mtype;/*message type,must be 0*/char mtext 1;/*message data*/;l消息类型mtype必须大于0,因为非正消息类型有特殊的指示作用。llength参数
14、以字节为单位指定待发送消息的长度。这是位于长整数消息类型之后的用户自定义数据的长度,该长度可以是0。lflag参数可以是0,也可以是IPC_NOWAIT。IPC_NOWAIT标志使得msgsnd调用非阻塞。当有如下情形之一时:在指定的队列中已经有太多的字节(对应msqid_ds结构中的msg_qbytes值);在系统范围存在太多的消息。若设置了IPC_NOWAIT,则msgsnd立即返回,返回一个EAGAIN错误。若未指定该标志,则msgsnd阻塞,直到具备存放新消息的空间;有msgid标识的消息队列被删除,此时返回EIDRM错误;被信号中断,此时返回EINTR错误。Linux 培培训训msg
15、rcv函数 l#include lssize_t msgrcv(int msqid,void*ptr,size_t length,long type,int flag);l返回:成功时为读入缓冲区中数据的字节数,出错时为-1l该函数从某个消息队列中读出一个消息。lptr参数指定所接收消息的存放位置。跟msgsnd一样,该指针指向紧挨在真正的消息数据之前返回的长整数类型字段。llength指定由ptr指向的缓冲区中数据部分的大小。这是该函数能返回的最大数据量。该长度不包含长整数类型字段。ltype指定希望从所给定的队列中读出什么样的消息:type为0,返回队列中第一个消息。每个消息队列是作为一个
16、FIFO链表维护的,所以返回的是队列中最早的消息。type大于0,返回其类型值为type的第一个消息。type小于0,返回其类型值小于或等于type参数的绝对值的消息中类型值最小的第一个消息。lflag参数指定所请求的消息不在队列中时怎么办。在没有消息时,若设置了IPC_NOWAIT标志,则函数立即返回一个ENOMSG错误;否则,调用者阻塞直到如下某个时间发生:l有一个所请求类型的消息可获取;l由msqid标识的消息队列被删除,此时返回个EIDRM错误;l被某个捕获的信号中断,此时返回EINTR错误。Linux 培培训训msgctl函数 l#include lint msgctl(int ms
17、qid,int cmd,struct msqid_ds*buf);l返回:成功时为0,出错时为-1l该函数提供在一个消息队列上的各种控制操作。lmsgctl提供三个命令:IPC_RMID:从系统中删除由msqid指定的消息队列。当前在该队列上的任何消息都被丢弃。此时。第三个参数忽略不用。IPC_SET:给指定的消息队列设置其msqid_ds结构的以下四个成员:msg_perm.uid、msg_perm.gid、msg_perm.mode和msg_perm.qbytes。它们的值来自buff指向的结构中的相应成员。IPC_STAT:通过buff参数给调用者返回所指定消息队列中的当前msqid_d
18、s结构。Linux 培培训训消息队列打开l如果没有调用 msgctl(semid,IPC_RMID,0)删除消息队列,则消息队列一直存在内核中,即便是创建进程已经退出也是如此,这个用ipcs可以看到l如果对一个已经创建的消息队列的路径再次创建消息队列,通常都会出错.因此可以采用一种保险的写法/*首先查询这个队列是否创建,如创建直接用它*/if(msgid=msgget(key,IPC_EXCL|0666)=-1)/*没有创建才去创建这个消息队列*/msgid=msgget(key,IPC_CREAT|IPC_EXCL|00666);if(msgid=-1)printf(msg create e
19、rrorn);return;l其它对象也用这样打开方法Company nameLinux培培训训主讲人:主讲人:肖勇军肖勇军桂电嵌入式交流群:156619189Linux 培培训训信号量l信号量与其他进程间通信方式不大相同,它主要提供对进程间共享资源访问控制机制。l信号量相当是一个全局的整数变量,这个变量只能用原子操作来改变值l信号灯与其它进程间通信方式有所不同,它主要用于进程间同步。通常所说的系统V信号灯实际上是一个信号灯的集合,可用于多种共享资源的进程间同步。每个信号灯都有一个值,可以用来表示当前该信号灯代表的共享资源可用(available)数量,l如果一个进程要申请共享资源,那么就从信
20、号灯值中减去要申请的数目,如果当前没有足够的可用资源,进程可以睡眠等待,也可以立即返回。当进程要申请多种共享资源时,linux可以保证操作的原子性,即要么申请到所有的共享资源,要么放弃所有资源,这样能够保证多个进程不会造成互锁。Linux 培培训训信号量集的数据结构lSystemV信号灯是信号灯集的概念:一个或多个信号灯构成一个集合。对于系统每个信号灯集,内核维护如下的一个结构:struct semid_ds struct ipc_perm sem_perm;/*operation permission struct*/struct sem*sem_base;/*ptr to first se
21、maphore in set*/unsigned short sem_nsems;/*#of semaphores in set*/time_t sem_otime;/*last semop time*/time_t sem_ctime;/*last change time*/;l当前信号灯集中的每个信号灯对应一个sem结构。定义如下:struct sem signed short semval;/*semaphore text map address*/pid_t sempid;/*pid of last operation*/unsigned short semncnt;/*#awaiti
22、ng semval cval*/unsigned short semzcnt;/*#awaiting semval=0*/;Linux 培培训训关于关于P原语原语lP原语:原语:P是荷兰语Proberen(测试)的首字母。为阻塞原语,负责把当前进程由运行状态转换为阻塞状态,直到另外一个进程唤醒它。操作为:申请一个空闲资源(把信号量减1),若成功,则退出;若失败,则该进程被阻塞;P原语的操作过程lsem减1;l若sem减1后仍大于或等于零,则进程继续执行;l若sem减1后小于零,则该进程被阻塞后进入与该信号相对应的队列中,然后转进程调度。System V 实现代码 int p(int semid
23、)struct sembuf sops=0,+1,IPC_NOWAIT;return(semop(semid,&sops,1);Linux 培培训训关于关于V原语原语lV原语V是荷兰语Verhogen(增加)的首字母。为唤醒原语,负责把一个被阻塞的进程唤醒,它有一个参数表,存放着等待被唤醒的进程信息。操作为:释放一个被占用的资源(把信号量加1),如果发现有被阻塞的进程,则选择一个唤醒之V原语的操作过程lsem加1;l若相加结果大于零,则进程继续执行;l 若相加结果小于或等于零,则从该信号的等待队列中唤醒一等待进程,然后再返回原进程继续执行或转进程调度。System V 实现代码int v(in
24、t semid)struct sembuf sops=0,-1,IPC_NOWAIT;return(semop(semid,&sops,1);Linux 培培训训信号量的处理流程信号量的处理流程 l用到头文件#include#include#include lsemget创建或打开一个信号量int semget(key_t key,int nsems,int semflg)lSemop()对信号量+1 或-1 或测试是否为0 int semop(int semid,struct sembuf*sops,unsigned nsops);linux可以增加或减小信号量的值,相应于对共享资源的释放和
25、占有 lsemctl 对信号量进行各种控制int semctl(int semid,int semnum,int cmd,union semun arg)Linux 培培训训semget函数 l#include lint semget(key_t key,int nsems,int oflag);l返回:成功时为非负标识符,出错时为-1l创建一个信号灯集或访问一个已存在的信号灯集。l返回值是信号灯标识符,供其他信号灯函数使用。lnsems是集合中的信号灯数。如果不是创建一个信号灯集,而只是访问已存在的集合,则该参数可以指定为0。一旦创建完毕一个信号灯集,就不能改变其中的信号灯数。l当实际操作为
展开阅读全文