1. Linux共享内存的概念
Linux共享内存是一种用于进程间通信(IPC)的机制,允许多个进程共享同一块内存区域。这种方式比起其他IPC方式(如管道、消息队列等)更为高效,适用于需要频繁访问共享数据的场景。在Linux系统中,共享内存使用key来标识不同的内存区域。
2. 创建共享内存
2.1 获取共享内存标识符
在创建共享内存之前,首先需要通过调用shmget
函数获取共享内存标识符。该函数的原型如下:
int shmget(key_t key, size_t size, int shmflg);
其中,key
是标识共享内存的键值,size
是要创建的共享内存的大小(单位为字节),shmflg
是一组标志位。
例如,要创建一块大小为1MB的共享内存:
key_t key = ftok("/tmp/memfile", 'R');
size_t size = 1024 * 1024; // 1MB
int shmflg = IPC_CREAT | 0666;
int shmid = shmget(key, size, shmflg);
if (shmid == -1) {
perror("shmget");
exit(1);
}
在上述示例中,我们调用了ftok
函数来生成键值,该函数会根据指定的文件路径和一个字符来生成一个唯一的键值。然后,我们将指定的标志位设置为IPC_CREAT | 0666
,表示创建共享内存并给予读写权限。
2.2 将共享内存映射到进程地址空间
得到共享内存标识符之后,下一步是将该内存映射到进程的地址空间中。这可以通过调用shmat
函数完成:
void *shmat(int shmid, const void *shmaddr, int shmflg);
其中,shmid
是共享内存标识符,shmaddr
是指定映射的地址(通常传入NULL
),shmflg
是一组标志位。
成功调用shmat
函数后,返回的是一个指向共享内存段的指针,可以用于访问共享内存中的内容。
void *shmaddr = shmat(shmid, NULL, 0);
if (shmaddr == (void *) -1) {
perror("shmat");
exit(1);
}
在上述示例中,我们将共享内存映射到进程的地址空间,并将返回的指针赋给shmaddr
变量。
3. 使用共享内存
3.1 写入共享内存
要向共享内存中写入数据,可以直接通过指针对共享内存区域进行写操作。
strcpy((char *)shmaddr, "Hello, shared memory!");
在上述示例中,我们使用strcpy
函数将字符串"Hello, shared memory!"写入到共享内存中。
3.2 读取共享内存
要从共享内存中读取数据,同样可以通过指针直接读取共享内存区域的内容。
char buffer[1024];
strcpy(buffer, (char *)shmaddr);
在上述示例中,我们将共享内存中的内容复制到buffer
中。
4. 删除共享内存
4.1 解除共享内存的映射
在使用完共享内存后,需要调用shmdt
函数来解除共享内存的映射关系:
int shmdt(const void *shmaddr);
其中,shmaddr
是共享内存的指针。
4.2 删除共享内存
要删除共享内存,需要调用shmctl
函数:
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
其中,shmid
是共享内存标识符,cmd
是指定要执行的操作,buf
是一个指向shmid_ds
结构体的指针。
要删除共享内存,可以将cmd
设置为IPC_RMID
:
struct shmid_ds shmid_ds;
int res = shmctl(shmid, IPC_RMID, &shmid_ds);
if (res == -1) {
perror("shmctl");
exit(1);
}
5. 总结
共享内存是一种高效的进程间通信机制,适用于需要共享数据的场景。在Linux系统中,通过shmget
函数创建共享内存,通过shmat
函数将共享内存映射到进程的地址空间中。使用过程中,需要注意调用shmdt
函数解除共享内存的映射关系,以及调用shmctl
函数删除共享内存。在写入和读取共享内存时,可以直接通过指针对共享内存区域进行读写操作。