版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第9章Linux进程通信内容提要进程通信概述管道内存映射SystemVIPCPOSIXIPC文件锁9.1进程通信概述进程通信概述进程需彼此协同、交换和共享数据,由于进程的用户空间各自独立,无法直接沟通,但它们共享内核空间和文件系统,可借助内核和文件来实现进程间的通信。应用编程接口分类API功能描述管道pipe建立无名管道Popen/pclose打开/关闭命令的标准输入或输出mkfifo创建命名管道内存映像文件mmap/munmap建立/解除文件至内存的映射SystemVIPC信号量semget创建/打开systemv信号量semop申请/释放systemv信号量semctl操作systemv信号量消息队列msgget创建/打开systemv消息队列msgrcv从systemv消息队列接收消息msgsnd向systemv消息队列发送消息msgctl操作systemv消息队列共享内存shmget建立/打开systemv共享内存shmat/shmdt建立/删除systemv共享内存映射shmctl操作systemv共享内存POSIXIPC信号量sem_open/sem_close/sem_unlink打开/关闭/删除POSIX信号量sem_wait/sem_post等待/释放POSIX信号量Sem_init/sem_destroy初始化/注销POSIX无名信号量消息队列mq_open/mq_close/mq_unlink打开/关闭/删除POSIX消息队列mq_getattr/mq_setattr获取/设置POSIX消息队列属性mq_receive/mq_send收发POSIX消息共享内存shm_open/shm_unlink打开/删除POSIX共享内存文件锁flock锁定/解锁文件9.2管道管道概述管道是一种进程间的单向数据传输机制,基于先进先出的字节流,管道有两个端点,一端用于写入数据,另一端用于从管道读取,读取的数据会从管道中移走。根据接口形式的不同,管道可分为无名管道和命名管道。管道的分类1.无名管道无名管道因无对应的管道文件而得名,借助内存而非外部文件实现通信,通常为关联的进程间建立通道。2.命名管道命名管道是建立于文件系统的特殊文件,借助文件接口实现进程间通信。创建无名管道头文件
#include<unistd.h>函数原型
int
pipe(intfd[2]);功能 创建无名管道。参数
pipefd[2]:对文件描述符。
flags:操作方式。返回值 成功返回0,否则返回-1。
无名管道的实现dentry(目录项)dentryf_opnamed_inodefile(文件描述)task_struct(进程控制块)fd0123465fd[](文件描述符表)file(文件描述)物理页写端读端dentryf_opread_pipe_fops(文件操作集)write_pipe_fops(文件操作集)..read.write.管道创建命名管道头文件
#include<sys/types.h> #include<sys/stat.h>函数原型
int
mkfifo(constchar*pathname,mode_tmode);功能 创建命名管道。参数
pathname:文件路径名。
mode:存取权限。返回值 成功返回0,失败返回-1。实例分析charbuffer[BUFSIZ];int
main(int
argc,char*argv[]){
intpipefd[2];
pipe(pipefd);
pid_t
pid=fork(); if(pid==0){ close(pipefd[1]); while(read(pipefd[0],&buffer,1)>0) write(1,&buffer,1); write(1,"\n",1); close(pipefd[0]); _exit(0); }else{ close(pipefd[0]); write(pipefd[1],argv[1],strlen(argv[1])); close(pipefd[1]);
wait(NULL); exit(0); }}9.3内存映射内存映射概述
内存映射是一种将文件的某个区域
映射至进程用户地址空间的技术。内存文件为一种特殊类型的文件,其内容存储于内存页中,例如,位于内存文件系统中的文件属于该类文件,利用内存映射可将内存文件的某个区域同时映射至多个进程的用户地址空间,从而实现进程间的通信。POSIXIPC正是通过在内存文件上建立内存映射构建。
mmap/munmap函数头文件
#include<sys/mman.h>函数原型
void*mmap(void*addr,size_t
length,int
prot,int
flags,int
fd,off_toffset);
int
munmap(void*addr,size_tlength);功能 建立/解除内存映射。参数
addr:映射区起始地址。
length:映射区大小。
prot:存取权限。
flags:映射方式。
fd:文件描述符。
offset:文件偏移量。返回值
mmap函数成功返回映射区起始地址,失败返回MAP_FAILED。
munmap函数成功返回0,失败返回-1。实例分析int
main(int
argc,char*argv[]){
int
fd=open("/dev/zero",O_RDWR,0); char*anon,*zero;anon=(char*)mmap(NULL,4096,PROT_READ|PROT_WRITE,MAP_ANON|MAP_SHARED,-1,0);zero=(char*)mmap(NULL,4096,PROT_READ|PROT_WRITE,MAP_FILE|MAP_SHARED,fd,0);
strcpy(anon,argv[1]);
strcpy(zero,argv[1]);
printf("anonymous:%s\tzero-backed:%s\n",anon,zero); switch((fork())){ case0:
strcpy(anon,argv[2]);
strcpy(zero,argv[2]);
munmap(anon,4096);
munmap(zero,4096);
close(fd); return0; } sleep(3);
printf("anonymous:%s\tzero-backed:%s\n",anon,zero);
munmap(anon,4096);
munmap(zero,4096);
close(fd); return0;}9.4SystemVIPC内容提要SystemVIPC概述
SystemV信号量
SystemV消息队列
SystemV共享内存SystemVIPC概述SystemVIPC源自SystemV系统,是一种传统的进程间通信的接口规范,在各类传统Unix系统中得到广泛使用,它由信号量、消息队列和共享内存三部分构成,可实现进程间的同步、数据传输和数据共享,
自Linux诞生之初,Linux内核就提供了对SystemVIPC的支持。
SystemVIPC通过在内核中创建IPC对象实现,每个IPC对象对应一个唯一的ID。SystemV信号量
信号量表示某种资源的数量,资源的数量可反映到信号量的数值上,当信号量大于0时,表示有资源可供使用,当信号量等于0时,表示已无资源可用,申请资源者需要等待。
SYSTEMV信号量用信号量集表示,由若干信号量组成,可同时反映多种资源的状态,一次可支持对一个或多个信号量的原子操作。SystemV信号量的操作步骤(1)创建/打开一个SystemV信号量集。(2)初始化SystemV信号量(3)申请/释放SystemV信号量(4)当SystemV信号量不再使时,将其删除。semget函数头文件
#include<sys/types.h> #include<sys/ipc.h> #include<sys/sem.h>函数原型
int
semget(key_tkey,int
nsems,int
semflg);功能 获得或创建信号量。参数
key:IPC对象标识。
nsems:信号量的数量。
semflg:存取权限和操作方式。返回值 成功返回信号量的标识,失败返回-1。信号量相关状态信息内核用数据结构记录每一种信号量的状态信息,例如:unsignedshortsemval;//信号量当前值unsignedshortsemzcnt;//等待信号量变为0的进程/线程的数量unsignedshortsemncnt;//等待释放信号量的进程/线程数量pid_t
sempid//最近一次修改信号量的进程ID
信号量的申请与释放会修改semval,当无信号量可用时,调用者进程便会进入semncnt和semzcnt关联的等待队列。semop函数头文件
#include<sys/types.h> #include<sys/ipc.h> #include<sys/sem.h>函数原型
int
semop(int
semid,struct
sembuf*sops,unsignednsops);功能 获得/释放信号量。参数
semid:信号量标识。
sops::信号量数组。
nsops:信号量数量。返回值 成功返回0,失败返回-1。semop函数(续)struct
sembuf{ushort
sem_num; //在信号量数组中的索引shortsem_op; //操作类型shortsem_flg; //操作标志};sembuf结构中成员变量sem_op描述信号量的操作类型参数sem_op含义sem_op>0指定信号量与sem_op相加,释放更多的信号量,唤醒正在等待该信号量的进程/线程sem_op=0等待指定信号量变为0sem_op<0指定信号量与sem_op相加,若值大于等于0,表示获得信号量,否则等待semctl函数头文件
#include<sys/types.h> #include<sys/ipc.h> #include<sys/sem.h>函数原型
int
semctl(int
semid,int
semnum,int
cmd,...);功能 信号量的控制操作。参数
semid:信号量标识。
semnum:在信号量集中的索引。
cmd:操作类型。返回值 成功返回值由具体操作决定,失败返回-1。semctl函数(续)unionsemun{
int
val;//用于设置信号量的值
struct
semid_ds*buf;//缓存地址,用于IPC_STAT和IPC_SETunsignedshort*array;//数组地址,用于GETALL和SETALL
struct
seminfo*__buf;//缓存地址,用于IPC_INFO};参数cmd含义GETVAL获得信号量的值SETVAL设置信号量的值GETPID获得最后一次操作信号量的进程GETNCNT获得正在等待信号量的进程数GETZCNT获得等待信号量值变为0的进程数IPC_RMID删除信号量集,唤醒所有等待的进程/线程3SystemV消息队列
消息队列是存在于内核中的消息列表,一个进程可将消息发送至消息队列,另一个进程则可从消息队列中获取消息。栈堆数据代码栈堆数据代码进程1进程2消息队列Linux内核Linux内核SystemV消息队列的操作步骤(1)建/打开SystemV消息队列。(2)接收/发送SystemV消息。(3)当SystemV消息队列不再使用时,将其删除。msgget函数头文件
#include<sys/types.h> #include<sys/ipc.h> #include<sys/msg.h>函数原型
int
msgget(key_tkey,int
msgflg);功能 创建/打开SystemV消息队列参数
key:IPC对象标识。
msgflg:存取权限和操作方式。返回值 成功返回消息队列标识,失败返回-1。msgrcv/msgsnd函数头文件
#include<sys/types.h> #include<sys/ipc.h> #include<sys/msg.h>函数原型
ssize_t
msgrcv(int
msqid,void*msgp,size_t
msgsz,long
msgtyp,int
msgflg);
int
msgsnd(int
msqid,constvoid*msgp,size_t
msgsz,int
msgflg);功能接收/发送SystemV消息。参数
msqid:消息队列的标识。
msgp:消息地址。
msgsz:消息大小(字节数)。
msgtyp:接收消息类型。
msgflg:操作方式。返回值 成功返回0,失败返回-1。struct
msgbuf{longmtype;//消息类型,必须大于0charmtext[1];//消息,具体结构用户可自定义};msgctl函数头文件
#include<sys/types.h> #include<sys/ipc.h> #include<sys/msg.h>函数原型
int
msgctl(int
msqid,int
cmd,struct
msqid_ds*buf);功能控制SystemV消息队列的属性。参数
msqid:消息队列标识。
cmd:操作类型。
buf:指向操作的数据。返回值 成功返回0,失败返回-1。msgctl函数struct
msqid_ds{
struct
ipc_perm
msg_perm;
struct
msg*msg_first; //指向消息队列的首
struct
msg*msg_last; //指向消息队列的尾
__kernel_time_t
msg_stime; //最后发送时间
__kernel_time_t
msg_rtime; //最后接收时间
__kernel_time_t
msg_ctime; //最后修改时间
unsignedshortmsg_cbytes; //当前消息队列的字节数
unsignedshortmsg_qnum; //消息队列中的消息数
unsignedshortmsg_qbytes; //消息队列的最大字节数
__kernel_ipc_pid_t
msg_lspid; //最后发送消息的进程ID__kernel_ipc_pid_t
msg_lrpid; //最后接收消息的进程ID};参数cmd含义IPC_RMID删除消息队列IPC_STAT获取消息队列的状态IPC_SET改变消息队列的存取权限struct
ipc_perm{
key_tkey; //IPC对象标识
uid_t
uid; //用户ID
gid_t
gid; //用户组ID
uid_t
cuid; //创建用户ID
gid_t
cgid; //创建用户组IDunsignedshortmode; //权限分配
unsignedshortseq; //序列号};SystemV共享内存
将同时映射至不同进程用户空幻的物理内存称为共享内存,物理内存可由若干不连续的物理页构成,共享内存在不同进程用户空间的地址未必相同。内核栈堆数据代码内核栈堆数据代码进程1进程2物理内存映射映射1.SYSTEMV共享内存的操作步骤(1)创建/打开SystemV共享内存。(2)将SystemV共享内存映射至调用者进程的用户空间。(3)当SystemV共享内存不再使用时,将映射接触。shmget函数头文件
#include<sys/ipc.h> #include<sys/shm.h>函数原型
int
shmget(key_tkey,intsize,int
shmflg);功能 创建/获得systemv共享内存。参数
Key:共享内存标识。
size:共享内存大小。
shmflg存取权限和操作方式。返回值 成功返回消息队列标识,失败返回-1。shmat/shmdt函数
头文件
#include<sys/types.h> #include<sys/shm.h>函数原型
void*shmat(int
shmid,constvoid*shmaddr,int
shmflg);
int
shmdt(constvoid*shmaddr);功能 建立/解除SystemV共享内存的内存映射。参数
shmid:IPC对象标识。
shmaddr:映射地址。
shmflg:权限和操作方式。返回值 成功返回映射的地址,失败返回-1。shmctl函数头文件
#include<sys/types.h> #include<sys/shm.h>函数原型
int
shmctl(int
shmid,int
cmd,struct
shmid_ds*buf);功能 操作systemv共享内存。参数
shmid:IPC对象标识。
cmd:操作命令。
buf:共享内存属性地址。返回值 成功返回0,失败返回-1。shmctl函数struct
shmid_ds{
struct
ipc_perm
shm_perm; //存取权限
int
shm_segsz; //共享内存大小
__kernel_time_t
shm_atime; //最后映射时间
__kernel_time_t
shm_dtime; //最后解除映射时间
__kernel_time_t
shm_ctime; //最后修改时间
__kernel_ipc_pid_t
shm_cpid; //创建进程ID__kernel_ipc_pid_t
shm_lpid; //最近操作进程IDunsignedshort shm_nattch; //建立映射的进程数};参数cmd描述IPC_STAT获取共享内存的状态IPC_SET设置共享内存的权限IPC_RMID删除共享内存IPC_LOCK锁定共享内存,使共享内存不被交换出去IPC_UNLOCK解锁共享内存9.5POSIXIPC内容提要POSIXIPC概述POSIX信号量
POSIX消息队列POSIX共享内存POSIXIPC概述
为了消除各类Unix间的差异,POSIX设计了一套具有更高可移植性的IPC接口标准,相较于SystemVIPC,POSIXIPC语法较为简洁,它同样支持信号量、消息队列和共享内存。在较新的Linux内核中实现了对POSIXIPC的支持。POSIX信号量POSIX信号量是一种进程间同步的控制机制,信号量用整数表示,通常代表某种资源的数量。进程通过减操作申请获得信号量,通过加操作申请释放信号量,当信号量值为0时,试图获取信号量的进程挂起,直至其他进程释放信号量;反之,当信号量已达上限,试图释放信号量的进程挂起,直至其他进程获取了信号量。POSIX信号量的分类POSI命名信号量在Linux系统中,命名信号量存储于文件系统tmpfs,tmpfs通常挂载至/dev/shm,当创建一个新POSIX命名信号量时,同名文件会出现在/dev/shm目录。2.POSIX无名信号量POSIX无名信号量在文件系统上无对应的文件,如同无名管道一样,可用于父子进程及其线程间的同步控制。POSIX信号量的操作步骤1.创建/打开POSIX信号量。1.申请/释放POSIX信号量。3.当完成对信号量的操作,及时关闭信号量。4.当所有进程都关闭了信号量,将信号量删除。创建/打开/关闭/删除POSIX命名信号量。(1)sem_open/sem_close/sem_unlink函数头文件
#include<fcntl.h> #include<sys/stat.h> #include<semaphore.h>函数原型
sem_t*sem_open(constchar*name,int
oflag);
sem_t*sem_open(constchar*name,int
oflag,mode_tmode,unsignedintvalue);
int
sem_close(sem_t*sem);
int
sem_unlink(constchar*name);功能 创建/打开/关闭/删除POSIX命名信号量。参数
name:信号量名称。
oflag:操作方式。
mode:权限设置。
value:信号量初始值。返回值
sem_open函数成功返回信号量地址,失败返回SEM_FAILED。申请/释放POSIX信号量(2)sem_wait/sem_post函数头文件
#include<semaphore.h>函数原型
int
sem_wait(sem_t*sem);
int
sem_timedwait(sem_t*sem,conststruct
timespec*abs_timeout);
int
sem_post(sem_t*sem);功能 申请获取/释放POSIX信号量。参数
sem:信号量对象。
abs_timeout:超时时间。返回值 成功,返回0,失败,返回-1。初始化/注销POSIX无名信号量(3)sem_init/sem_destroy函数头文件
#include<semaphore.h>函数原型
int
sem_init(sem_t*sem,int
pshared,unsignedintvalue)
int
sem_destroy(sem_t*sem)功能 初始化/注销POSIX无名信号量。参数
sem:信号量。
pshared:共享标志。
value:信号量的初始值。返回值 成功,返回0,否则,返回-1。POSIX无名信号量在文件系统上无对应的文件,如同无名管道一样,基于内存实现,可用于父子进程及其线程间的同步控制。POSIX消息队列POSIX消息队列是一种进程间以消息为单位的数据传输机制,消息以队列形式储存,并为消息定义优先级,优先级高的消息会被优先处理。POSIX消息队列的实现在Linux系统中,POSIX消息队列存储于mqueue文件系统,若将mqueue文件系统挂载至/dev/mqueue目录,新建的消息队列会在/dev/mqueue生成相应的文件.POSIX消息队列的操作步骤1.创建/打开一个POSIX消息队列。2.接收/发送消息。3.当完成对消息队列的操作,应及时关闭消息队列。4.当所有进程不再使用消息队列时,应将消息队列删除。创建/打开/关闭/删除POSIX消息队列(1)mq_open/mq_close/mq_unlink函数头文件
#include<fcntl.h> #include<sys/stat.h> #include<mqueue.h>函数原型
mqd_t
mq_open(constchar*name,int
oflag);
mqd_t
mq_open(constchar*name,int
oflag,mode_t
mode,struct
mq_attr*attr);
int
mq_close(mqd_t
mqdes);
int
mq_unlink(constchar*name);功能 创建/打开/关闭/删除POSIX消息队列。参数
name:POSIX消息队列名称。
oflag:操作方式。
mode:访问权限。
attr:属性地址。返回值
mq_open函数成功返回消息队列描述符,失败返回-1。struct
mq_attr{longmq_flags;//收发信息是否阻塞,取值为0或O_NONBLOCKlongmq_maxmsg;//发送消息数量上限
longmq_msgsize;//每条消息的最大上限
longmq_curmsgs;//当前消息的数量};获取/设置POSIX消息队列属性(2)mq_getattr/mq_setattr函数头文件
#include<mqueue.h>函数原型
int
mq_getattr(mqd_t
mqdes,struct
mq_attr*attr);
int
mq_setattr(mqd_t
mqdes,conststruct
mq_attr*newattr,struct
mq_attr*oldattr);功能 获取/设置POSIX消息队列属性。参数
mqdes:消息队列描述符。
attr:属性地址。
newattr:新属性地址。
oldattr:原属性地址。返回值 成功返回0,失败返回-1。接收/发送消息(3)mq_receive/mq_send函数头文件
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 《政府绩效管理》课程教学大纲
- 《办公自动化》课程教学大纲
- 2024年低首付汽车售卖合同范本
- 2024年代理投标协议合同范本
- 山东省济南市商河县2024-2025学年上学期七年级期中考试数学试题(无答案)
- 2024-2025学年江苏省盐城市七校联考高二上学期11月期中考试数学试题(含答案)
- 医疗战略分析
- 一次性使用医疗用品管理制度
- 便秘患者的护理方案
- 医院管理年中活动方案
- 放射诊疗监督检查记录表
- 吸收氨过程填料塔的设计吸收塔设计完整版
- 培智实用数学11册认识钟表试题整理(共13页)
- 再谈赏识教育
- NS2000变电站综合自动化系统辅助装置技术使用说明书(2006-5-25)
- 检验科标本拒收记录
- 药剂科质量与安全管理小组工作制度及职责
- 地下水池施工方案
- 关于初中英语的论文试谈初中英语写作教学
- 新人教版八年级英语上册第六单元.ppt
- 工程部维修工考核表
评论
0/150
提交评论