共享内存,标准IPC之一,也是进程间通信最快的一种方式。
1.概念
所有的标准IPC都有一个内部ID作为唯一标识。内部ID的获取通过外部key,key的类型是key_t。key的获取方法有在头文件中定义所有key和通过ftok函数获取一个key。
key_t ftok(const char *pathname,int proj_id);
//pathname:有效的路径
//proj_id:非0的八位项目ID,一般采用一个字符
通过key获取内部ID的函数都叫做xxxget。
所有的标准IPC结构都提供一个xxxctl函数,该函数至少包含了查询,修改和删除的功能。
所有IPC都是由内核管理,不需要手动删除。
2.共享内存(shared memory)
(1)原理
内核以一块物理内存作为媒介,通常情况下一块物理内存只允许一个进程映射,共享内存实现了:允许所有进程对这块物理内存进行映射,当多个内存映射到这同一片内存空间时,便可以理解为进行了数据间的交换。
(2)编程使用
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/shm.h>
int main()
{
//1.获取key
key_t key=ftok("./",'x');
//2.使用shmget函数通过key创建/获取共享内存
int shmid=shmget(key,100,IPC_CREAT|0666);
//shmget参数一:上一步获取到的key,参数二:共享内存大小,参数三:创建时使用IPC_CREAT|0666
//3.使用shmat将共享内存映射到用户空间
char *p=shmat(shmid,NULL,0);
//shmat参数一:上一步获取的共享内存,参数二:映射地址,通常给零让系统自主选择,参数三:映射标志,通常给0
//4.像访问普通内存一样去访问共享内存(读/写)
//子进程写
if(!fork())
{
while(1)
{
printf("请写入:");
fgets(p,sizeof(p),stdin);
strtok(p,"\n");
printf("写入了%ld字节内容\n",strlen(p));
}
}
//父进程读
while(1)
{
printf("读到了%ld字节内容:%s\n",strlen(p),p);
sleep(3);
}
//5.解除映射
shmdt(p);
return 0;
}
以上只是使用例子,存在着实际不为合理的地方,供了解使用。
(3)shmcl函数
int shmcl(int shmid,int cmd,struct shmid_ds *buf);
//shmid:共享内存ID
//cmd:操作命令:IPC_STAT查询,IPC_SET修改,IPC_RMID删除
//buf:查询和修改时使用,查询时传出共享内存信息,设置时传入共享内存信息
struct shmid_ds {
struct ipc_perm shm_perm; /* 所有者和权限 */
size_t shm_segsz; /* 共享内存大小 */
time_t shm_atime; /* 最后挂接时间 */
time_t shm_dtime; /* 最后脱接时间 */
time_t shm_ctime; /* 最后一次修改时间 */
pid_t shm_cpid; /* 创建者PID */
pid_t shm_lpid; /* 最后挂接/脱接PID */
shmatt_t shm_nattch; /* 当前挂接进程数 */
...
};
struct ipc_perm {
key_t __key; /* key的值 */
uid_t uid; /* --所有者ID */
gid_t gid; /* --所有者组ID */
uid_t cuid; /* 创建者ID */
gid_t cgid; /* 创建者组ID */
unsigned short mode; /* --权限 + SHM_DEST and
SHM_LOCKED flags */
unsigned short __seq; /* Sequence number */
};
//其中只有uid,gid和mode可以修改