Linux共享内存、消息队列通信详解

    技术2022-07-10  129

    ##共享内存通信 在linux内核中创建一段共享内存,使用shmget函数: #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); 第一个参数key定义是否创建一个带密钥的共享内存。

    include <stdio.h> #include <sys/shm.h> #include <signal.h> #include <unistd.h> #include <sys/types.h> #include <stdlib.h> int main() { int shmid; int key; key=ftok("./a.c",'a'); if(key<0) { printf("creat key failure\n"); return -1; } printf("creat key sucess key=%X\n",key); shmid=shmget(key,128,IPC_CREAT|0777); if(shmid<0) { printf("creat share memory failure\n"); return -1; } printf("creat share memory sucess shmid=%d\n",shmid); system("ipcs -m"); system("ipcrm -m shmid"); return 0; }

    shmat:将共享内存映射到用户空间. void *shmat(int shmid, const void *shmaddr, int shmflg); 返回值为指针类型,指向用户空间的某个地址,该地址可通过shmaddr变量进行设置。若由内存自行分配,可以设置为NULL

    shmdt:将用户空间的映射内存删除 int shmdt(const void *shmaddr);

    shmctl:对用内核空间的共享内存进行操作 1、读取对象属性 2、设置对象属性 3、删除对象属性 int shmctl(int shmid, int cmd, struct shmid_ds *buf);

    #include <stdio.h> #include <sys/shm.h> #include <signal.h> #include <unistd.h> #include <sys/types.h> #include <stdlib.h> #include <string.h> int main() { int shmid; int key; char *p; key=ftok("./a.c",'a'); if(key<0) { printf("creat key failure\n"); return -1; } printf("creat key sucess key=%X\n",key); shmid=shmget(key,128,IPC_CREAT|0777); if(shmid<0) { printf("creat share memory failure\n"); return -1; } printf("creat share memory sucess shmid=%d\n",shmid); system("ipcs -m"); p=(char *)shmat(shmid,NULL,0); if(p==NULL) { printf("shmet function failure\n"); return -3; } fgets(p,128,stdin); printf("share memory data:%s",p); shmdt(p); // memcmp(p,"abcd",4); shmctl(shmid,IPC_RMID,NULL); system("ipcs -m"); return 0; }

    对共享内存的总结: 对共享内存的实现步骤:首先要创建内存空间,将内存空间映射到用户空间,使用标准输入输出函数对内存内容进行读取,(共享内存可分为有血缘关系的用户进程和无血缘关系的用户进程,这里可以通过是否选择ftok创建key值)然后是删除共享内存空间。 ##消息队列 在linux内核中通过msgget打开或创建队列。 #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgget(key_t key, int msgflg); 通过msgsnd和msgrcv函数来队列发送信息或从内核接收信息 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); 下列代码是实现队列的双向通信 A进程

    #include <stdio.h> #include <stdlib.h> #include <sys/msg.h> #include <signal.h> #include <unistd.h> #include <string.h> #include <sys/types.h> struct msgbuf { long type; char voltage[124]; char ID[4]; }; int main() { int msgid; int readret; int key; int pid; struct msgbuf sendbuf,revbuf; key=ftok("./a.c",'a'); if(key<0) { printf("creat key filure\n"); return -2; } msgid=msgget(key,IPC_CREAT|0777); if(msgid<0) { printf("creat message queue failure\n"); return -1; } printf("creat message queue sucess:msgid=%d\n",msgid); system("ipcs -q"); pid=fork(); if(pid==0)// { sendbuf.type=200; while(1) { memset(sendbuf.voltage,0,124); printf("please input message:\n"); fgets(sendbuf.voltage,124,stdin); msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.voltage),0); } } if(pid>0) { while(1) { memset(revbuf.voltage,0,124); msgrcv(msgid,(void *)&revbuf,124,100,0); printf("revbuf.voltage=%s\n",revbuf.voltage); } } //删除消息队列 msgctl(msgid,IPC_RMID,NULL); system("ipcs -q"); return 0; }

    B进程

    #include <stdio.h> #include <stdlib.h> #include <sys/msg.h> #include <signal.h> #include <unistd.h> #include <string.h> #include <sys/types.h> struct msgbuf { long type; char voltage[128]; char ID[4]; }; int main() { int msgid; int readret; int key; int pid; struct msgbuf sendbuf,revbuf; key=ftok("./a.c",'a'); if(key<0) { printf("creat key filure\n"); return -2; } msgid=msgget(key,IPC_CREAT|0777); if(msgid<0) { printf("creat message queue failure\n"); return -1; } printf("creat message queue sucess:msgid=%d\n",msgid); system("ipcs -q"); pid=fork(); if(pid>0)// { sendbuf.type=100; while(1) { memset(sendbuf.voltage,0,128); printf("please input message:\n"); fgets(sendbuf.voltage,128,stdin); msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.voltage),0); } } if(pid==0) { while(1) { memset(revbuf.voltage,0,128); msgrcv(msgid,(void *)&revbuf,128,200,0); printf("revbuf.voltage=%s\n",revbuf.voltage); } } /* system("ipcs -q"); memset(revbuf.voltage,0,128); readret=msgrcv(msgid,(void *)&revbuf,128,100,0); printf("revbuf.voltage=%s\n",revbuf.voltage); */ //删除消息队列 msgctl(msgid,IPC_RMID,NULL); system("ipcs -q"); return 0; }

    结构体中long字段必须具有严格的正整数值。 接收过程可以使用此值进行消息选择。

    Processed: 0.011, SQL: 9