Linux进程间通信——使用共享内存
原创Linux进程间通信——使用共享内存
在多进程或多线程的应用程序中,进程间通信(Inter-Process Communication,IPC)是确保不同进程能够二者之间交换信息的重要机制。共享内存是IPC的一种常用方法,它允许多个进程共享同一块内存空间,从而实现高效的通信。本文将详细介绍Linux下使用共享内存进行进程间通信的方法。
1. 共享内存的概念
共享内存是一种特殊的内存区域,它允许不同的进程访问同一块内存。在Linux系统中,共享内存通常是通过System V IPC(Inter-Process Communication)或POSIX IPC(POSIX Inter-Process Communication)实现的。System V IPC提供了更为充裕的IPC机制,而POSIX IPC则提供了更为统一的接口。
2. 共享内存的创建
在Linux下,可以使用System V IPC或POSIX IPC来创建共享内存。以下分别介绍两种方法的创建过程。
2.1 使用System V IPC创建共享内存
使用System V IPC创建共享内存需要以下步骤:
- 使用
shmget
系统调用创建共享内存段。 - 使用
shmat
系统调用将共享内存段映射到当前进程的地址空间。
#include <sys/ipc.h>
#include <sys/shm.h>
int main() {
key_t key = ftok("shmfile", 65); // 生成共享内存的键值
int shmid = shmget(key, 1024, 0644 | IPC_CREAT); // 创建共享内存
if (shmid == -1) {
perror("shmget");
return 1;
}
char *data = (char *)shmat(shmid, (void *)0, 0); // 将共享内存映射到地址空间
if (data == (char *)(-1)) {
perror("shmat");
return 1;
}
// 在这里,data指向共享内存的地址,可以进行读写操作
// 使用完毕后,释放共享内存
if (shmdt(data) == -1) {
perror("shmdt");
return 1;
}
return 0;
}
2.2 使用POSIX IPC创建共享内存
使用POSIX IPC创建共享内存需要以下步骤:
- 使用
shm_open
系统调用打开共享内存对象。 - 使用
ftruncate
系统调用设置共享内存的大小。 - 使用
mmap
系统调用将共享内存映射到当前进程的地址空间。
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
int main() {
const char *name = "/my_shared_memory";
int shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
if (shm_fd == -1) {
perror("shm_open");
return 1;
}
ftruncate(shm_fd, 1024); // 设置共享内存的大小
char *data = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (data == MAP_FAILED) {
perror("mmap");
return 1;
}
// 在这里,data指向共享内存的地址,可以进行读写操作
// 使用完毕后,关闭共享内存对象
if (close(shm_fd) == -1) {
perror("close");
return 1;
}
return 0;
}
3. 共享内存的同步
由于多个进程可以同时访问共享内存,故而需要同步机制来避免竞态条件。在Linux下,可以使用互斥锁(mutex)或读写锁(rwlock)来实现同步。
3.1 使用互斥锁
可以使用POSIX线程库(pthread)提供的互斥锁来同步对共享内存的访问。
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *process_function(void *arg) {
pthread_mutex_lock(&mutex); // 加锁
// 对共享内存进行操作
pthread_mutex_unlock(&mutex); // 解锁
return NULL;
}
int main() {
pthread_t thread_id;
pthread_create(&thread