POSIX共享内存是一种在UNIX和类UNIX系统上可用的进程间通信机制。它允许多个进程共享同一块内存区域,从而可以在这块共享内存上进行读写操作。
POSIX共享内存适用于需要高效地进行大量数据交换的场景,比如多个进程需要共享大型数据集合或缓存。它可以提供比其他进程间通信方式更快的数据传输速度
创建或打开一个POSIX共享内存对象。
int shm_open(const char *name, int oflag, mode_t mode);
参数
返回值
设置共享内存对象的大小。
int ftruncate(int fd, off_t length);
参数
返回值
将共享内存对象映射到进程的地址空间。
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
参数
返回值
解除共享内存的映射。
int munmap(void *addr, size_t length);
参数
返回值
删除共享内存对象。
int shm_unlink(const char *name);
参数
返回值
测试代码如下,代码编译需要加-lrt -pthread:
#include
#include
#include
#include
#include
#include
#include
#include
// 打印时分秒的宏
#define PRINT_MIN_SEC do { \
time_t t = time(NULL); \
struct tm *tm_ptr = localtime(&t); \
printf("%02d:%02d:%02d:", tm_ptr->tm_hour, tm_ptr->tm_min, tm_ptr->tm_sec);\
} while (0);printf
#define SHM_NAME "/example_shm"
#define SHM_SIZE 1024
void parent_process();
void child_process();
int main()
{
pid_t pid = fork();
if (pid == 0)
{
child_process();
}
else if (pid > 0)
{
parent_process();
}
else
{
perror("fork failed");
exit(EXIT_FAILURE);
}
return 0;
}
void parent_process()
{
PRINT_MIN_SEC("Parent start!\n");
int shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666);
if (shm_fd == -1)
{
perror("shm_open failed");
exit(EXIT_FAILURE);
}
ftruncate(shm_fd, SHM_SIZE);
char *ptr = mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (ptr == MAP_FAILED) {
perror("mmap failed");
exit(EXIT_FAILURE);
}
bzero(ptr, SHM_SIZE);
strcpy(ptr, "Parent Write Data");
sleep(2); // 等待子进程读取共享内存中的数据
PRINT_MIN_SEC("Parent read from shared memory: %s\n", ptr);
munmap(ptr, SHM_SIZE);
close(shm_fd);
shm_unlink(SHM_NAME);
}
void child_process()
{
PRINT_MIN_SEC("Child start!\n");
sleep(1); // 等待父进程创建共享内存并写入数据到共享内存
int shm_fd = shm_open(SHM_NAME, O_RDWR, 0666);
if (shm_fd == -1)
{
perror("shm_open failed");
exit(EXIT_FAILURE);
}
char *ptr = mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (ptr == MAP_FAILED)
{
perror("mmap failed");
exit(EXIT_FAILURE);
}
PRINT_MIN_SEC("Child read from shared memory: %s\n", ptr);
bzero(ptr, SHM_SIZE);
strcpy(ptr, "Child Write Data");
munmap(ptr, SHM_SIZE);
close(shm_fd);
}
通过父子间进程读写共享内存的时间不一致来实现进程通信,测试结果如下:
测试代码如下,代码编译需要加-lrt -pthread :
#include
#include
#include
#include
#include
#include
#include
#include
#include
// 打印时分秒的宏
#define PRINT_MIN_SEC do { \
time_t t = time(NULL); \
struct tm *tm_ptr = localtime(&t); \
printf("%02d:%02d:%02d:", tm_ptr->tm_hour, tm_ptr->tm_min, tm_ptr->tm_sec);\
} while (0);printf
#define SHM_NAME "/example_shm"
#define SHM_SIZE 1024
void parent_process();
void child_process();
// 打印当前信号量的值
void printfValue(sem_t *sem)
{
// 打印当前值
int value;
sem_getvalue(sem, &value);
PRINT_MIN_SEC("Current value of semaphore: %d\n", value);
}
int main()
{
sem_t *mutex = sem_open("/mysemaphore", O_CREAT, 0644, 0);
pid_t pid = fork();
if (pid == 0)
{
child_process(mutex);
}
else if (pid > 0)
{
parent_process(mutex);
}
else
{
perror("fork failed");
exit(EXIT_FAILURE);
}
return 0;
}
void parent_process(sem_t * mutex)
{
int SendNum = 0;
char SendData[32] = {0};
PRINT_MIN_SEC("Parent start!\n");
printfValue(mutex);
int shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666);
if (shm_fd == -1)
{
perror("shm_open failed");
exit(EXIT_FAILURE);
}
ftruncate(shm_fd, SHM_SIZE);
char *ptr = mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (ptr == MAP_FAILED) {
perror("mmap failed");
exit(EXIT_FAILURE);
}
while(1)
{
sprintf(SendData, "Parent Write Data-%d\n", SendNum);
SendNum++;
strcpy(ptr, SendData);
sem_post(mutex);
sleep(2);
}
PRINT_MIN_SEC("Parent read from shared memory: %s\n", ptr);
munmap(ptr, SHM_SIZE);
close(shm_fd);
shm_unlink(SHM_NAME);
}
void child_process(sem_t * mutex)
{
PRINT_MIN_SEC("Child start!\n");
printfValue(mutex);
sleep(1); // 等待父进程创建共享内存并写入数据到共享内存
int shm_fd = shm_open(SHM_NAME, O_RDWR, 0666);
if (shm_fd == -1)
{
perror("shm_open failed");
exit(EXIT_FAILURE);
}
char *ptr = mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (ptr == MAP_FAILED)
{
perror("mmap failed");
exit(EXIT_FAILURE);
}
while(1)
{
sem_wait(mutex);
PRINT_MIN_SEC("Child read from shared memory: %s\n", ptr);
}
munmap(ptr, SHM_SIZE);
close(shm_fd);
}
父进程通过信号量,每1秒写一次数据,写入完毕后执行post,子进程一直阻塞等待,获取到信号量后从共享内存读取数据,测试结果如下:
本文阐述了进程间通信之共享内存(POSIX)的定义、应用场景、优缺点等,列举了编程中使用的接口,编写了测试用例测试相关功能。