linux 共享内存 进程间同步 例子
时间: 2023-10-14 15:07:21 浏览: 41
下面是一个基于 Linux 共享内存机制的进程间同步的例子:
首先,我们需要创建一个共享内存区域,可以使用 `shmget()` 函数来创建:
```c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHM_SIZE 1024
int shmid;
char *shmaddr;
/* 创建共享内存 */
shmid = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0666);
if (shmid == -1) {
perror("shmget");
exit(1);
}
```
接下来,我们需要将共享内存区域映射到进程的地址空间中,可以使用 `shmat()` 函数来实现:
```c
/* 映射共享内存 */
shmaddr = (char *)shmat(shmid, NULL, 0);
if (shmaddr == (char *) -1) {
perror("shmat");
exit(1);
}
```
现在,我们就可以在进程间共享数据了,例如:
```c
/* 写入数据 */
strcpy(shmaddr, "Hello, world!");
/* 读取数据 */
printf("%s\n", shmaddr);
```
接下来,我们需要在多个进程间同步对共享内存的访问,这可以通过信号量机制来实现。我们可以使用 `semget()` 函数来创建一个信号量集合:
```c
#include <sys/sem.h>
int semid;
/* 创建信号量集合 */
semid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666);
if (semid == -1) {
perror("semget");
exit(1);
}
```
然后,我们可以使用 `semctl()` 函数来初始化信号量的值:
```c
#include <sys/sem.h>
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
};
union semun semarg;
/* 初始化信号量值为 1 */
semarg.val = 1;
if (semctl(semid, 0, SETVAL, semarg) == -1) {
perror("semctl");
exit(1);
}
```
现在,我们就可以在进程访问共享内存之前,先通过 `semop()` 函数来获取信号量:
```c
#include <sys/sem.h>
struct sembuf sembuf;
/* 获取信号量 */
sembuf.sem_num = 0;
sembuf.sem_op = -1;
sembuf.sem_flg = SEM_UNDO;
if (semop(semid, &sembuf, 1) == -1) {
perror("semop");
exit(1);
}
```
然后,对共享内存进行读写操作。
最后,访问完共享内存后,我们需要释放信号量:
```c
#include <sys/sem.h>
/* 释放信号量 */
sembuf.sem_num = 0;
sembuf.sem_op = 1;
sembuf.sem_flg = SEM_UNDO;
if (semop(semid, &sembuf, 1) == -1) {
perror("semop");
exit(1);
}
```
完整的代码可以参考下面的例子:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#define SHM_SIZE 1024
int main()
{
int shmid, semid;
char *shmaddr;
union semun semarg;
struct sembuf sembuf;
/* 创建共享内存 */
shmid = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0666);
if (shmid == -1) {
perror("shmget");
exit(1);
}
/* 映射共享内存 */
shmaddr = (char *)shmat(shmid, NULL, 0);
if (shmaddr == (char *) -1) {
perror("shmat");
exit(1);
}
/* 创建信号量集合 */
semid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666);
if (semid == -1) {
perror("semget");
exit(1);
}
/* 初始化信号量值为 1 */
semarg.val = 1;
if (semctl(semid, 0, SETVAL, semarg) == -1) {
perror("semctl");
exit(1);
}
/* 获取信号量 */
sembuf.sem_num = 0;
sembuf.sem_op = -1;
sembuf.sem_flg = SEM_UNDO;
if (semop(semid, &sembuf, 1) == -1) {
perror("semop");
exit(1);
}
/* 写入数据 */
strcpy(shmaddr, "Hello, world!");
/* 读取数据 */
printf("%s\n", shmaddr);
/* 释放信号量 */
sembuf.sem_num = 0;
sembuf.sem_op = 1;
sembuf.sem_flg = SEM_UNDO;
if (semop(semid, &sembuf, 1) == -1) {
perror("semop");
exit(1);
}
/* 解除共享内存映射 */
if (shmdt(shmaddr) == -1) {
perror("shmdt");
exit(1);
}
/* 删除共享内存 */
if (shmctl(shmid, IPC_RMID, NULL) == -1) {
perror("shmctl");
exit(1);
}
/* 删除信号量集合 */
if (semctl(semid, 0, IPC_RMID, semarg) == -1) {
perror("semctl");
exit(1);
}
return 0;
}
```