【Linux之进程间通信】06.Linux进程通信 - 共享内存
【Linux之进程间通信】
项目代码获取:https://gitee.com/chenshao777/linux-processes.git
(麻烦点个免费的Star哦,您的Star就是我的写作动力!)
06.共享内存
共享内存是Linux进程间的通信方式之一
创建共享内存函数
int shmget(key_t key, size_t size, int shmflg);
参数 | 含义 |
---|---|
key | IPC_PRIVATE或ftok()函数获取 |
size | 共享内存大小 |
shmflg | 权限 |
返回值:
成功返回共享内存描述符
失败返回-1
需要包含头文件
#include <sys/ipc.h>
#include <sys/shm.h>
共享内存和管道一样
有的共享内存只能在亲缘关系的进程间通信
有的可以在任意进程间通信
这取决于第一个参数 key
共享内存的创建(用于亲缘关系进程间)
参数 key 赋值为IPC_PRIVATE,表示用于亲缘关系进程
实例代码:
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>/*创建一个共享内存int shmget(key_t key, size_t size, int shmflg);参数:key : 用户给定的键值,IPC对象的名字size: 共享内存的大小shmflg: 共享内存的权限返回值:成功返回有效的共享内存标识符,失败返回-1查看内核中IPC对象: ipcs -m删除IPC对象: ipcrm -m shmid
*/
int main(int argc, char *argv[])
{int shm_id;//创建共享内存(亲缘进程)shm_id = shmget(IPC_PRIVATE, 100, 0777);if(shm_id < 0){printf("共享内存创建失败\n");}printf("共享内存创建成功,shm_id = %d\n",shm_id);//查看所有IPC对象system("ipcs -m");//删除IPC对象char cmd[50] = {0};sprintf(cmd, "ipcrm -m %d", shm_id);system(cmd);//查看所有IPC对象system("ipcs -m");return 0;
}
运行结果(创建内存段后再删除内存段):
共享内存创建成功,shm_id = 32778------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节 连接数 状态
0x00000000 32768 hc 600 524288 2 目标
0x00000000 32769 hc 600 524288 2 目标
0x00000000 32772 hc 600 524288 2 目标
0x00000000 6 hc 600 134217728 2 目标
0x00000000 32776 hc 600 524288 2 目标
0x00000000 32778 hc 777 100 0
0x00000000 15 hc 600 524288 2 目标
0x00000000 16 hc 600 524288 2 目标
0x00000000 19 hc 600 524288 2 目标 ------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节 连接数 状态
0x00000000 32768 hc 600 524288 2 目标
0x00000000 32769 hc 600 524288 2 目标
0x00000000 32772 hc 600 524288 2 目标
0x00000000 6 hc 600 134217728 2 目标
0x00000000 32776 hc 600 524288 2 目标
0x00000000 15 hc 600 524288 2 目标
0x00000000 16 hc 600 524288 2 目标
0x00000000 19 hc 600 524288 2 目标
可以看到通过 ipcs -m 命令获取到当前共享内存段中有
0x00000000 32778 hc 777 100 0
它的键值为 0,这表示它只能用于亲缘进程通信
共享内存的创建(任意进程间)
参数 key 值通过 ftok(const char *pathname, int proj_id) 函数获取
ftok(const char *pathname, int proj_id) 函数的第一个参数是文件路径,当前路径就可以,第二个参数是一个int类型的值,可实际上只有8位(1~127)
成功返回Key值,失败返回-1
示例代码:
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>/*创建一个共享内存int shmget(key_t key, size_t size, int shmflg);参数:key : 用户给定的键值,IPC对象的名字size: 共享内存的大小shmflg: 共享内存的权限返回值:成功返回有效的共享内存标识符,失败返回-1查看内核中IPC对象: ipcs -m删除IPC对象: ipcrm -m shmid
*/
int main(int argc, char *argv[])
{int shm_id;int key;key = ftok(".", 1);if(key < 0 ){printf("创建key失败\n");return -1;}shm_id = shmget(key, 100, IPC_CREAT | 0777);if(shm_id < 0){printf("共享内存创建失败\n");}printf("共享内存创建成功,shm_id = %d\n",shm_id);//查看所有IPC对象system("ipcs -m");//删除IPC对象char cmd[50] = {0};sprintf(cmd, "ipcrm -m %d", shm_id);system(cmd);//查看所有IPC对象system("ipcs -m");return 0;
}
注意的是,shmget函数第一个参数要换为key变量,第三个参数要加上IPC_CREAT宏
shmget(key, 100, IPC_CREAT | 0777);
运行结果:
共享内存创建成功,shm_id = 32802------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节 连接数 状态
0x00000000 32768 hc 600 524288 2 目标
0x00000000 32769 hc 600 524288 2 目标
0x00000000 32772 hc 600 524288 2 目标
0x00000000 6 hc 600 134217728 2 目标
0x00000000 32776 hc 600 524288 2 目标
0x00000000 15 hc 600 524288 2 目标
0x00000000 16 hc 600 524288 2 目标
0x00000000 19 hc 600 524288 2 目标
0x01011451 32802 hc 777 100 0 ------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节 连接数 状态
0x00000000 32768 hc 600 524288 2 目标
0x00000000 32769 hc 600 524288 2 目标
0x00000000 32772 hc 600 524288 2 目标
0x00000000 6 hc 600 134217728 2 目标
0x00000000 32776 hc 600 524288 2 目标
0x00000000 15 hc 600 524288 2 目标
0x00000000 16 hc 600 524288 2 目标
0x00000000 19 hc 600 524288 2 目标
发现这一行中,键值不为0了,代表此共享内存可以用于任意进程间通信
0x01011451 32802 hc 777 100 0
key值 具体如何生成?
key 31-24 proj_id 低8位
key 23-16 pathname的st_dev属性的低8位
key 15-0 pathname的st_ino属性的低16位
32位组合而成一个int值,就是我们的ftok的返回值了