(一)发行版:Ubuntu16.04.7
(二)记录:
(1)什么是共享内存
共享内存是System V版本的最后一个进程间通信方式。共享内存,顾名思义就是允许两个不相关的进程访问同一个逻辑内存,共享内存是两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常为同一段物理内存。进程可以将同一段物理内存连接到他们自己的地址空间中,所有的进程都可以访问共享内存中的地址。如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。
(2)shmget函数
头文件:<sys/ipc.h>、<sys/shm.h>
函数原型: int shmget(key_t key,size_t size,int shmflg);
参数:key_t key:IPC_PRIVATE或者是ftok函数的返回值
size_t size: 共享内存的大小
int shmflg: 权限
返回值:成功返回共享内存的标识符,失败返回-1。
(3)shmget函数编译运行
a.使用IPC_PRIVATE
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main(void)
{
int shmid;
shmid=shmget(IPC_PRIVATE,1024,0777);
if(shmid==-1)
{
printf("shmget error.\n");
return -1;
}
printf("shmget is ok and shmid is %d\n",shmid);
return 0;
}
删除共享内存:
(4)ftok函数
头文件:<sys/types.h>、<sys/ipc.h>
函数原型:key_t ftok(const char *pathname,int proj_id);
参数:const char *pathname文件路径以及文件名
int proj_id:字符
返回值:成功返回key值,失败返回-1
(5)ftok函数编译运行(需要先创建m.c)
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main(void)
{
int shmid;
key_t key;
key=ftok("./m.c",'m');
shmid=shmget(key,1024,0777|IPC_CREAT);
if(shmid==-1)
{
printf("shmget error.\n");
return -1;
}
printf("shmget is ok and shmid is %d\n",shmid);
return 0;
}
可以发现用ftok创建的共享内存的key值不为0 。
(6)shmat函数
头文件:<sys/types.h>、<sys/shm.h>
函数原型:void *shmat(int shmid,const void *shmaddr,int shmflg);
参数:int shmid:共享内存的标识符,就是shmget函数的返回值
const void *shmaddr:映射到的地址,一般写NULL,NULL为系统自动完成的映射
int shmflg:通常为0,表示共享内存可读可写,或者SHM_RDONLY,表示共享内存只读
返回值:成功返回共享内存映射到进程中的地址,失败返回-1
(7)shmdt函数
头文件:<sys/types.h>、<sys/shm.h>
函数原型:int shmdt(const void *shmaddr);
参数:const void *shmaddr:共享内存映射后的地址
返回值:成功返回0,失败返回-1
注意:shmdt函数是将进程中的地址映射删除,也就是说当一个进程不需要共享内存的时候,就可以使用这个函数将他从进程地址空间中脱离,并不会删除内核里面的共享内存对象。
(8)父进程与子进程进行通信
//父进程与子进程通过共享内存通信
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
int shmid;
key_t key;
pid_t pid;
//映射地址
char *s_addr,*p_addr;
//创建共享内存
key=ftok("./m.c",'m');
shmid=shmget(key,1024,0777|IPC_CREAT);
if(shmid==-1)
{
printf("shmget error.\n");
return -1;
}
printf("shmget is ok and shmid is %d\n",shmid);
//创建进程
pid=fork();
//父进程
if(pid > 0)
{
//映射地址
p_addr=shmat(shmid,NULL,0);
strncpy(p_addr,"hello",5);
wait(NULL);
exit(0);
}
//子进程
if(pid == 0)
{
sleep(2);
s_addr = shmat(shmid,NULL,0);
printf("s_addr is %s\n",s_addr);
exit(0);
}
return 0;
}
(三)命令: