1、Linux程序设计教程第10章进程间通信2第10章 进程间通信n10.1 System V IPC介绍n10.2 System V信号量n10.3 System V共享内存n10.4 System V消息队列分为POSIX和SystemVnSystemV IPC在本机中通信,不能跨网络生存期与内核相同,系统重启则消失生存期内,任何进程可使用整型标识符访问。没有i节点和路径名,所以不能像文件/目录一样访问可使用ipcs显示状态、ipcrm删除对象。访问权限:读、写,没有执行系统调用nXget、Xctl(X:sem-信号量,shm-共享内存,msg-消息队列)nsemop,shmat、shmdt,
2、msgsnd、msgrcvSystemV可将路径名使用ftok函数生成关键字,Xget的参数为关键方式来打开对象返回整型标识符。10.1 System V IPC介绍410.1 System V IPC介绍nkey、id以及Xid_ds之间的关系510.2 System V信号量(semaphore)n信号量(semaphore)一种比较特殊的IPC,它只是一个计数器(counter)。一般情况,多个进程在访问共享对象时使用信号量实现同步操作,如经典的生产者/消费者问题。n实质是一个整数计数器,记录可同时访问共享资源的单元个数。当进程要求使用某资源,先对信号量减1n=0:进程可以用该资源n0:
3、进程休眠,直至信号量值大于或等于0时被唤醒。进程对资源访问结束时,信号量值加1n=0:证明有其他进程等待,唤醒队列第一个进程。6n信号量操作基本过程POSIX信号量只针对一个信号量操作,SystemV信号量可以对一个信号量集合操作。基本步骤n通过路径名设置信号量集合的关键字ftokn建立信号量集合并得到标识符semgetn设置信号量集合semctln对信号量集合中任意个信号量操作(加减1)semopn删除信号量集合操作使用semctl完成。10.2 System V信号量(semaphore)710.2 System V信号量(semaphore)nsemget#include#include
4、 int semget(key_t key,int nsems,int semflg);功能:创建信号量参数key:信号量的键值nsems:信号量的个数semflg:创建标志,可以是IPC_CREAT或IPC_CREAT|IPC_EXCL 返回值:n成功返回共享内存ID;失败返回-1,并设置errno810.2 System V信号量(semaphore)nsemctlint semctl(int semid,int semnum,int cmd,.);功能:信号量控制函数参数:semid:信号量IDcmd:控制命令semnum:信号量集中信号量的序号返回值:成功返回0;失败返回-19n通过两
5、个或多个进程共享同一块内存区域实现进程间通信。n通常是一个进程创建共享内存区域,然后多个进程可以对其进行访问。n由于数据是由内存直接映射到进程空间,所以速度快。但涉及同步问题,可用信号量来实现同步。共享内存进程A进程B10.3 System V共享内存(share memory)10n共享内存基本操作过程创建将被共享的内存空间(确定大小)将该空间映射到本进程中进行正常的读写操作解除映射如果需要,删除被共享的内存空间10.3 System V共享内存(share memory)11#include n创建并得到共享内存段创建并得到共享内存段int shmget(key_t key,size_t
6、size,int flags);返回值:成功返回共享内存标识符,错误返回-1(置errno)n控制共享内存段控制共享内存段(包含删除包含删除)int shmctl(int shmid,int cmd,struct shmid_ds*data);返回值:成功返回0,错误返回-1(置errno)n连接共享内存段连接共享内存段void*shmat(int shmid,const void*shmaddr,int flags);返回值:成功返回进程中该内存段的地址,错误返回-1(置errno)n断开共享内存段断开共享内存段int shmdt(const void*shmaddr);返回值:成功返回0,
7、错误返回-1(置errno)10.3 System V共享内存(share memory)12nshmget#include#include int shmget(key_t key,size_t size,int shmflg);功能:n创建共享内存参数:nkey:共享内存的键值nsize:共享内存大小nshmflg:创建标志返回值:n成功返回共享内存ID;失败返回-110.3 System V共享内存(share memory)13nshmat说明说明void*shmat(int shmid,const void*shmaddr,int flags);参数:shmid:共享内存标识符。sh
8、maddr:进程映射内存段的地址,可以指定,但一般设置为NULL,表示由系统安排,安排好的地址由返回值返回。flags:对该内存段是否设置只读,默认设置读写。返回值:返回值:成功返回进程中该内存段的地址,错误返回-1(置errno)10.3 System V共享内存(share memory)n共享内存与管道的区别共享内存与管道都是利用内存空间进行进程间通信。进程server从一个文件传输到进程client的过程看两者的区别,管道需要4次复制,共享内存需要2次复制,速度快。1410.3 System V共享内存(share memory)n共享内存举例shmwrtie.c 创建shm并将arg
9、v1写入shmshmread.c 从shm中获得值shmdel.c 删除shm注意n创建共享内存确定大小时,可以使用结构体方式确定该块内存中数据类型。n创建共享内存成功后可以使用ipcs查看创建的结果ipcs是SystemV IPC提供的查看IPC信息的工具删除SystemV IPC还可以使用ipcrm m shmid删除共享内存1510.3 System V共享内存(share memory)16n也叫报文队列,克服信号最多在接收信号进程的生命周期中有效(随进程持续)的缺点。n消息队列在系统重启前一直有效(随内核持续)10.4 System V消息队列17n消息队列,即消息的一个链表,一系列
10、连续排列的消息,保存在内核中,通过消息队列的引用标识符访问。n每个消息都包括两部分:类型和正文。n任何进程都可以向消息队列中发送指定类型消息,其他进程都可以从消息队列中根据类型获取相应的消息。消息类型正文消息类型正文消息类型正文10.4 System V消息队列18n消息队列操作基本过程创建消息队列根据收/发消息类型进行收/发消息如有必要,则删除消息队列n关于消息队列说明队列,先进先出如果类型相同,先发送的消息将先被读出消息被读出则消息队列就减少一个结点。当消息队列满时的写操作或消息队列空时的读操作都会阻塞。10.4 System V消息队列1910.4 System V消息队列nmsgget
11、#include#include#include int msgget(key_t key,int msgflg);功能:n创建、打开消息队列参数:nkey:消息队列键值nmsgflg:创建方式返回值:n成功返回消息队列ID;失败返回-12010.4 System V消息队列nmsgsndint msgsnd(int msqid,const void*msgp,size_t msgsz,int msgflg)功能:n发送消息参数:nmsgid:消息队列IDnmsgp:指向消息指针nmsgsz:消息长度nmsgflg:发送方式返回值:n成功返回消息队列ID;失败返回-12110.4 System
12、 V消息队列nmsgrcvssize_t msgrcv(int msqid,void*msgp,size_t msgsz,long msgtyp,int msgflg);功能:n接收消息参数:nmsgid:消息队列IDnmsgp:指向消息的指针nmsgsz:消息长度nmsgflg:接收方式返回值:n成功返回消息正文字节数;失败返回-12210.4 System V消息队列nmsgctlint msgctl(int msqid,int cmd,struct msqid_ds*buf);功能:n消息队列控制函数参数:nmsgid:消息队列IDncmd:控制命令返回值:n成功返回0;失败返回-123Linux 通信方式 小结n管道:连接一个进程的输出至另一个进程的输入的一种方法。单向,无名(进程本身或亲缘进程)、有名(FIFO无关进程)掌握无名管道父子进程操作n信号:用于通知接收进程有某种事件发生signal,killn信号量:一个计数器,用来记录对某个资源的使用情况n共享内存:允许多个进程访问同一块内存空间n消息队列:消息的链表,链表中每个节点包括消息类型和正文两部分。谢谢!