进程间通讯-信号量

介绍

信号量是进程间通信的一种同步机制,用于管理多个进程对共享资源的访问。以下是一些关于信号量的关键要点:

  1. 信号量概念

    • 信号量是一个特殊的变量或计数器,其值表示可供并发进程使用的资源数量。
    • 信号量可以用来控制对临界区(critical section)的访问,确保在任何给定时刻只有一个进程在使用该资源。
  2. P/V操作

    • 信号量主要进行两种操作:等待§和发送(V)。
    • P操作会检查信号量的值:
      • 如果信号量的值大于0,将其减1,进程可以继续执行。
      • 如果信号量的值为0,进程会被阻塞(挂起),并放入一个等待队列中,直到其他进程执行V操作释放信号量。
    • V操作会将信号量的值增加1:
      • 如果信号量的值小于或等于0,唤醒等待队列中的一个进程。
      • 如果信号量的值已经大于0,只需简单地增加其值。
  3. 类型

    • 二进制信号量:只能取0或1的信号量,常用于实现互斥锁(mutex)。
    • 计数信号量:可以取大于1的值,用于控制可重入资源的数量。
  4. 系统调用

    • 在Unix/Linux系统中,常用的信号量系统调用包括:
      • semget():创建或获取一个信号量集。
      • semop():执行P/V操作。
      • semctl():控制信号量的各种属性。
  5. 参数

    • semget()函数的参数包括:
      • key:一个键值,用于标识全局唯一的信号量集。
      • nsems:要创建或获取的信号量数量。
      • flags:标志位,可以指定权限和其他选项。
  6. 工作原理

    • 当一个进程需要访问共享资源时,它首先执行P操作,减少信号量的值。
    • 如果信号量的值变为非正数,该进程被阻塞,直到其他进程执行V操作增加信号量的值并唤醒它。
    • 当进程完成对资源的访问后,它执行V操作,释放信号量,允许其他等待的进程继续执行。

实现举例

使用POSIX semaphore API实现两个进程之间的同步。创建一个信号量,并让两个进程交替打印数字。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

#define SEM_KEY 1234

int main() {
    int semid;
    struct sembuf P = {0, -1, SEM_UNDO}, V = {0, 1, SEM_UNDO};

    // 创建信号量
    if ((semid = semget(SEM_KEY, 1, IPC_CREAT | 0600)) == -1) {
        perror("semget");
        exit(EXIT_FAILURE);
    }

    pid_t pid;
    if ((pid = fork()) == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    } else if (pid == 0) { // 子进程
        for (int i = 1; i <= 5; ++i) {
            // 执行P操作,获取信号量
            if (semop(semid, &P, 1) == -1) {
                perror("semop (P)");
                exit(EXIT_FAILURE);
            }

            printf("Child: %d\n", i);

            // 执行V操作,释放信号量
            if (semop(semid, &V, 1) == -1) {
                perror("semop (V)");
                exit(EXIT_FAILURE);
            }
        }
        exit(EXIT_SUCCESS);
    } else { // 父进程
        for (int i = 6; i <= 10; ++i) {
            // 执行P操作,获取信号量
            if (semop(semid, &P, 1) == -1) {
                perror("semop (P)");
                exit(EXIT_FAILURE);
            }

            printf("Parent: %d\n", i);

            // 执行V操作,释放信号量
            if (semop(semid, &V, 1) == -1) {
                perror("semop (V)");
                exit(EXIT_FAILURE);
            }
        }
        wait(NULL);
        exit(EXIT_SUCCESS);
    }
}
实例说明

在这个例子中,首先创建一个信号量集,然后通过fork()函数创建一个子进程。父进程和子进程都执行类似的循环,但在循环内部,它们首先执行P操作来获取信号量,然后打印数字,最后执行V操作来释放信号量。由于信号量的值初始为1,因此每次只有一个进程能够获取到信号量并打印数字。当一个进程完成打印后,它会释放信号量,允许另一个进程继续执行。这样,两个进程就能交替打印数字了。

总结

进程间通讯的信号量是一种有效的机制,用于协调多个进程对共享资源的访问,确保系统的正确性和稳定性,防止竞态条件和死锁等问题的发生。

  • 25
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

匠心码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值