Linux 信号量

article/2025/11/7 3:45:34

信号量

    • 信号量
    • 信号量的定义
    • 信号量理论例子
    • Linux信号量机制
    • 使用信号量

信号量

信号量:用于管理对资源的访问。
(1) 当我们编写的程序使用了线程时,不管它是运行在多用户系统上、多进程系统上,还是运行在多用户多进程系统上,我们通常会发现,程序中存在着一部分临 界代码,我们需要确保只有一个进程 (或一个执行线程) 可以进入这个临界代码并拥有对资源独占式的访问权。

(2)信号量有着复杂的编程接口,但幸运的是,我们可以很轻松地为自己提供一个更简单的接口,它足够应付大多数信号量编程的问题。

(3)为了防止出现因多个程序同时访问-一个共享资源而引发的问题,我们需要有一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域。
(4)要想编写通用的代码,以确保程序对某个特定的资源具有独占式的访问权是非常困难的。虽然有一个名为Dekker算法的解决方法,但这个算法依赖于“忙等待”或“自旋锁”。也就是说,一个进程要持续不断地运行以等待某个内存位置被改变。在像Linux这样的多任务环境中,人们并不愿意使用这种浪费CPU资源的处理方法。但如果硬件支持独占式访问(一般是通过特定的CPU指令的形式),那么情况就变得简单多了。一个硬件支持的例子就是,用一条指令以原子方式访问并增加寄存器的值,在这个读取/增加/写入操作执行的过程中不会有其他指令(甚至一个中断)发生。
(5)一种可能的解决方法是,使用带O_ EXCL标志的open函数来创建锁文件,它提供了原子化的文件创建方法。它允许一个进程通过获取一个令牌(即新创建的文件)来取得成功。这个方法比较适合于处理简单的问题,但对于更复杂的例子,它就显得比较杂乱且缺乏效率。
(6)荷兰计算机科学家Edsger Dijkstra提出的信号量概念是在并发编程领域迈出的重要一步。 信号量是一个特殊的变量,它只取正整数值,并且程序对其访问都是原子操作。

信号量的一个更正式的定义是:它是一个特殊变量,只允许对它进行等待(wait) 和发送信号(signal)这两种操作。因为在Linux编程中,“等待”和“发送信号”都已具有特殊的含义,所以我们将用原先定义的符号来表示这两种操作。

  • P (信号量变量):用于等待。
  • V (信号量变量):用于发送信号。
    这两个字母分别来自于荷兰语单词passeren(传递,就好像位于进入临界区域之前的检查点)和vrijgeven (给予或释放,就好像放弃对临界区域的控制权)。在与信号量关联的内容中,你可能还会看到术语“开”(up)和“关”(down),它们取自开、关信号标志的用法。

信号量的定义

最简单的信号量是只能取值0和1的变量,即二进制信号量。这也是信号量最常见的一一种形式。可以取多个正整数值的信号量被称为通用信号量。
PV操作的定义非常简单。假设有一个信号量变量sv,则这两个操作的定义如图:
在这里插入图片描述

还可以这样看信号量:当临界区域可用时,信号量变量sv的值是true,然后P(sv)操作将它减1使它变为false以表示临界区域正在被使用;当进程离开临界区域时,使用V(sv) 操作将它加1,使临界区域再次变为可用。注意,只用一个普通变量进行类似的加减法是不行的,因为在C、C++、C#或几乎任何一个传统的编程语言中,都没有一个原子操作可以满足检测变量是否为true,如果是再将该变量设置为false的需要。这也是信号量操作如此特殊的原因。

信号量理论例子

我们用一个简单的理论性的例子来说明其工作原理。假设有两个进程proc1和proc2,这两个进程都需要在其执行过程中的某–时刻对–个数据库进行独占式的访问。我们定义一一个二进制信号量sv,该变量的初始值为1,两个进程都可以访问它。要想对代码中的临界区域进行访问,这两个进程都需要执行相同的处理步骤,事实上,这两个进程可以只是同一个程序的两个不同执行实例。两个进程共享信号量变量sv。一旦其中一个进程执行了P(sv)操作,它将得到信号量,并可以进入临界区域。而第二个进程将被阻止进入临界区域,因为当它试图执行P(sv)操作时,它会被挂起以等待第一一个进程离开临界区域并执行V(sv)操作释放信号量。
需要的伪代码对两个进程都是相同的,如下所示:

semaphore sv = 1;
loop forever {
P(sv) ;
critical code section;
V(sv) ;
noncritical code section;
}

这段代码相当简单,这是因为PV操作的功能非常强大。如图显示了Pv操作是如何把守代码中的临界区域的。

在这里插入图片描述

Linux信号量机制

. 头文件

 #include <sys/sem.h>#include <sys/types.h>#include <sys/ipc.h>#include <semaphore.h>
  • int semget(key_t key, int nsems, int semflg);
semget()创建或者获取已存在的信号量
semget()成功返回信号量的 ID, 失败返回-1
key:两个进程使用相同的 key 值,就可以使用同一个信号量
nsems:内核维护的是一个信号量集,在新建信号量时,其指定信号量集中信号量的个数
semflg 可选: IPC_CREAT IPC_EXCL
  • *int semop( int semid, struct sembuf sops, unsigned nsops);
semop()对信号量进行改变,做 P 操作或者 V 操作
semop()成功返回 0,失败返回-1
struct sembuf
{
unsigned short sem_num; //指定信号量集中的信号量下标
short sem_op; //其值为-1,代表 P 操作,其值为 1,代表 V 操作
short sem_flg; //SEM_UNDO
};
  • int semctl( int semid, int semnum, int cmd, …);
semctl()控制信号量
semctl()成功返回 0,失败返回-1
cmd 选项: SETVAL IPC_RMID
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *_buf;
};
  • int sem_init(sem_t *sem, int pshared, unsigned int value);
  • int sem_wait(sem_t *sem);
  • int sem_post(sem_t *sem);
  • int sem_destroy(sem_t *sem);

使用信号量

两线程完成输入

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <fcntl.h>char buff[128] = {0};sem_t sem1;sem_t sem2;void* PthreadFun( void *arg){int fd = open("a.txt", O_RDWR | O_CREAT, 0664);assert(fd != -1);//函数线程完成将用户输入的数据存储到文件中while(1){sem_wait(&sem2);if(strncmp(buff, "end", 3) == 0){break;}write(fd, buff, strlen(buff));memset(buff, 0, 128);sem_post(&sem1);}sem_destroy(&sem1);sem_destroy(&sem2);}int main(){sem_init(&sem1, 0, 1);sem_init(&sem2, 0, 0);pthread_t id;int res = pthread_create(&id, NULL, PthreadFun, NULL);assert(res == 0);//主线程完成获取用户数据的数据,并存储在全局数组 buff 中while(1){sem_wait(&sem1);printf("please input data: ");fflush(stdout);fgets(buff, 128, stdin);buff[strlen(buff) - 1] = 0;sem_post(&sem2);if(strncmp(buff, "end", 3) == 0){break;}}pthread_exit(NULL);}

在这里插入图片描述


http://chatgpt.dhexx.cn/article/2vDk99Eb.shtml

相关文章

Linux内核信号量:二值信号量/互斥信号量,计数信号量,读写信号量

《semaphore信号量&#xff1a;一个简单的示例程序》用户态程序 目录 概念 应用场景 使用方法 内核信号量的构成 信号量的API 初始化 PV操作 获取信号量&#xff08;P&#xff09; 释放内核信号量&#xff08;V&#xff09; 补充 内核信号量的使用例程 场景1 场景…

Linux系统中信号量的基本使用方法

大家好&#xff0c;今天主要和大家聊一聊&#xff0c;如何使用信号量的方法。 目录 第一&#xff1a; 父子进程相隔1s报数一次 第二&#xff1a;利用信号量实现父子进程通信 信号量(Semaphore)&#xff0c;有时被称为信号灯&#xff0c;是在多线程环境下使用的一种设施&#…

信号量【Linux】

文章目录 1. POSIX信号量1.1 引入1.2 概念1.3 PV原语&#xff08;原理&#xff09;1.4 相关接口 2. 二进制信号量3. 基于环形队列的生产消费模式3.1 介绍3.2 为什么要使用环形队列3.3 环形队列的作用3.4 实现互斥和同步两个信号量框架生产和消费的逻辑完善环形队列1信号量完善环…

Linux信号量操作

信号量简介&#xff1a; 在对于临界区资源管理的过程中&#xff0c;多个程序同时访问一个共享资源经常容易引发一系列问题&#xff1a;如死锁&#xff0c;结果不唯一等等&#xff0c;在1965年&#xff0c;由荷兰科学家E.W.Dijkstra提出了一种新的进程同步工具&#xff0c;信号…

【关于Linux中----信号量及其使用场景】

文章目录 一、解释信号量1.1 概念的引入1.2 信号量操作和使用接口 二、信号量使用场景2.1 引入环形队列&&生产消费问题2.2 代码实现2.3 对于多生产多消费的情况2.4 申请信号量和加锁的顺序问题2.5 多生产多消费的意义 一、解释信号量 1.1 概念的引入 我们知道&#x…

linux(信号量)

信号量 几个基本概念临界资源临界区原子性互斥 信号量后台进程前台进程 信号储存信号处理信号(信号捕捉) 发送信号1、键盘产生&#xff1a;2、系统调用接口发送信号3、由软件条件产生信号4、硬件异常发送信号 内核中的信号量**信号量在内核中的数据结构****信号集操作函数** 信…

Linux--信号量

1.信号量的定义: 信号量是一个特殊的变量&#xff0c;一般取正数值。它的值代表允许访问的资源数目&#xff0c; 获取资源时&#xff0c;需要对信号量的值进行原子减一&#xff0c;该操作被称为p操作。当信号量值为0时&#xff0c;代表没有资源可用&#xff0c;p操作会阻塞。释…

【Linux】Linux的信号量集

所谓信号量集&#xff0c;就是由多个信号量组成的一个数组。作为一个整体&#xff0c;信号量集中的所有信号量使用同一个等待队列。Linux的信号量集为进程请求多个资源创造了条件。Linux规定&#xff0c;当进程的一个操作需要多个共享资源时&#xff0c;如果只成功获得了其中的…

linux信号量简介

一、什么是信号量 为了防止多个程序同时访问一个共享资源而引发的一系列问题&#xff0c;我们需要一种访问机制&#xff0c;它可以通过生成并使用令牌来授权&#xff0c;在同一时刻只能有一个线程访问代码的临界区域。 临界区域是指执行数据更新的代码需要独占式地执行。而信…

Linux下信号量使用总结

目录 1.Linux下信号量简介 2.POSIX信号量 2.1 无名信号量 2.2 有名信号量 3.System V信号量 1.Linux下信号量简介 信号量是解决进程之间的同步与互斥的IPC机制&#xff0c;互斥与同步关系存在的症结在于临界资源。 临界资源是在同一个时刻只容许有限个&#xff08;一般只有…

Linux信号量详解

Linux信号量详解 1.什么是信号量信号量是一种特殊的变量&#xff0c;访问具有原子性。只允许对它进行两个操作&#xff1a;1)等待信号量当信号量值为0时&#xff0c;程序等待&#xff1b;当信号量值大于0时&#xff0c;信号量减1&#xff0c;程序继续运行。2)发送信号量将信号量…

Linux进程间通信—信号量

一、概述 进程间通信&#xff08;interprocess communication&#xff0c;简称 IPC&#xff09;指两个进程之间的通信。系统中的每一个进程都有各自的地址空间&#xff0c;并且相互独立、隔离&#xff0c;每个进程都处于自己的地址空间中。所以同一个进程的不同模块譬如不同的函…

Linux操作系统-信号量

信号量也属于一种进程间通信的机制&#xff0c;与其他的进程间通信不同&#xff0c;信号量不是用来传输数据的&#xff0c;而是用来进程间同步与互斥。除此之外&#xff0c;信号量还可以实现线程间的互斥。 信号量是什么&#xff1f; 信号量的本质是一个计数器。 一个信号量…

Linux·信号量全解

目录 信号量 进程间 【无名信号量完成 有血缘关系的进程间 互斥】 知识点2【有名信号量 没有血缘进程互斥】 1、创建一个有名信号量 2、信号量的关闭&#xff1a; 3、信号量文件的删除 4、P操作 sem_wait V操作sem_post 销毁信号量sem_destroy 知识点3【有名信号量 没…

Linux-----信号量

信号量 信号量原理信号量概念信号量函数基于环形队列的生产消费模型空间和数据资源生产者和消费者申请、释放信号量模拟实现基于环形队列的生产者消费者模型 信号量原理 之前我们知道被多个执行流同时访问的公共资源叫做临界资源&#xff0c;而临界资源不保护的话会造成数据不…

Linux信号量

文章目录 POSIX信号量信号量的原理信号量的概念信号量函数 二元信号量模拟实现互斥功能基于环形队列的生产消费模型空间资源和数据资源生产者和消费者申请和释放资源必须遵守的两个规则代码实现信号量保护环形队列的原理 POSIX信号量 信号量的原理 我们将可能会被多个执行流同…

Linux —— 信号量

目录 一、POSIX信号量 1. 什么是信号量 2. 信号量的基本原理 二、与信号量相关的操作 1. 初始化信号量 2. 销毁信号量 3. 等待信号量 4. 发布信号量 三、基于环形队列的生产者消费者模型 1. 空间资源和数据资源 2. 生产者和消费者申请和释放资源 四、模拟实现基于…

Double取值intValue()与doubleValue()之参数缺省

Double调用intValue()是四舍五入向下取整。 调用doubleValue()才是取double真实值。

java.lang.NullPointerException: Attempt to invoke virtual method ‘int java.lang.Integer.intValue()‘

问题 对于PreparedStatement 对象设置参数时&#xff0c; 提示该错误; java.lang.NullPointerException: Attempt to invoke virtual method ‘int java.lang.Integer.intValue()’ 具体问题 2022-09-06 21:28:10.695 11368-11755/com.example.electronicmall E/AndroidRunt…

IntValue()方法 和 ValueOf()方法

intValue() 1.intValue()是java.lang.Number类的方法&#xff0c;Number是一个抽象类。Java中所有的数值类都继承它。也就是说&#xff0c;不单是Integer有intValue方法&#xff0c;Double&#xff0c;Long等都有此方法。 2.此方法的意思是&#xff1a;输出int数据。每个数值类…