进程间通信(IPC)之————信号量

本文介绍了信号量的概念,作为进程间通信的一种方式,用于控制临界资源的互斥访问。信号量本质是数据操作锁,通过P操作(减操作)和V操作(加操作)实现资源的申请和释放。文中还详细讲解了信号量的创建、销毁、初始化以及P、V操作的实现,并通过实例展示了如何使用信号量解决进程间的同步问题,确保资源的有序访问。
摘要由CSDN通过智能技术生成

一. 信号量

    在谈论信号量之前,先要提到临界资源临界区的概念,临界资源是指多个进程访问但一个时间段内只允许一个进程独占的资源,而临界区是指多个进程访问临界资源的这一段公共的代码。

    信号量的本质是一种数据操作锁,也可以说就是一个计数器,它本身并不能提供对进程间的通信,而是通过控制某一资源来完成进程间的互斥和同步,比如当一个进程请求某一用信号量来表示的临界资源时,先要进行检查该资源的信号量,若信号量大于零,表示有资源可用,若信号量等于零,则表示有其他进程正在使用该资源,则申请的进程需要挂起等待。

    信号量的存在其实就是给进程间的信号,表示该资源可不可以被访问,因此也是作为进程间通信的一种方式。


二. 信号量的创建与销毁

    信号量和前面提到的管道、消息队列是一样的,都是需要函数创建来获取的:

wKiom1cPO7jAAimFAAAnd4ht7cQ852.png

函数参数中,key在消息队列中就提到过,它可以被认为是一个端口号,用ftok函数来创建:

wKioL1cPPPLDpGDmAAAJYnVVfDs415.png

pathanme是文件路径名,而proj_id是一个整数,二者结合可转换成一个整数标识。

nsems表示要创建多少个信号量,因为semget创建的是一个信号量集,可能有多个资源需要被标识;

semflg

信号量是一种用于进程间通信和同步的机制。它是一个计数器,用于保证在共享资源上的互斥访问。在Linux系统中,可以使用信号量来实现进程间的同步和互斥。以下是信号量的基本概念: - 计数器:信号量的值是一个计数器,它可以被多个进程共享。 - P操作:当一个进程需要访问共享资源时,它必须执行P操作,该操作会将信号量的值减1。如果信号量的值为0,则进程将被阻塞,直到信号量的值大于0。 - V操作:当一个进程使用完共享资源后,它必须执行V操作,该操作会将信号量的值加1。如果有进程正在等待该信号量,则唤醒其中一个进程继续执行。 在ZUCC中,可以使用信号量来实现进程的同步和互斥。首先,需要使用semget函数创建一个信号量集合,并使用semctl函数对信号量进行初始化。然后,可以使用semop函数执行P和V操作。例如,下面是一个简单的示例程序,用于演示信号量的使用: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/sem.h> #define SEM_KEY 1234 union semun { int val; struct semid_ds *buf; unsigned short *array; }; int main() { int semid, pid; union semun arg; struct sembuf sb; // 创建信号量集合 semid = semget(SEM_KEY, 1, IPC_CREAT | 0666); if (semid == -1) { perror("semget"); exit(EXIT_FAILURE); } // 初始化信号量 arg.val = 1; if (semctl(semid, 0, SETVAL, arg) == -1) { perror("semctl"); exit(EXIT_FAILURE); } // 创建子进程 pid = fork(); if (pid == -1) { perror("fork"); exit(EXIT_FAILURE); } else if (pid == 0) { // 子进程执行P操作 sb.sem_num = 0; sb.sem_op = -1; sb.sem_flg = SEM_UNDO; if (semop(semid, &sb, 1) == -1) { perror("semop P"); exit(EXIT_FAILURE); } printf("Child process\n"); // 子进程执行V操作 sb.sem_num = 0; sb.sem_op = 1; sb.sem_flg = SEM_UNDO; if (semop(semid, &sb, 1) == -1) { perror("semop V"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } else { // 父进程执行P操作 sb.sem_num = 0; sb.sem_op = -1; sb.sem_flg = SEM_UNDO; if (semop(semid, &sb, 1) == -1) { perror("semop P"); exit(EXIT_FAILURE); } printf("Parent process\n"); // 父进程执行V操作 sb.sem_num = 0; sb.sem_op = 1; sb.sem_flg = SEM_UNDO; if (semop(semid, &sb, 1) == -1) { perror("semop V"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } return 0; } ``` 在上述代码中,创建了一个信号量集合,并将其初始化为1。然后,创建了一个子进程和一个父进程,它们分别执行P和V操作。由于信号量的初始值为1,因此父进程和子进程都可以顺利地执行。如果将信号量的初始值改为0,那么父进程和子进程都将被阻塞,直到有一个进程执行V操作为止。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值