目录
-
共享内存
共享内存,顾名思义,就是两个或多个进程都可以访问的同一块内存空间,一个进程对这块空间内容的修改可为其他参与通信 的进程所看到的。显然,为了达到这个目的就需要做两件事:一件是在内存划出一块区域来作为共享区;另一件是把这个区域映 射到参与通信的各个进程空间。共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数 据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。
内存共享示意图:
-
内存共享涉及到的函数
- ftok()
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
该函数根据pathname指定的文件或目录的索引节点号和proj_id计算并返回一个key_t类型的ID值,如果失败则返回-1;
第一个参数pathname是一个系统中必须存在的文件或文件夹的路径,会使用该文件的索引节点;
第二个参数proj_id是用户指定的一个子序号,这个数字有的称之为project ID。它是一个8bit的整数,取值范围是1~255。
注意:如果要确保key值不变,要么确保ftok()的文件不被删除,要么不用ftok()指定一个固定的key值。
-
shmget()
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
说明:该函数用来创建共享内存,成功返回一个非负整数,即该共享内存段的标识码;失败返回-1。 第一个参数key是ftok()返回的key_t类型键值; 第二个参数size以字节为单位指定需要共享的内存容量。; 第三个参数shmflg是权限标志,它的作用与open函数的mode参数一样,如果要想在key标识的共享内存不存在就创建它的话,可以与 IPC_CREAT做或操作。共享内存的权限标志与文件的读写权限一样,举例来说,0644,它表示允许一个进程创建的共享内存被内存创建 者所拥有的进程向共享内存读取和写入数据,同时其他用户创建的进程只能读取共享内存。
-
shmat()
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
说明:第一次创建完共享内存时,它还不能被任何进程访问,shmat函数的作用就是用来启动对该共享内存的访问,并把共享内存连 接到当前进程的地址空间。调用成功时返回一个指向共享内存第一个字节的指针,如果调用失败返回-1.
第一个参数shmid是由shmget函数返回的共享内存标识;
第二个参数shmaddr指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。
第三个参数shmflg是一组标志位,通常为0。
-
shmdt()
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
说明:该函数用于将共享内存从当前进程中分离。注意,将共享内存分离并不是删除它,只是使该共享内存对当前进程不再可用。
参数shmaddr是shmat函数返回的地址指针,调用成功时返回0,失败时返回-1。
-
shmctl()
说明:该函数用于控制共享内存
第一个参数shmid是shmget函数返回的共享内存标识符;
第二个参数cmd是要采取的操作,它可以取下面的三个值:
IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值;
IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值;
IPC_RMID:删除共享内存段
第三个参数buf: 是一个结构指针,它指向共享内存模式和访问权限的结构。其结构体类型定义如下:
struct shmid_ds {
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
}
-
编程示例:
说明:下面两个两个进程(不同程序)使用共享内存方式共享一个结构体变量的示例,其中sharedmem_write程序用来创建一个 person结构体共享内存并改更新里面的成员内容,而sharedmem_read 则在另外一个毫无关系的进程中同步访问该结构体里 的内容。
-
sharedmem_write代码
#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/null" #define FTOK_PROJID 0x28 typedef struct st_person { char name[64]; int age; } t_person; int main(int argc, char **argv) { key_t key; int shmid; int i; t_person *person; 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_person), IPC_CREAT|0666); if( shmid < 0) { printf("shmget() create shared memroy failure: %s\n", strerror(errno)); return -2; } person = shmat(shmid, NULL, 0); if( (void *)-1 == person ) { printf("shmat() alloc shared memroy failure: %s\n", strerror(errno)); return -2; } strncpy(person->name, "xxx", sizeof(person->name)); person->age = 28; sleep(1); for(i=0; i<4; i++) { person->age ++; printf("Person '%s' age [%d]\n", person->name, person->age); sleep(1); } shmdt(person); shmctl(shmid, IPC_RMID, NULL); return 0; }
2.sharedmem_read代码
#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/null"
#define FTOK_PROJID 0x28
typedef struct st_person
{
char name[64];
int age;
} t_person;
int main(int argc, char **argv)
{
key_t key;
int shmid;
int i;
t_person *person;
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_person), IPC_CREAT|0666);
if( shmid < 0)
{
printf("shmget() create shared memroy failure: %s\n", strerror(errno));
return -2;
}
person = shmat(shmid, NULL, 0);
if( (void *)-1 == person )
{
printf("shmat() alloc shared memroy failure: %s\n", strerror(errno));
return -2;
}
for(i=0; i<4; i++)
{
printf("Person '%s' age [%d]\n", person->name, person->age);
sleep(1);
}
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
-
运行结果
- sharedmem_write
2.sharedmem_read
说明:sharedmem_write 程序创建一个person之后并将他的基本数据进行初始化;而sharedmem_read里面什么都不干,就只获取sharedmem_write的person的相关信息打印输出。