共享内存(进程间通信)
ipcs (1) 命令可以查看系统中的进程间通信
针对于三种进程间通信 Message Queues
共享内存和信号量数组
system v ipc 对象(进程间通信的名字)
需要根据ID 获得键值。
如何获取键值?
ftok(3) 使用他获取一个 system v ipc 的键值
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
功能: 将 pathname 和proj_id 转换为system v ipc 的键值
参数 :
pathname : 指定一个存在的文件名字
proj_id : 使用这个数字的低有效8位
返回值:
如果 patchname 和proj_id 完全相同,得到的结果值也相同。
成功 返回生成的键值
失败 -1 errno 被设置
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
功能: 分配一个system v 的共享内存段
参数:
key: 指定一个键值
size: 指定了共享内存段的大小 如果给定1k,实际大小为4k
shmflg:
IPC_CREAT: 如果没有跟key 相关的共享内存段存在,创建
IPC_EXCL: 如果和上一个宏一起使用,如果有key 相关的共享内存段存在,则报错。
低有效9位,指定了授予共享内存段的权限
返回值:
成功 : 返回一个与key 相关的共享内存段的ID
错误 : -1 errno
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能 : 将共享内存段关联到当前进程的地址空间
参数:
shmid : 指定共享内存段的id
shmaddr : NULL 由系统选择合适的地址
shmflg : 0
返回值:
成功 : 返回共享内存段的地址
错误 (void *) -1 errno
int shmdt(const void *shmaddr);
功能 : 解除当前进程和共享内存段的关联
参数:
shmaddr : 指定共享内存段在当前进程的起始地址。
返回值
成功 0
错误 -1 errno
共享内存使用示例:
pa.c 向共享内存中写入 “hello beijing”
pb.c 从共享内存中读出数据,将读出的数据写到显示器
此进程在创建按共享内存
将数据放入共享内存
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <errno.h>
#include <sys/shm.h>
#include <string.h>
int main(int argc, char * argv[])
{
key_t key = ftok(argv[1], 123);
if (key == -1){
perror("get key");
return -1;
}
printf("key = %d \n", key);
int shmid = shmget(key,1024,IPC_CREAT| 0664);
printf("shmid = %d \n",shmid);
void * addr = shmat(shmid, NULL, 0);
if (addr == (void*) ( -1)){
perror("shmat");
return -1;
}
strcpy(addr, "hello beijing");
shmdt(addr);
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <errno.h>
#include <sys/shm.h>
#include <string.h>
从共享内存中获取相应的数据
int main(int argc, char * argv[])
{
key_t key = ftok(argv[1], 123);
if (key == -1){
perror("get key");
return -1;
}
printf("key = %d \n", key);
int shmid = shmget(key,1024,IPC_CREAT| 0664);
printf("shmid = %d \n",shmid);
void * addr = shmat(shmid, NULL, 0);
if (addr == (void*) ( -1)){
perror("shmat");
return -1;
}
printf("%s\n",(char *)addr);
shmdt(addr);
}