赞
踩
共享内存通过页表映射到进程的进程虚拟地址空间的共享区中,进程通过操控共享区的内容,间接操作共享内存中的内容
不同的进程将同一块共享内存映射到自己的共享区中,通过操作各自的共享区,以达到进程间数据交换
shmget函数
int shmget(key_t key, size_t size, int shmflg);
功能:开辟一段共享内存,用共享内存标识符key去标识这块内存,并返回共享内存的操作句柄
头文件:
参数:
宏 | 含义 |
---|---|
IPC_CREAT | 若共享内存不存在,则创建 |
IPC_EXCL | 与IPC_CREAT一同使用,为了确保共享内存已经存在时,会报告错误 |
返回值:创建成功返回 共享内存操作句柄 ,创建失败返回 -1
共享内存标识符:用于唯一标识某块共享内存的,进程可以通过共享内存标识符找到这块共享内存
共享内存操作句柄:用于操作这块内存的
代码演示shmget函数
#include <stdio.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/shm.h> #define KEY 0x89898989 int main() { int shmid = shmget(KEY,1024,IPC_CREAT); if(shmid < 0) { perror("shmget"); return -1; } printf("shmid : %d\n",shmid); return 0; }
[gongruiyang@localhost Testshm]$ ./shm
shmid : 425985
ipcs命令用于查看所有进程间通信(IPC)信息,-m选项是所有信息中过滤出共享内存段的进程间通信信息
ipcs -m
命令演示
[gongruiyang@localhost Testshm]$ ipcs -m
------------ 共享内存段 --------------
key shmid owner 权限 字节 nattch status
0x00000000 262144 gongruiyan 600 524288 2 dest
0x89898989 425985 gongruiyan 0 1024 0 dest
0x00000000 393218 gongruiyan 600 524288 2 dest
上面的程序创建了一个进程标识符为0x89898989的共享内存段,虽然程序已经执行结束,但是共享内存段仍然存在,说明共享内存的生命周期的结束不是跟随程序的,而是跟随内核的
ipcrm用于删除进程间通信资源,-m代表删除的是共享内存段
ipcrm -m 共享内存操作句柄
命令演示
[gongruiyang@localhost Testshm]$ ipcs -m
------------ 共享内存段 --------------
key shmid owner 权限 字节 nattch status
0x00000000 262144 gongruiyan 600 524288 2 dest
0x89898989 425985 gongruiyan 0 1024 0 dest
0x00000000 393218 gongruiyan 600 524288 2 dest
[gongruiyang@localhost TestPipeCS]$ ipcrm -m 425985
[gongruiyang@localhost TestPipeCS]$ ipcs -m
------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节 nattch 状态
0x00000000 262144 gongruiyan 600 524288 2 dest
0x00000000 393218 gongruiyan 600 524288 2 dest
由上面程序创建出来的共享内存的权限为0可以看出,我们对该共享内存无任何权限,我们可以在创建共享内存的时候对共享内存属性进行修改,增加 权限
int shmid = shmget(KEY,1024,IPC_CREAT | 0664);
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:将指定的共享内存段映射到进程虚拟地址的共享区中的某一块中
头文件:
参数:
宏 | 含义 |
---|---|
SHM_RDONLY | 规定当前进程对该共享内存有 只读权限 |
0 | 规定当前进程对该共享内存有 读写权限 |
返回值:返回 映射到的共享区 的地址
程序演示
#include <stdio.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/shm.h> #define KEY 0x89898989 int main() { int shmid = shmget(KEY,1024,IPC_CREAT | 0664); if(shmid < 0) { perror("shmget"); return -1; } void* lp = shmat(shmid,NULL,0); //让系统分配共享区,该进程对共享内存的权限为 可读可写 printf("%p\n",lp); return 0; }
[gongruiyang@localhost Testshm]$ ./shm
0xffffffffffffffff
程序思路:
程序演示:单进程对共享内存进行读写操作
#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/ipc.h> #include <sys/shm.h> #define KEY 0x89898989 int main() { //1.创建一块共享内存标识符为KEY的共享内存 int shmid = shmget(KEY,1024,IPC_CREAT | 0664); if(shmid < 0) { perror("shmget"); return -1; } //2.将创建出来的共享内存附加到本进程中,让系统分配共享区,权限为读写 void* lp = shmat(shmid,NULL,0); //3.本进程向共享内存中写入数据 const char* w_buf = "Hello World!\n"; strcpy((char*)lp,w_buf); //4.本进程从共享内存中读取数据 printf("%s\n",lp); return 0; }
程序演示:一个进程写入数据 一个进程读取数据
读进程
#include <stdio.h> #include <unistd.h> #include <sys/shm.h> #include <string.h> #define KEY 0x89898989 int main() { int shmid = shmget(KEY, 1024, IPC_CREAT | 0664); if(shmid < 0) { perror("shmget"); return -1; } void* lp = shmat(shmid, NULL, 0); printf("%s\n", (char*)lp); while(1) { sleep(1); } return 0; }
写进程
#include <stdio.h> #include <unistd.h> #include <sys/shm.h> #include <string.h> #define KEY 0x89898989 int main() { int shmid = shmget(KEY, 1024, IPC_CREAT | 0664); if(shmid < 0) { perror("shmget"); return -1; } const char* w_buf = "Hello World!\n"; void* lp = shmat(shmid, NULL, 0); strcpy((char*)lp, w_buf); while(1) { sleep(1); } return 0; }
进程读取共享内存中数据时,并不会将共享内存中的数据拿走,数据依然存在共享内存之中
int shmdt(const void *shmaddr);
功能:将进程中附加到共享区的某个共享内存段进行分离开
头文件:
参数:
返回值:0 代表分离成功 ; -1 代表分离失败
程序演示
#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/ipc.h> #include <sys/shm.h> #define KEY 0x89898989 int main() { //1.创建一块共享内存标识符为KEY的共享内存 int shmid = shmget(KEY,1024,IPC_CREAT | 0664); if(shmid < 0) { perror("shmget"); return -1; } //2.将创建出来的共享内存附加到本进程中,让系统分配共享区,权限为读写 void* lp = shmat(shmid,NULL,0); while(1) { sleep(1); } return 0; }
[gongruiyang@localhost Testshm]$ ipcs -m
------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节 nattch 状态
0x00000000 262144 gongruiyan 600 524288 2 dest
0x89898989 524289 gongruiyan 664 1024 1
0x00000000 393218 gongruiyan 600 524288 2 dest
由此可以看出:附加在 共享内存标识符为0x89898989 上的进程数量nattch为1
进程分离后的程序及现象
#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/ipc.h> #include <sys/shm.h> #define KEY 0x89898989 int main() { //1.创建一块共享内存标识符为KEY的共享内存 int shmid = shmget(KEY,1024,IPC_CREAT | 0664); if(shmid < 0) { perror("shmget"); return -1; } //2.将创建出来的共享内存附加到本进程中,让系统分配共享区,权限为读写 void* lp = shmat(shmid,NULL,0); //将本进程与共享内存分离 int ret_shmdt = shmdt(lp); if(ret_shmdt < 0) perror("shmdt"); else printf("shmdt success!\n"); while(1) { sleep(1); } return 0; }
[gongruiyang@localhost Testshm]$ ipcs -m
------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节 nattch 状态
0x00000000 262144 gongruiyan 600 524288 2 dest
0x89898989 557057 gongruiyan 664 1024 0
0x00000000 393218 gongruiyan 600 524288 2 dest
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:操作共享内存的属性
头文件:
参数:
宏 | 含义 |
---|---|
IPC_STAT | 获取共享内存属性,将指定的共享内存属性填入buf中 |
IPC_SET | 设置共享内存数,将指定的共享内存属性按照buf设置 |
IPC_RMID | 删除共享内存,buf直接传递NULL |
shmid_ds结构体源码
struct shmid_ds { struct ipc_perm shm_perm; /* Ownership and permissions */ size_t shm_segsz; /* Size of segment (bytes) */ time_t shm_atime; /* Last attach time */ time_t shm_dtime; /* Last detach time */ time_t shm_ctime; /* Last change time */ pid_t shm_cpid; /* PID of creator */ pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */ shmatt_t shm_nattch; /* No. of current attaches */ ... }; struct ipc_perm { key_t __key; /* Key supplied to shmget(2) */ uid_t uid; /* Effective UID of owner */ gid_t gid; /* Effective GID of owner */ uid_t cuid; /* Effective UID of creator */ gid_t cgid; /* Effective GID of creator */ unsigned short mode; /* Permissions + SHM_DEST and SHM_LOCKED flags */ unsigned short __seq; /* Sequence number */ };
程序演示:获取共享内存属性,并输出共享内存大小
#include <stdio.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/shm.h> #define KEY 0x89898989 int main() { int shmid = shmget(KEY,1024,IPC_CREAT | 0664); if(shmid < 0) { perror("shmget"); return -1; } struct shmid_ds buf; shmctl(shmid, IPC_STAT, &buf); // 获取 共享内存段 大小 printf("shm size : %ld字节\n",buf.shm_segsz); return 0; }
[gongruiyang@localhost Testshm]$ ./shm
shm size : 1024字节
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。