共享内存的概念
共享内存:两个或多个进程都可以访问的同一块内存空间,一个进程对这块空间内容的修改可为其他参与通信的进程所看到的。因为数据不需要再客户进程和服务器进程之间复制,所以共享内存是最快的一种进程通信。可以看一下共享内存的示意图
共享内存的函数
1、shmget
函数原型:
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
函数说明:shmget函数创建一个新的共享内存区,或者访问一个已存在的共享内存区。
返回值:成功返回一个非负整数,即该共享内存区标识符,其他三个shmxxx函数就用来指代这个内存区,失败返回-1。
参数说明:第一个参数key是ftok()返回的key_t类型键值;
第二个参数size以字节为单位指定需要共享的内存容量;
第三个参数shmflg是权限标志,它的作用与open函数的mode参数一样,如果要想在key标识的共享内存不存在就创建它的话,可以与IPC_CREAT做或操作。共享内存的权限标志,与文件的读写权限一样,举例来说,0644,它表示允许一个进程创建的共享内存被内存创建者所拥有的进程向共享内存读取和写入数据,同时其他用户创建的进程只能读取共享内存;
2、shmat
函数原型
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
函数说明:第一次创建完共享内存时,它还不能被任何进程访问,shmat函数的作用就是用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间。
返回值:调用成功返回一个指向共享内存第一个字节的指针,如果调用失败返回-1.
参数说明:第一个参数shmid是由shmget函数返回的共享内存标识;
第二个参数shmaddr指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址;
第三个参数shmflg是一组标志位,通常为0.
3、shmdt
函数原型
#include <sys/shm.h>
int shmdt(const void *shmaddr);
函数说明:该函数用于将共享内存从当前进程中分离。注意,将共享内存分离并不是删除它,只是使该共享内存对当前进程不再可用。
参数说明:参数shmaddr是shmat函数返回的地址指针,调用成功时返回0,失败时返回-1。
4、shmctl
函数原型
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
函数说明:该函数用于控制共享内存
参数说明:第一个参数shmid是shmget函数返回的共享内存标识符;
第二个参数cmd是要采取的操作,它可以取下面的三个值:
①IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值;
②IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值;
③IPC_RMID:删除共享内存段
第三个参数,buf是一个结构指针,它指向共享内存模式和访问权限的结构。其结构体类型定义如下:
struct shmmid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
}
共享内存的代码示例
创建连个进程(不同程序)使用共享内存方式共享一个结构体变量的示例,其中shared_mem_write程序用来创建一个student结构体共享内存并修改更新里面的成员内容,而shared_mem_read则在另外一个毫无关系的进程中同步访问该结构体里的内容。
第一个进程shared_mem_write
/*********************************************************************************
* Copyright: (C) 2020 makun<[email protected]>
* All rights reserved.
*
* Filename: shared_mem_write.c
* Description: This file
*
* Version: 1.0.0(2020年03月21日)
* Author: makun <[email protected]>
* ChangeLog: 1, Release initial version on "2020年03月21日 02时56分59秒"
*
********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define FTOK_PATH "/dev/zero"
#define FTOK_PROJID 0x22
typedef struct st_student
{
char name[64];
int age;
}t_student;
int main (int argc, char **argv)
{
key_t key;
int shmid;
int i;
t_student *student;
if( (key =ftok(FTOK_PATH, FTOK_PROJID)) <0)
{
printf("ftok get IPC token failure:%s\n",strerror(errno));
return -1;
}
shmid =shmget(key, sizeof(t_student),IPC_CREAT |0666);
if( shmid < 0)
{
printf("shmget create shared memroy failure:%s\n",strerror(errno));
return -2;
}
student = shmat(shmid,NULL,0);
if( (void *)-1 == student)
{
printf("shmat alloc shared memory failure:%s\n",strerror(errno));
return -2;
}
strncpy(student->name, "zhangsan",sizeof(student->name));
student->age=18;
for(i=0; i<4; i++)
{
student->age ++;
printf("student %s age %d\n",student->name,student->age);
sleep(1);
}
shmdt(student);
shmctl(shmid, IPC_RMID,NULL);
return 0;
}
第二个进程shared_mem_read
/*********************************************************************************
* Copyright: (C) 2020 makun<[email protected]>
* All rights reserved.
*
* Filename: shared_mem_read.c
* Description: This file
*
* Version: 1.0.0(2020年03月21日)
* Author: makun <[email protected]>
* ChangeLog: 1, Release initial version on "2020年03月21日 02时56分59秒"
*
********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define FTOK_PATH "/dev/zero"
#define FTOK_PROJID 0x22
typedef struct st_student
{
char name[64];
int age;
}t_student;
int main (int argc, char **argv)
{
key_t key;
int shmid;
int i;
t_student *student;
if( (key =ftok(FTOK_PATH, FTOK_PROJID)) <0)
{
printf("ftok get IPC token failure:%s\n",strerror(errno));
return -1;
}
shmid =shmget(key, sizeof(t_student),IPC_CREAT |0666);
if( shmid < 0)
{
printf("shmget create shared memroy failure:%s\n",strerror(errno));
return -2;
}
student = shmat(shmid,NULL,0);
if( (void *)-1 == student)
{
printf("shmat alloc shared memory failure:%s\n",strerror(errno));
return -2;
}
for(i=0; i<4; i++)
{
printf("student %s age %d\n",student->name,student->age);
sleep(1);
}
shmctl(shmid, IPC_RMID,NULL);
return 0;
}
运行结果: