您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > 42linux高级编程-5
HauboTrainingCenterLinux高级程序设计-5张勇涛共享内存共享内存进程一进程二共享内存什么是共享内存共享内存区域是被多个进程共享的一部分物理内存。如果多个进程都把该内存区域映射到自己的虚拟地址空间,则这些进程就都可以直接访问该共享内存区域,从而可以通过该区域进行通信。共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容。共享内存由进程创建,但是进程结束时共享内存仍然保留,除非该共享内存被显示的删除戒重启系统。ipcs–m查看系统中共享内存的基本信息实现共享内存的步骤一、创建共享内存,使用shmget函数。二、映射共享内存,将这段创建的共享内存映射到具体的进程空间去,使用shmat函数。注意:共享内存由进程创建,但是进程结束时,共享内存仍然保留,除非是共享内存被显示地删除或重启操作系统.共享内存的创建系统调用:shmget();原型:intshmget(key_tkey,intsize,intshmflg);参数:key是共享内存的关键字,size指定共享内存的大小shmflg的低9位决定了共享内存属主,属组,和其它用户的访问权限,其它位指定了共享内存的创建方式返回值:如果成功,返回共享内存段标识符。如果失败,则返回-1:消息队列创建方式参数:参数描述IPC_CREAT创建共享内存,如果共享内存已经存在,就获取共享内存的标示符IPC_EXCL与宏IPC_CREAT一起使用,单独使用无意义,此时只能创建一个不存在的共享内描述存,如果内存已经存在则调用失败系统调用:shmget()注意:当参数key的取值为IPC_PRIVATE时,将创建关键字为0的共享内存,UNIX内核中可以同时存在多个关键字为0的共享内存系统调用:shmget()errno=EINVAL(无效的内存段大小)EEXIST(内存段已经存在,无法创建)EIDRM(内存段已经被删除)ENOENT(内存段不存在)EACCES(权限不够)ENOMEM(没有足够的内存来创建内存段)共享内存的映射系统调用:shmat();原型:void*shmat(intshmid,char*shmaddr,intshmflg);返回值:如果成功,则返回共享内存段连接到进程中的地址。如果失败,则返回-1:errno=EINVAL(无效的IPCID值或者无效的地址)ENOMEM(没有足够的内存)EACCES(存取权限不够)在绝大部分情况,我们指定参数shmaddr值为NULL标志位,系统将自劢确认共享内存链接到进程空间的首地址。共享内存的释放当一个进程不在需要共享的内存段时,它将会把内存段从其地址空间中脱离。系统调用:shmdt();调用原型:intshmdt(char*shmaddr);返回值:如果失败,则返回-1;errno=EINVAL(无效的连接地址)共享内存的例子shm1.cshm2.c共享内存与管道1.使用共享内存机制通讯的两个线程必须在同一台物理机器上2.共享内存的访问方式是随机的,而不是只能从一端写,从另一端读,因此,其灵活性比管道和套接字大的多,能够传从的信息也复杂的多。共享内存的缺点1.管理复杂,两个进程必须在同一台物理机器上才能使用这种方式。2.安全性脆弱。消息队列IPC(interprocesscommunication)广义上一切能是进程间互相交流的对象和方法都是IPC,比如文件、管道、socket等。狭义上的IPC特指消息队列、信号量和共享内存三种对象。IPC的应用范围:消息队列应用于不同进程之间少量数据的顺序共享。信号量应用于进程间的同步与互斥的控制。共享内存则应用于进程间大批量数据的随机共享访问。管道的缺陷管道是一种最古老的方式,他不打包就直接发送过去了消息队列的优点1.消息队列先进先出2.消息队列将输出的信息进行了打包处理,这样就可以保证以每个消息为单位进行接收。3.消息队列可以对货物进行分类服务,标记各类别的货物,这样可以根据货物类别分别出货。消息队列消息队列就是消息的一个链表,它允许一个戒多个进程向它写消息,一个戒多个进程从中读消息。具有一定的FIFO的特性,但是可实现消息的随即查询。这些消息存在于内核中,由“队列ID”来标识。消息队列的实现包括创建和打开队列、添加消息、读取消息和控制消息队列这四种操作。msgget:创建和打开队列,其消息数量受系统限制。msgsnd:添加消息,将消息添加到消息队列尾部。msgrcv:读取消息,从消息队列中取走消息。msgctl:控制消息队列。消息队列的创建intmsgget(key_tkey,intflag)key:返回新的或已有队列的ID,IPC_PRIVATEflag:低9位决定了共享内存属主,属组,和其它用户的访问权限,其它位指定了共享内存的创建方式消息队列创建方式参数:取值描述IPC_CREAT创建消息队列,如果消息队列已经存在,就获取消息队列的标示符IPC_EXCL与宏IPC_CREAT一起使用,单独使用无意义,此时只能创建一个不存在的共享内存,如果内存已经存在则调用失败消息队列发送函数#includesys/ipc.h#includesys/types.h#includemsg.hintmsgsnd(intmsqid,structmsgbuf*msgp,size_tmsgsz,intmsgflag)参数:msqid是消息队列的队列ID;msgp是消息内容所在的缓冲区;msgsz是消息的大小,不包括消息类型部分而且取值必须大于0;msgflg是控制消息发送的方式,当前有堵塞和非堵塞两种。如果设置了IPC_NOWAIT,消息采用非阻塞方式发送,否则采取阻塞方式发送。msgsnd堵塞的原因是:1.消息队列满2.消息总数满msgsnd返回情况表情况Msgflg设置返回值errno消息发送成功0无消息队列被删除-1EIDRM信号中断-1EINTR消息发送阻塞设置IPC_NOWAIT-1EAGAIN未设置等待直到堵塞条件消失戒者异常出现消息队列发送模型1.定义消息结构2.打开/创建消息队列3.组装消息4.发送消息5.发送判断1.消息结构structmsgbuf{longmtype;/*typeofmessage*/charmtext[100];/*messagetext*/};2.打开/创建消息队列intmsid;/*打开(戒创建)消息队列*/if((msid=msgget(0x1234,0666|IPC_CREAT))0){fprintf(stderr,openmsg%Xfailed.\n,0x1234);return;}3.组装消息structmymsgbufbuf;/*申请消息缓冲*/buf.mtype=100;strcpy(buf.ctext,“helloworld\n”);4.发送消息/5.发送判断while((msgsnd(msid,&buf,strlen(buf.ctext),0))0){if(errno==EINTR)continue;return;}消息队列接收函数#includesys/ipc.h#includesys/types.h#includemsg.hintmsgrcv(intmsqid,structmsgbuf*msgp,size_tmsgsz,longmsgtyp,intmsgflg)msqid是消息队列的引用标识符;msgp是接收到的消息将要存放的缓冲区;msgsz是消息的大小;msgtyp是期望接收的消息类型;msgflg是标志。msgrcv返回情况表情况msgflg设置返回值errno队列情况消息接收成功实际接收消息的长度无删除消息消息队列被删除-1EIDRM已删除信号中断-1EINTR无满足要求的信息IPC_NOWAIT-1EAGAIN未设置等待直到堵塞条件消失或异常出现消息数据的长度大于msgszMSG_NOERRORmsgsz无截断消息未设置-1E2BIG删除消息消息队列接收模型1.定义消息结构2.打开/创建消息队列3.准备接受消息缓冲区4.接收消息5.接收判断消息队列的例子msg1.cmsg2.c消息队列的控制#includesys/ipc.h#includesys/types.h#includemsg.hintmsgctl(intmsqid,intcmd,structmsqid_ds*buf)功能:对消息队列执行各种控制,包括查询消息队列数据结构,改变消息队列的访问权限、改变消息队列属主信息和删除消息队列等消息队列与管道消息队列和管道都是一头写,一头读!消息队列和管道的不同点:1.消息队列无需固定的读写进程,任何进程都可以读写2.消息队列可以支持多个进程,多个进程可以读写消息队列,即消息队列可以实现多对多,而管道只能是点对点3.消息队列只在内存中实现。4.消息队列不是只在UNIX和类UNIX操作系统中实现。几乎所有主流操作系统都支持消息队列。
本文标题:42linux高级编程-5
链接地址:https://www.777doc.com/doc-6203131 .html