文章目录
一.基本概念
引入:
无名管道、有名管道、信号通信都是通过在内核空间的对象进行通信。
IPC通信所涉及到的函数:
二.共享内存
1.共享内存的创建
- 函数原型
int shmget(key_t key,int size,int shmflg)
函数参数
key:IPC_PRIVATE或ftok的返回值
size:共享内存区大小
shmg:同open函数的权限位,也可以用8进制表示法
函数返回 成功:共享内存段标识符一D-文件描述符; 出错:-1
eg1:
#include "sys/types.h"
#include "sys/shm.h"
#include "signal.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
int main()
{
int shmid;
shmid=shmget(IPC_PRIVATE,128,0777);
if(shmid <0)
{
printf("creat share memory failure\n");
return -1;
}
printf("creat share memory sucess shmid=%d\n",shmid);
system("ipcs -m");//查看ipc对象
sytem("ipcrm -m");//删除ipc对象
return 0;
}
备注:
查看内核中IPC对象的命令: ipcs -m
删除IPC :ipcrm -m id
system()函数返回值:成功,则返回进程的状态值;当sh不能执行时,返回127;失败返回-1;
(1) key:IPC_PRIVATE或ftok的返回值,两种方式所获得的key的区别
通过ftok的返回值创建的key:
ftok:创建key值。
char ftok(const char *path,char key)
参数:第一个参数:文件路径和文件名;
第二个参数:一个字符。
返回值:正确返回一个k值,出错返回-1
eg2:
#include "sys/types.h"
#include "sys/shm.h"
#include "signal.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
int main()
{
int shmid;
int key;
//char *p;
key=ftok("./a.c",'a');
if(key <0)
{
printf("creat key fialure\n");
return -2;
}
printf("creat key success key=%x\n",key);
shmid=shmget (key,128,IPC_CREAT | 0777);//shmet在内核空间创建一个共享内存
if(shmid <0)
{
printf("creat share memory failure\n");
return -1;
}
printf("creat share memory sucess shmid=%d\n",shmid);
system("ipcs -m");
/*
p= (char*) shmat(shmid,NULL,0);//可以将共享内存映射到用户空间去
if(p=NULL)
{
printf("shmat function failure\n");
return -3;
}
// write share memory
fgets(p,128,stdin);
// read share memory
printf("share memory data:'s",p);
// printf("sencond read share memory data:'s",p);//这句话还能读出来
**去享内存特点:**
共享内存创建之后,一直存在于内核中,直到被删除或系统关闭:
共享内存和管道不一样,读取后,内容仍在其共享内存中。
*/
return 0;
}
对比结果:IPC_PRIVATE操作时,共享内存的key值都一样,都是0。使用ftok来创建key值,对于不同的ftok函数的参数,key值不相同。只要key值是一样的,用户空间的进程通过这个函数打开,则会对内核的同一个IPC对象操作。具体区别:类似无名管道和有名管道的区别
(2)共享内存的映射:shmat将共享内存映射到用户空间中
能不能用read,write呢?read write必须每次都要进入内核
为了方便用户空间对共享内存的操作,使用地址映射的方式。
shmat函数功能:可以将共享内存映射到用户空间去,好处:可以在用户空间对内核的共享内存进行操作。
void *shmat (int shmid,const void *shmaddr,int shmflg);
参数:第一个参数:需要映射的共享内存的ID号;
第二个参数:映射到的地址,NULL为系统自动完成的映射;
第三个参数shmflg:
SHM_RDONLY共享内存只读; 默认是0,表示共享内存可读写。
返回值:成功:映射后的地址
失败:NULL
**共享内存特点:**
共享内存创建之后,一直存在于内核中,直到被删除或系统关闭;
共享内存和管道不一样,读取后,内容仍在其共享内存中。
2.共享内存的删除
(1)shmdt:将进程里的地址映射删除(删除用户空间的映射内存)
int shmdt(const void *shmaddr)
参数:shmaddr共享内存映射后的地址
返回值:成功:0
出错:1
在上述eg2加上:
shmdt (p);//删除在用户空间的内存
memcpy(p,"abcd",4)//执行出现断错误 ,删除之后不可以再进行操作
(2)shmctl : 删除内核空间的共享内存对象。
函数原型:int shmctl(int shmid,int cmd,struct shmi_ds*buf)
函数参数:shmid:要操作的共享内存标识符。
cmd:
IPC_STAT(获取对象属性)实现了命令ipcs -m
IPC_SET(设置对象属性)
IPC_RMID(删除对象) 实现了命令ipcrm -m
buf: 指定IPC_STAT/PC SET时用以保存/设置属性。
函数返回值:成功:0; 出错:-1
在上述eg2加上:
shmctl(shmid,IPC_RMID,NULL);//删除内核空间的共享内存
system("ipcs -m");//查看对象 已经被删除查看不到