共享内存数据结构
struct shmid_ds { struct ipc_perm shm_perm; //IPC对象数据结构 size_t shm_segsz; //共享内存段的大小 time_t shm_atime; //最后一次映射共享内存的时间 time_t shm_dtime; //最后一次解除映射的时间 time_t shm_ctime; //最后一次共享状态发生改变的时间 pid_t shm_cpid; //共享内存创建者的进程号 pid_t shm_lpid; // shmatt_t shm_nattch; //当前共享内存被连接的次数 ... };
共享内存函数
shmget函数
功能:
用来创建共享内存
原型:
int shmget(key_t key,size_t size,int shmflg);
参数
key:这个共享内存段名字
size:共享内存大小
shmflg:由9个权限标志构成,用法和创建文件时使用的mode模式标志一样
返回值:
成功返回一个非负整数,即该共享内存段的标识码,失败返回-1
shmat函数
功能:
将共享内存段连接到进程地址空间
原型:
void *shmat(int shmid,const *shmaddr,int shmflg);
参数
shmid:共享内存标识
shmaddr:指定连接的地址
shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY
关于第三个参数:
1.如果shmaddr 是NULL,系统将自动选择一个合适的地址!
2.如果shmaddr 不是NULL 并且没有指定SHM_RND则此段连接到addr所指定的地址上。
3.如果shmaddr非0并且指定了SHM_RND,则此段连接到shmaddr -(shmaddr mod SHMLAB)所表示的地址上。这里解释一下SHM_RND命令,它的意思是取整,而SHMLAB的意思是低边界地址的倍数,它总是2的乘方,该算式是将地址向下取最近一个SHMLAB(一般为4096)的倍数。 除非只计划在一种硬件上运行应用程序(在现在是不太可能的),否则不用指定共享段所连接到的地址。所以一般指定shmaddr为0,以便由内核选择地址。
4.shmflg=SHM_RDONLY,表示连接操作用来只读共享内存
返回值:
成功返回一个指针,指向映射区的起始地址,失败返回-1。
shmdt函数
功能:
将共享内存段与当前进程脱离
原型:
int shmdt(const void *shmaddr);
参数
shmaddr:由shmat所返回的值
返回值:
成功返回0,失败返回-1
注意:将共享内存与当前进程脱离不等于删除共享内存段
shmctl函数
功能:
用来创建和访问一个消息队列
原型:
int shmctl(int shmid,int cmd,struct shmid_ds *buf);
参数
shmid:由shmget返回的共享内存标识码
cmd:将要采取的动作(有三个可取值)
buf:指向一个保存着共享内存的模式状态和访问权限的数据结构(也就是动作命令带的参数)
返回值:
成功返回0,失败返回-1.
应用代码
shmwrite
#include <unistd.h> #include <sys/types.h> #include <sys/msg.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ }while(0) typedef struct stu { char name[32]; int age; }STU; int main(int argc,char *argv[]) { //创建一个共享内存 int shmid; //第二个参数是创建的共享内存的大小 shmid=shmget(1234,sizeof(STU),IPC_CREAT | 0666); if(shmid==-1) ERR_EXIT("shmget"); STU *p; //将这块内存连接到进程的地址空间中 //0表示连接的这块内存既可读又可写 p=shmat(shmid,NULL,0); if(p==(void*)-1) ERR_EXIT("shmat"); strcpy(p->name,"wangkai"); p->age=20; //判断数据是否被读走,若没有,则一直等待,不断开进程与共享内存区的连接 while(1) { if(memcmp(p,"quit",4)==0) break; } //断开进程与共享内存区的连接 shmdt(p); //从系统中删除由shmid标识的共享内存区并拆除它 shmctl(shmid,IPC_RMID,NULL); return 0; }
shmread
#include <unistd.h> #include <sys/types.h> #include <sys/msg.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ }while(0) typedef struct stu { char name[32]; int age; }STU; int main(int argc,char *argv[]) { //创建一个共享内存 int shmid; shmid=shmget(1234,0,0); if(shmid==-1) ERR_EXIT("shmget"); STU *p; //将这块内存连接到进程的地址空间中 //0表示连接的这块内存既可读又可写 p=shmat(shmid,NULL,0); if(p==(void*)-1) ERR_EXIT("shmat"); printf("name=%s age=%d\n",p->name,p->age); //读走以后将前4个字节置为quit,已提示发送方已收到,可以断开连接 memcpy(p,"quit",4); shmdt(p); return 0; }