C语言-进程间通信—共享内存的入门
前言
进程间通信(Inter-Process Communication, IPC)是操作系统中实现多进程协同工作的重要手段之一。在多种IPC方式中,共享内存因其高效、灵活的特性而受到广泛关注。本文将介绍C语言中共享内存的基本概念、使用方法和注意事项,帮助读者入门共享内存的使用。
一、共享内存的基本概念
共享内存是指两个或多个进程共享一个给定的存储区。因为进程可以直接读写内存,所以这是最快的一种IPC方式。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。
二、C语言中共享内存的使用
共享内存,顾名思义就是开辟一段内存,让多个进程能对其进行读写。我们常有几个操作:创建共享内存、连接共享内存、断开连接共享内存、删除共享内存。
1、创建共享内存
使用shmget
函数可以创建共享内存。
函数信息
我们查看man手册中,shmget函数的信息如下:
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
参数介绍
-
key
:用于唯一标识共享内存段的键值。 -
size
:共享内存的大小,以字节为单位。 -
shmflg
:权限标志位和IPC_CREAT标志的组合。
返回值
On success, a valid shared memory identifier is returned. On error, -1
is returned, and errno is set to indicate the error.
成功会返回一个共享内存的标识符,如果错误会返回-1。
2. 连接到共享内存
使用shmat
函数可以将共享内存连接到进程的地址空间。
函数信息
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
参数介绍
- shmid
:由
shmget`返回的共享内存标识符。 -
shmaddr
:指定共享内存连接到进程地址空间的起始地址,通常设置为NULL。 -
shmflg
:标志位,通常设置为0。
返回值
On success, shmat() returns the address of the attached shared memory
segment; on error, (void *) -1 is returned, and errno is set to indi‐
cate the cause of the error.
3.断开共享内存连接
使用shmdt
函数可以断开共享内存与进程的连接。
函数信息
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
参数介绍
-
shmaddr
:shmat
返回的指向共享内存的指针。
4. 删除共享内存
当不再需要共享内存时,使用shmctl
函数配合IPC_RMID命令可以删除它。
函数信息
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数介绍
-
shmid
:共享内存标识符。 -
cmd
:要执行的操作,如IPC_RMID用于删除共享内存。 -
buf
:指向shmid_ds
结构的指针,用于获取或设置共享内存的属性,我们一般不怎么关心,设置成0
三、使用案例
写信息入共享内存
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// int shmget(key_t key, size_t size, int shmflg);
int main()
{
char *memmary;
key_t key;
key = ftok(".",1);
int shmid = shmget(key,1024*4,IPC_CREAT|0666);
memmary = shmat(shmid,0,0);
strcpy(memmary,"hello word\n");
sleep(5);
shmdt(memmary);
shmctl(shmid,IPC_RMID,0);
printf("done \n");
return 0;
}
这个代码,我们先创建了一个共享内存,然后连接到这个共享内存,利用strcpy
函数将字符串写入共享内存中,然后我们挂起程序5s等待其他程序将共享内存读走。然后断开连接并删除了共享内存。
读取共享内存里的信息
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// int shmget(key_t key, size_t size, int shmflg);
int main()
{
char *memmary;
key_t key;
key = ftok(".",1);
int shmid = shmget(key,1024*4,0);
memmary = shmat(shmid,0,0);
printf("get memmary:%s",memmary);
shmdt(memmary);
return 0;
}
这段代码我们连接上了同一个共享内存,然后读取里面的值后输出。
四、Linux中操作共享内存
常用命令
1、ipcs -m
通过这个命令我们可以看到共享内存的信息:
------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节 连接数 状态
0x0103c0ec 7 hyx 666 4096 0
2、ipcrm -m [key]
通过该命令,我们可以删除指定key的共享内存
五、注意事项
- 同步问题:多个进程同时读写共享内存时,必须解决同步问题,以防止数据竞争和不一致。通常可以使用信号量(semaphores)或互斥锁(mutexes)来实现同步。
- 权限管理:创建共享内存时,需要设置适当的权限,以确保只有授权的进程能够访问。
- 错误处理:在使用共享内存相关函数时,应检查返回值以处理可能出现的错误。
- 内存管理:虽然共享内存提供了高效的进程间通信方式,但也需要谨慎管理内存,避免内存泄漏和其他内存相关的问题。
总结
共享内存是一种高效的进程间通信方式,它允许不同进程直接访问同一块内存区域。通过C语言的IPC相关函数,我们可以方便地创建、连接、断开和删除共享内存。然而,在使用共享内存时,我们需要注意同步问题、权限管理、错误处理以及内存管理等方面的问题,以确保程序的正确性和安全性。
本文介绍了共享内存的基本概念和使用方法,希望能为读者入门共享内存提供一定的帮助。在实际使用中,建议参考操作系统的相关文档和资料,以获得更详细和深入的了解。