收藏 分销(赏)

Linux信号量、共享内存及消息队列.ppt

上传人:仙人****88 文档编号:10369521 上传时间:2025-05-24 格式:PPT 页数:56 大小:261.50KB 下载积分:10 金币
下载 相关 举报
Linux信号量、共享内存及消息队列.ppt_第1页
第1页 / 共56页
Linux信号量、共享内存及消息队列.ppt_第2页
第2页 / 共56页


点击查看更多>>
资源描述
Click to edit Master text styles,Second level,Third level,Fourth level,Fifth level,*,Click to edit Master title style,第,8,章 信号量、共享内存和消息队列,System V IPC,3,种,IPC,机制:,信号量,(semaphore set),,用于管理对资源的访问。,消息队列,(message queue),,程序之间传递数据的一种简单方法。,共享内存,(shared memory),,用于在程序之间高效的共享数据,shell,命令,ipcs,ipcrm,访问,ipcs,q,Ipcs,s,Ipcs,-m,Ipcrm,#,ipcs,-mIPC status from as of 2007,年,04,月,10,日 星期二,18,时,32,分,18,秒,CSTT ID KEY MODE OWNER GROUPShared Memory:m 0 0 x50000d43-,rw-r-r,-root,root,m 501 0 x1e90c97c-,rw-r,-oracle,dba,2,System V IPC,的共同特征,标识符与关键字,引用,IPC,对象:标识符,创建,IPC,对象时指定关键字,(,key_t,key;),key,的选择,:,预定义常数,IPC_PRIVATE,;,ftok,函数,内核将关键字转换成标识符,许可权结构,和文件类比,struct,ipc_perm,3,struct,ipc_perm,struct,ipc_perm,u i d _ t u i d;/*owners effective user id*/,g i d _ t g i d;/*owners effective group id*/,u i d _ t,cuid,;/*creators effective user id*/,g i d _ t c g i d;/*creators effective group id*/,m o d e _ t mode;/*access modes*/,u l o n g s e q;/*slot usage sequence number*/,k e y _ t key;/*key*/,4,SV IPC,系统调用,功能,消息队列,信号量,共享内存,分配一个,IPC,对象,获得对,IPC,的访问,msgget,semget,shmget,IPC,操作,:,发送,/,接收消息,信号量操作,连接,/,释放共享内存,msgsnd,/,msgrcv,semop,shmat,/,shmdt,IPC,控制:获得,/,修改状态信息,取消,IPC,msgctl,semctl,shmctl,5,信号量,并发程序设计,互斥和同步,PV,操作,(,原语,),P,操作:用于等待,V,操作:用于信号,6,PV,操作和信号量,procedure,p(var,s:samephore,),s.value,=s.value-1;,if(,s.value,0),sleep(s.queue,);,procedure,v(var,s:samephore,),s.value,=s.value+1;,if(,s.value,=0),wakeup(s.queue,);,7,一个理论性的例子,s,emaphore,sv,=1;,l,oop forever,P(sv,);,critical code section;,V(sv,);,noncritical code section;,8,内核中与信号量有关的数据结构,semaphore set,struct,semid_ds,struct,ipc_perm,sem_perm,;,struct,sem,*,sem_base,;,/*,指向信号量集合的指针*,/,time_t,sem_otime,;/*,最后一次操作的时间*,/,time_t,sem_ctime,;/*,最后一次改变此结构的时间*,/,unsigned short,sem_nsems,;,/*,集合中信号量个数*,/,9,Linux/UNIX,的信号量机制,struct,sem,pid_t,sempid,;,/*,最后操作该信号量的进程,ID*/,unsigned short,semncnt,;/*,等待对该信号量执行,P,操作的进程数*,/,unsigned short,semzcnt,;/*,等待,semval,为,0,的进程数*,/,unsigned short,semval,;,/*,信号量当前值*,/,10,信号量系统调用,#include,#include,#include,int,semget,(key_t,key,int,nsems,int,semflg,);,int,semop,(int,semid,struct,sembuf,*sops,unsigned,nsops,);,int,semctl,(int,semid,int,semnum,int,cmd,.);,11,semget,函数,功能:创建一个新信号量或取得一个已有信号量的,标志符。,函数原型为,int,semget,(key_t,key,int,nsems,int,semflg,);,“key”,参数,预定义常数,IPC_PRIVATE,;,约定的关键字,ftok,函数,“,semflg,”,参数,设置访问权限,(,低,9,位,),IPC_CREAT,IPC_EXCL,按位或,“,nsems,”,指定需要的信号量数目,几乎总是取值为,1,。,#include,key_t,ftok,(const,char*,path,int,id);,12,semget,函数(续),sem_id,=,semget,(key_t)1234,1,0666|IPC_CREAT);,13,semop,函数,功能:改变信号量的值,函数原型为,int,semop,(int,semid,struct,sembuf,*sops,size_t,nsops,);,“sops”,参数,struct,sembuf,unsigned short,sem_num,;/*,信号量编号*,/,short,sem_op,;/*,信号量操作*,/,short,sem_flg,;/*,操作标志*,/,nsops,参数,结构数组的元素个数,14,semop,函数(续),sem_flg,用于对操作进行适当的控制,主要,有,2,个控制标志。,IPC_NOWAIT,当指定的操作不能完成时,进程不等待立即返回,返回值为,-1,,,errno,置为,EAGAIN,。,SEM_UNDO,(建议),进程退出时,执行信号量解除(,undo,)操作。,15,semop,函数(续),int,semaphore_p(void,),struct,sembuf,sem_b,;,sem_b.sem_num,=0;,sem_b.sem_op,=-1;/*P()*/,sem_b.sem_flg,=SEM_UNDO;,if(,semop(sem_id,&,sem_b,1)=-1),fprintf(stderr,semaphore_p,failedn);,return(0);,return(1);,16,semop,函数(续),static,int,semaphore_v(void,),struct,sembuf,sem_b,;,sem_b.sem_num,=0;,sem_b.sem_op,=1;/*V()*/,sem_b.sem_flg,=SEM_UNDO;,if(,semop(sem_id,&,sem_b,1)=-1),fprintf(stderr,semaphore_v,failedn);,return(0);,return(1);,17,semctl,函数,功能:直接控制信号量信息,函数原型为:,int,semctl,(int,semid,int,semnum,int,cmd,.);,第,4,个参数(可选),union,semun,int,val,;,/*,用于,SETVAL,命令,指明要设置的值*,/,struct,semid_ds,*,buf,;,/*,用于,IPC_STAT/IPC_IPC_SET,命令,用来存放信号量集合数据结构,*,/,unsigned short*array;,/*,用于,GETALL/SETALL,命令,用来存放所获得的或是要设置信号量集合中所有信号量的值,*,/,arg,;,“,cmd,”,参数,18,semctl,函数(续),“,cmd,”parameter,IPC_STAT:,对指定的信号量标识返回,arg.semid_ds,结构中的当前值,IPC_SET:,在进程有足够权限的前提下,把信号量集合的当前关联值置为,arg.semid_ds,结构给出的值,IPC_RMID:,删除信号量集合,SETVAL:,设置信号量集合中由,semnum,指定的单个信号量的值,(,设为,arg.val,),19,semctl,函数(续),int,set_semvalue(void,),union,semun,sem_union,;,sem_union.val,=1;,if(,semctl,(sem_id,0,SETVAL,sem_union,)=-1),return(0);,return(1);,void,del_semvalue(void,),union,semun,sem_union,;,if(,semctl,(sem_id,0,IPC_RMID,sem_union,)=-1),fprintf(stderr,Failed to delete semaphoren);,20,Examples,一个完整的实例,sem1.c(,进程互斥,),21,semun.h,#if,defined(_GNU_LIBRARY,_)&!,defined(_SEM_SEMUN_UNDEFINED,),/*union,semun,is defined by including */,#else,/*according to X/OPEN we have to define it ourselves*/,union,semun,int,val,;,struct,semid_ds,*,buf,;,unsigned short,int,*array;,#,endif,22,int,main(int,argc,char*,argv,),int,i;,int,pause_time,;,char,op_char,=O;,srand(unsigned,int)getpid,();,sem_id,=semget(key_t)1234,1,0666|IPC_CREAT);,if(,argc,1),if(!,set_semvalue,(),fprintf(stderr,Failed to initialize semaphoren);,exit(EXIT_FAILURE,);,op_char,=X;,sleep(2);,23,for(i,=0;i 1),sleep(10);,del_semvalue,();,exit(EXIT_SUCCESS,);,24,static,int,set_semvalue,(void,),union,semun,sem_union,;,sem_union.val,=1;,if(,semctl,(sem_id,0,SETVAL,sem_union,)=-1)return(0);,return(1);,static void,del_semvalue,(void,),union,semun,sem_union,;,if(,semctl,(sem_id,0,IPC_RMID,sem_union,)=-1),fprintf(stderr,Failed to delete semaphoren);,25,static,int,semaphore_p,(void,),struct,sembuf,sem_b,;,sem_b.sem_num,=0;,sem_b.sem_op,=-1;/*P()*/,sem_b.sem_flg,=SEM_UNDO;,if(,semop,(sem_id,&,sem_b,1)=-1),fprintf(stderr,semaphore_p,failedn);,return(0);,return(1);,static,int,semaphore_v,(void,),struct,sembuf,sem_b,;,sem_b.sem_num,=0;,sem_b.sem_op,=1;/*V()*/,sem_b.sem_flg,=SEM_UNDO;,if(,semop,(sem_id,&,sem_b,1)=-1),fprintf(stderr,semaphore_v,failedn);,return(0);,return(1);,26,共享内存,共享内存,共享内存是内核为进程创建的一个特殊内存段,它将出现在自己的地址空间中,其它进程可以将同一段共享内存连接,(attach),到自己的地址空间,最快的进程间通信方式,不提供任何同步功能,27,共享内存示意图,进程,A,的,逻辑地址空间,进程,B,的,逻辑地址空间,物理内存,共享存储,28,shmid_ds,结构,struct,shmid_ds,struct,ipc_perm,shm_perm,;/see XSI IPC,size_t,shm_segsz,;/size of segment in bytes,pid_t,shm_lpid,;/,pid,of last,shmop,pid_t,shm_cpid,;/,pid,of creator,shmatt_t,shm_nattch,/number of current attaches,time_t,shm_atime,;/last-attach time,time_t,shm_dtime,;/last-detach time,time_t,shm_ctime,;/last-change time,;,29,共享内存系统调用,#include,#include,#include,int,semget,(key_t,key,int,size,int,flag);,void*,shmat,(int,shmid,void*,addr,int,flag);,int,shmdt,(void,*,addr,);,int,shmctl(int,shmid,int,cmd,struct,shmid_ds,*,buf,);,30,shmget,函数,#include,#include,#include,int,semget,(key_t,key,size_t,size,int,shmflag,);,成功返回一个共享内存标识符,失败返回,1,第一个参数,key,为共享内存段命名。,第二个参数,size,为需要共享的内存容量。(如果,key,已存在时,必须不大于该共享内存段的大小),第三个参数设置访问权限,(,低,9,位)和,IPC_CREAT,IPC_EXCL,按位或。,功能:获得或创建一个共享内存标识符。,31,shmget,函数(续),shmid,=,shmget,(key_t)1234,sizeof(struct,shared_use_st),0666|IPC_CREAT);,32,shmat,函数,#include,#include,#include,void*,shmat,(int,shm_id,const void*,addr,int,shmflg,);,成功返回共享存储段连接的实际地址,失败返回,-1,第一个参数,shm_id,为,shmget,返回的共享内存标识符。,第二个参数,shm_addr,指明共享内存段要连接到的地址,通常是,一个空指针,表示让系统来选择共享内存出现的地址。,第三个参数,shmflg,可以设置两个标志位,SHM_RND,(与,shm_addr,联合使用,控制内存连接的地址),SHM_RDONLY,要连接的共享内存段是只读的。,功能:将共享内存段连接到一个进程的地址空间中。,33,shmdt,函数,#include,#include,#include,int,shmdt,(const,void*,shmaddr,);,其中,shmaddr,为,shmat,返回的地址。,功能:将共享内存从当前进程中分离。,34,shmctl,函数,int,shmctl,(int,shm_id,int,command,struct,shmid_ds,*,buf,);,成功返回,0,,失败返回,-1,功能:查看及修改共享内存段的,shmid_ds,结构,删除该结构以及相连的共享存储段标识。,第二个参数,commad,取值:,IPC_STAT,buf,指向当前共享内存段的,shmid_ds,结构,IPC_SET,把共享内存段的当前关联值设置为,shmid_ds,结构给出的值,IPC_RMID,从系统中删除该共享存储段。,35,例,1,:生产者程序,int,main(void,),key=5678;,if(shmid,=,shmget(ke,y,SHMSZ,,,IPC_CREAT|0666,)0),exit(EXIT_FAILURE,);,if(shm,=shmat(shmid,NULL,0)=(char*)-1),exit(EXIT_FAILURE,);,s=,shm,;,for(c,=,a;c,=,z;c,+),*s+=c;,*s=NULL;,while(*,shm,!=*)sleep(1);,exit(EXIT_SUCCESS,);,36,int,main(void,),if(,shmid,=,shmget(key,SHMSZ,,,0666),written_by_you,=0;,39,while(running),while(shared_stuff-written_by_you=1),sleep(1);,printf(waiting for client.n);,printf(Enter some text:);,fgets(buffer,BUFSIZ,stdin);,strncpy(shared_stuff-some_text,buffer,TEXT_SZ);,shared_stuff-written_by_you=1;,if(strncmp(buffer,end,3)=0),running=0;,40,例,2,:消费者程序,int main(),shmid=shmget(key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);,shared_memory=shmat(shmid,(void*)0,0);,if(shared_memory=(void*)-1),fprintf(stderr,shmat failedn);,exit(EXIT_FAILURE);,printf(Memory attached at%Xn,(int)shared_memory);,41,shared_stuff=(struct shared_use_st*)shared_memory;,shared_stuff-written_by_you=0;,while(running),if(shared_stuff-written_by_you),printf(You wrote:%s,shared_stuff-some_text);,sleep(rand()%4);,shared_stuff-written_by_you=0;,if(strncmp(shared_stuff-some_text,“end”,3)=0),running=0;,42,消息队列,消息队列,消息队列是消息的链表,存放在内核中并由消息队列标识符标识。,First in,first out,消息独立于发送和接收进程而存在,块数据,每个数据块都含有一个类型,struct,msqid_ds,43,struct,msqid_ds,struct,msqid_ds,struct,ipc_perm,msg_perm,;,msgqnum_t,msg_qnum,;,/,消息的数量,msglen_t,msg_qbytes,;,/,最大消息的长度,pid_t,msg_lspid,;,/,最后一个发送到消息队列的进程,ID,pid_t,msg_lrpid,;,/,最后一个读取消息的进程,ID,time_t,msg_stime,;,/,最后一次发送到消息队列的时间,time_t,msg_rtime,;,/,最后一次读取消息的时间,time_t,msg_ctime,;,/,最后一次改变的时间,;,44,消息队列系统调用,#include,#include,#include,int,msgget,(key_t,key,int,flag);,int,msgsnd,(int,msqid,const void*,ptr,size_t,nbytes,int,flag);,int,msgrcv,(int,msqid,void*,ptr,size_t,nbytes,long,msgtype,int,flag);,int,msgctl,(int,msqid,int,cmd,struct,shmid_ds,*,buf,);,45,消息的结构,消息结构约束,必须小于系统规定的上限(,MSGMAX,),必须以长整型成员变量开始,表示消息的类型。,例:,struct,my_message,long,int,message_type,;,char qtext10;,46,msgsnd,和,msgrcv,int,msgsnd,(int,msqid,const void*,ptr,size_t,nbytes,int,msgflag);,int,msgrcv,(int,msqid,void*,ptr,size_t,nbytes,long,int,msgtype,int,msgflag);,其中:,nbytes,不包括长整型消息类型成员变量的长度。,msgrcv,的第四个参数,type,指明要接收的消息类型:,msgtype,=0,接收第一条消息,msgtype,0,接收其类型等于,msgtype,的第一个消息,msgtype,0,接收其类型小于或等于,msgtype,绝对值 的第一个消息,msgflag,可设置,IPC_NOWAIT,,一般为,0,47,#include,#include,#include,#include,#include,#define QKEY (key_t)0105,#define QPERM 0660,#define MAXOBN 50,#define MAXPRIOR 10,struct,q_entry,long,mtype,;,char mtextMAXOBN+1;,48,int,init_queue(void,),int,queue_id,;,if(queue_id,=,msgget,(QKEY,IPC_CREAT|QPERM,)=-1),perror(“msgget,failed”);,return(,queue_id,);,49,int,send(char,*,objname,int,priority),int,len,s_qid,;,struct,q_entry,s_entry,;,if(s_qid,=,init_queue,()=-1),return(-1);,s_entry.mtype,=(,long)priority,;,strncpy(s_entry.mtext,objname,MAXOBN,);,if(,msgsnd,(s_qid,&s_entry,len,0)=-1),perror(“msgsnd,failed”);,return(-1);,else,return 0;,50,int,receive(void,),if(r_qid,=,init_queue,()=-1),return(-1);,for(;),if(mlen,=,msgrcv,(r_qid,&r_entry,MAXOBN,(-,1*MAXPRIOR),0)=-1),perror(“msgrcv,failed”);,return(-1);,else,r_entry.mtextmlen,=0;,printf(“npriority:%ld,name:%sn”,msg,-,mtype,msg,-,mtext,);,51,msgctl,函数,函数原型,int,msgctl,(int,msqid,int,cmd,struct,msqid_ds,*,buf,);,“,cmd,”parameter,IPC_STAT:,把,msqid_ds,结构中的数据置为消息队列的当前关联值,IPC_SET:,在进程有足够权限的前提下,把消息队列的当前关联值置为,msqid_ds,结构给出的值,IPC_RMID:,删除消息队列,52,#define MAX_TEXT 512,struct,my_msg_st,long,int,my_msg_type,;,char,some_textMAX_TEXT,;,;,int,main(),int,running=1;,struct,my_msg_st,some_data,;,int,msgid,;,char,bufferBUFSIZ,;,msgid,=msgget(key_t)1234,0666|IPC_CREAT);,while(running,),printf(Enter,some text:);,fgets(buffer,BUFSIZ,stdin,);,some_data.my_msg_type,=1;,strcpy(some_data.some_text,buffer);,发送者程序,53,if(,msgsnd(msgid,(void*)&,some_data,MAX_TEXT,0)=-1),fprintf(stderr,msgsnd,failedn);,exit(EXIT_FAILURE,);,if(,strncmp(buffer,end,3)=0),running=0;,exit(EXIT_SUCCESS,);,54,int,main(),int,running=1;,int,msgid,;,struct,my_msg_st,some_data,;,long,int,msg_to_receive,=0;,msgid,=msgget(key_t)1234,0666|IPC_CREAT);,while(running,),if(,msgrcv(msgid,(void*)&,some_data,BUFSIZ,msg_to_receive,0)=-1),接收者程序,55,printf(You,wrote:%s,some_data.some_text,),if(,strncmp(some_data.some_text,end,3)=0),running=0;,if(,msgctl(msgid,IPC_RMID,0)=-1),56,
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服