C++中fork()进程间共享列表与互斥锁的声明方法
实现进程间共享列表与互斥锁的两种方式
一、原生POSIX API实现
fork()创建的子进程会复制父进程的地址空间,但普通内存区域是各自独立的,因此必须通过共享内存存放需要共享的列表和互斥锁,同时互斥锁需配置为进程间可见的属性。
1. 核心要点
- 共享内存区域:通过
shm_open创建共享内存对象,再用mmap映射到进程地址空间,让父子进程访问同一块物理内存。 - 进程间互斥锁:初始化
pthread_mutex_t时,设置PTHREAD_PROCESS_SHARED属性,确保锁能跨进程生效。 - 注意:标准STL容器(如
std::list)默认使用堆内存分配,无法直接放入共享内存。如果要用STL容器,需要自定义分配器将内存分配到共享内存区域;或者改用C风格链表(节点全部放在共享内存中)。
2. 代码示例
#include <iostream> #include <unistd.h> #include <pthread.h> #include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> #include <cstring> #include <sys/wait.h> // 定义共享内存中的结构体:包含互斥锁和固定大小的列表(模拟) #define MAX_LIST_ITEMS 100 struct SharedData { pthread_mutex_t mutex; int list[MAX_LIST_ITEMS]; int count; // 记录列表中元素的数量 }; int main() { // 创建共享内存对象 int shm_fd = shm_open("/my_shared_memory", O_CREAT | O_RDWR, 0666); if (shm_fd == -1) { perror("shm_open failed"); return 1; } // 设置共享内存大小 ftruncate(shm_fd, sizeof(SharedData)); // 映射共享内存到进程地址空间 SharedData* shared_data = static_cast<SharedData*>(mmap(nullptr, sizeof(SharedData), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0)); if (shared_data == MAP_FAILED) { perror("mmap failed"); return 1; } // 初始化互斥锁的进程间共享属性 pthread_mutexattr_t mutex_attr; pthread_mutexattr_init(&mutex_attr); pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED); pthread_mutex_init(&shared_data->mutex, &mutex_attr); pthread_mutexattr_destroy(&mutex_attr); // 初始化列表计数 shared_data->count = 0; pid_t pid = fork(); if (pid == -1) { perror("fork failed"); return 1; } else if (pid == 0) { // 子进程:向列表添加元素 for (int i = 0; i < 10; ++i) { pthread_mutex_lock(&shared_data->mutex); if (shared_data->count < MAX_LIST_ITEMS) { shared_data->list[shared_data->count++] = i + 100; std::cout << "Child added: " << i + 100 << std::endl; } pthread_mutex_unlock(&shared_data->mutex); sleep(1); } } else { // 父进程:向列表添加元素 for (int i = 0; i < 10; ++i) { pthread_mutex_lock(&shared_data->mutex); if (shared_data->count < MAX_LIST_ITEMS) { shared_data->list[shared_data->count++] = i; std::cout << "Parent added: " << i << std::endl; } pthread_mutex_unlock(&shared_data->mutex); sleep(1); } // 等待子进程结束 wait(nullptr); // 打印最终列表 pthread_mutex_lock(&shared_data->mutex); std::cout << "\nFinal list: "; for (int i = 0; i < shared_data->count; ++i) { std::cout << shared_data->list[i] << " "; } std::cout << std::endl; pthread_mutex_unlock(&shared_data->mutex); // 清理资源 pthread_mutex_destroy(&shared_data->mutex); munmap(shared_data, sizeof(SharedData)); shm_unlink("/my_shared_memory"); } return 0; }
编译时需链接pthread库:g++ -o shared_list shared_list.cpp -lpthread
二、Boost.Interprocess库实现
Boost.Interprocess专门为进程间通信设计,提供了开箱即用的共享内存容器和进程间同步原语,大幅简化代码,无需手动管理共享内存映射和锁属性。
1. 核心要点
- 使用
managed_shared_memory创建/打开共享内存区域。 - 使用
interprocess::list(带共享内存分配器)作为共享列表。 - 使用
interprocess::mutex作为进程间互斥锁,无需额外配置属性。
2. 代码示例
#include <iostream> #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/containers/list.hpp> #include <boost/interprocess/sync/interprocess_mutex.hpp> #include <boost/interprocess/sync/scoped_lock.hpp> #include <unistd.h> #include <sys/wait.h> namespace bip = boost::interprocess; // 定义共享内存中的数据结构 struct SharedData { bip::interprocess_mutex mutex; bip::list<int, bip::allocator<int, bip::managed_shared_memory::segment_manager>> list; // 构造函数:初始化列表(使用共享内存分配器) SharedData(bip::managed_shared_memory::segment_manager* sm) : list(sm) {} }; int main() { // 先删除旧的共享内存(避免残留) bip::shared_memory_object::remove("/boost_shared_memory"); // 创建共享内存区域 bip::managed_shared_memory segment(bip::create_only, "/boost_shared_memory", 65536); // 在共享内存中构造SharedData对象 SharedData* shared_data = segment.construct<SharedData>("SharedData")(segment.get_segment_manager()); pid_t pid = fork(); if (pid == -1) { perror("fork failed"); return 1; } else if (pid == 0) { // 子进程:添加元素 for (int i = 0; i < 10; ++i) { bip::scoped_lock<bip::interprocess_mutex> lock(shared_data->mutex); shared_data->list.push_back(i + 100); std::cout << "Child added: " << i + 100 << std::endl; sleep(1); } } else { // 父进程:添加元素 for (int i = 0; i < 10; ++i) { bip::scoped_lock<bip::interprocess_mutex> lock(shared_data->mutex); shared_data->list.push_back(i); std::cout << "Parent added: " << i << std::endl; sleep(1); } // 等待子进程结束 wait(nullptr); // 打印最终列表 bip::scoped_lock<bip::interprocess_mutex> lock(shared_data->mutex); std::cout << "\nFinal list: "; for (int num : shared_data->list) { std::cout << num << " "; } std::cout << std::endl; // 清理资源 segment.destroy<SharedData>("SharedData"); bip::shared_memory_object::remove("/boost_shared_memory"); } return 0; }
编译时需链接Boost库:g++ -o boost_shared_list boost_shared_list.cpp -lboost_system -lboost_interprocess
说明
- Boost.Interprocess的容器自动使用共享内存分配器,无需担心内存分配位置问题。
scoped_lock是RAII风格的锁,能自动管理锁的释放,避免死锁风险。
内容的提问来源于stack exchange,提问作者ALEXIS LAZANAS
相关产品推荐
相关产品推荐

