Linux共享内存信号灯进程同步示例
时间: 2023-07-07 15:05:53 浏览: 53
下面是一个简单的 Linux 共享内存、信号灯和进程同步的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#define SHM_KEY 1234 // 共享内存关键字
#define SEM_KEY 5678 // 信号灯关键字
// 共享内存结构体
typedef struct {
int value;
} shared_memory;
int main() {
int shmid, semid;
shared_memory *shm;
struct sembuf sem_ops;
// 创建共享内存
shmid = shmget(SHM_KEY, sizeof(shared_memory), IPC_CREAT | 0666);
if (shmid == -1) {
perror("shmget");
exit(EXIT_FAILURE);
}
// 连接到共享内存
shm = shmat(shmid, NULL, 0);
if (shm == (void *)-1) {
perror("shmat");
exit(EXIT_FAILURE);
}
// 初始化共享内存值
shm->value = 0;
// 创建信号灯
semid = semget(SEM_KEY, 1, IPC_CREAT | 0666);
if (semid == -1) {
perror("semget");
exit(EXIT_FAILURE);
}
// 初始化信号灯值
semctl(semid, 0, SETVAL, 1);
// 创建子进程
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) { // 子进程
for (int i = 0; i < 10; i++) {
sem_ops.sem_num = 0;
sem_ops.sem_op = -1; // P操作
sem_ops.sem_flg = 0;
semop(semid, &sem_ops, 1);
shm->value++;
printf("子进程:共享内存值增加为 %d\n", shm->value);
sem_ops.sem_num = 0;
sem_ops.sem_op = 1; // V操作
sem_ops.sem_flg = 0;
semop(semid, &sem_ops, 1);
sleep(1);
}
} else { // 父进程
for (int i = 0; i < 10; i++) {
sem_ops.sem_num = 0;
sem_ops.sem_op = -1; // P操作
sem_ops.sem_flg = 0;
semop(semid, &sem_ops, 1);
shm->value--;
printf("父进程:共享内存值减少为 %d\n", shm->value);
sem_ops.sem_num = 0;
sem_ops.sem_op = 1; // V操作
sem_ops.sem_flg = 0;
semop(semid, &sem_ops, 1);
sleep(2);
}
}
// 删除共享内存和信号灯
shmdt(shm);
shmctl(shmid, IPC_RMID, NULL);
semctl(semid, 0, IPC_RMID);
return 0;
}
```
在这个示例中,我们创建了一个 `shared_memory` 结构体作为共享内存区域,其中只有一个整数类型的 `value` 成员。我们使用 `shmget()` 来创建共享内存,使用 `shmat()` 来连接到共享内存。然后,我们初始化了 `value` 的值为 0。
接下来,我们使用 `semget()` 创建了一个信号灯,使用 `semctl()` 初始化了信号灯的值为 1。
然后,我们使用 `fork()` 创建了一个子进程。在子进程中,我们执行了一个循环,每次将共享内存中的 `value` 值加一,并打印出来。在父进程中,我们也执行了一个循环,每次将共享内存中的 `value` 值减一,并打印出来。在每次操作共享内存之前,我们使用信号灯进行了同步,使用 P 操作获取信号灯,使用 V 操作释放信号灯。
最后,我们删除了共享内存和信号灯,使用 `shmdt()` 断开了共享内存的连接,使用 `shmctl()` 和 `semctl()` 删除了共享内存和信号灯的数据结构。