共享内存的特点:
共享内存创建后一直存在于内核中,直到被删除或系统关闭;
共享内存和管道不一样,读取后,内容仍然存在。
shm_get函数: 共享内存的创建
头文件: #include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
函数原型: int shmget(key_t key, int size, int shmflg)
函数参数: key:IPC_PRIVATE 或 ftok的返回值
size:共享内存区大小
shmflg:同open函数的权限位,也可以用8进制表示
返回: 成功:共享内存段标识符,ID,文件描述符
失败:-1
查看IPC对象:ipcs -m 共享内存/ -p 消息队列/ -s 信号灯
删除IPC对象:ipcrm -m/-p/-s id
例:shmid=shmget(IPC_PRIVATE,128,0777);
使用shmget函数创建共享内存时,参数如果是IPC_PRIVATE,则共享内存的key值都一样,为0。如果要使key非0,则需要借助函数ftok。
ftok函数:
原型: char ftok(const char *path, char key)
参数: path:文件路径和文件名
key:一个字符
返回值:成功返回一个key值
失败-1
例:key=ftok("./a.c",‘b’);
shmid=shmget(key,128,IPC_CREAT | 0777);
shmat函数: 创建了共享内存后需要将内存映射到用户空间,减少内核访问。
原型:void *shmat(int shmid, const void *shmaddr, int shmflg) //类似于malloc
参数: 第一个参数,ID号
第二个参数,映射到的地址,NULL为系统自动完成的映射
第三个参数,shmflg, SHM_RDONLY共享内存只读
默认是0,表示可读写
返回: 成功映射后的地址
失败NULL
例:p=(char *)shmat(shmid,NULL,0);
shmdt函数: 删除进程中的地址映射
原型: int shmdt(const void *shmaddr)
参数: shmaddr共享内存映射后的地址
返回: 成功0,出错-1
例:shmdt(p );
shmctl函数: 删除共享内存对象
原型: int shmctl(int shmid, int cmd, struct shmid_ds * buf)
参数: shmid,要操作的共享内存标识符
cmd: IPC_STAT,获取对象属性值 //实现了命令ipcs -m
IPC_SET,设置对象属性
IPC_RMID,删除对象 //实现了命令ipcrm -m
buf: 指定IPC_STAT/IPC_SET时用以保存/设置属性
返回: 成功0,出错-1
例:shmctl(shmid,IPC_RMID,NULL);
父子进程通信
父进程完成内存映射后,等待读取用户输入信息;当输入完成后,通过kill向子进程发送SIGUSR1信号告知有消息可读,同时父进程进入睡眠状态;
子进程完成内存映射后,就进入休眠状态;当收到信号后,进程唤醒,并从共享内存中读取信息;读取完成后向父进程发送SIGUSR2信号,告知,信息被读取,你可以继续输入了。
#include "sys/shm.h"
#include "signal.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
void myfun(int signum)
{
return ;
}
int main()
{
int shmid;
int key;
char *p;
int pid;
shmid=shmget(IPC_PRIVATE,128,IPC_CREAT | 0777);
if(shmid <0)
{
printf("creat share memory failure\n");
return -1;
}
printf("creat share memory sucess shmid=%d\n",shmid);
pid=fork();
if(pid > 0)//parent process
{
signal(SIGUSR2,myfun);//kill默认终止进程,需加处理函数
p=(char *)shmat(shmid,NULL,0);
if(p == NULL)
{
printf("parent process:shmat function failure\n");
return -3;
}
while(1)
{
//write share memory
printf("parent process start write share memory:\n");
fgets(p,128,stdin);
kill(pid,SIGUSR1);// child process read data
pause();// wait child process read
}
}
if(pid == 0)//child process
{
signal(SIGUSR1,myfun);
p=(char *)shmat(shmid,NULL,0);
if(p == NULL)
{
printf("child process shmat function failure\n");
return -3;
}
while(1)
{
pause();// wait parent process write
//start read share memory
printf("share memory data:%s",p);
kill(getppid(),SIGUSR2);
}
}
shmdt(p);
shmctl(shmid,IPC_RMID,NULL);
system("ipcs -m ");
return 0;
}
执行结果:
creat share memory sucess shmid=2228235
parent process start write share memory:
hello
share memory data:hello
非亲缘关系进程通信
server
#include "sys/types.h"
#include "sys/shm.h"
#include "signal.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
struct mybuf
{
int pid;
char buf[124];
};
void myfun(int signum)
{
return ;
}
int main()
{
int shmid;
int key;
struct mybuf *p;
int pid;
key=ftok("./a.c",'a');
if(key < 0)
{
printf("creat key failure\n");
return -1;
}
printf("creat key sucess\n");
shmid=shmget(key,128,IPC_CREAT | 0777);
if(shmid <0)
{
printf("creat share memory failure\n");
return -1;
}
printf("creat share memory sucess shmid=%d\n",shmid);
signal(SIGUSR2,myfun);
p=(struct mybuf *)shmat(shmid,NULL,0);
if(p == NULL)
{
printf("server process:shmat function failure\n");
return -3;
}
//get client pid
p->pid=getpid();//write server pid to share memory
pause();//wait client read server pid;
pid=p->pid;
//write
while(1)
{
//write share memory
printf("parent process start write share memory:\n");
fgets(p->buf,128,stdin);
kill(pid,SIGUSR1);// client process read data
pause();// wait client process read
}
shmdt(p);
shmctl(shmid,IPC_RMID,NULL);
system("ipcs -m ");
return 0;
}
运行结果
creat key sucess
creat share memory sucess shmid=2392070
parent process start write share memory:
hello
client
#include "sys/types.h"
#include "sys/shm.h"
#include "signal.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
struct mybuf
{
int pid;
char buf[124];
};
void myfun(int signum)
{
return ;
}
int main()
{
int shmid;
int key;
struct mybuf *p;
int pid;
key=ftok("./a.c",'a');
if(key < 0)
{
printf("creat key failure\n");
return -1;
}
printf("creat key sucess\n");
shmid=shmget(key,128,IPC_CREAT | 0777);
if(shmid <0)
{
printf("creat share memory failure\n");
return -1;
}
printf("creat share memory sucess shmid=%d\n",shmid);
signal(SIGUSR1,myfun);
p=(struct mybuf *)shmat(shmid,NULL,0);
if(p == NULL)
{
printf("client process:shmat function failure\n");
return -3;
}
//get server pid
//read share memory
pid=p->pid;
//write client pid to share memory
p->pid=getpid();
//kill signal
kill(pid,SIGUSR2);
//client start read data from share memory
while(1)
{
pause();//wait server write data to share memory;
printf("client process receve data from share memory:%s",p->buf);//read data
kill(pid,SIGUSR2);//server may write share memory
}
shmdt(p);
shmctl(shmid,IPC_RMID,NULL);
system("ipcs -m ");
return 0;
}
运行结果
creat key sucess
creat share memory sucess shmid=2392070
client process receve data from share memory:hello