【Linux】System V信号量详解以及semget()、semctl()和semop()函数讲解

news2024/9/30 21:26:19

在这里插入图片描述

💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤
📃个人主页 :阿然成长日记 👈点击可跳转
📆 个人专栏: 🔹数据结构与算法🔹C语言进阶🔹C++🔹Liunx
🚩 不能则学,不知则问,耻于问人,决无长进
🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍

文章目录

  • 前言:
  • 一、什么是临界区和临界资源?
  • 二、SystemV信号量引出
  • 三、什么是SystemV信号量?
  • 四、 SystemV信号量的创建和控制以及操作
    • 1.semget()函数:
    • 2.semctl()函数:
    • 3.semop()函数:

前言:

上一篇博客讲解了System V共享内存,在最后说它的缺点时提到,他没有提供进程同步机制,那么为了弥补这个缺点,所以引入了信号量sem机制。

一、什么是临界区和临界资源?

  • 临界资源:多个进程共同使用的一份资源,例如共享内存就是一个临界资源

  • 临界区:不同进程内部,访问临界资源的那段代码

二、SystemV信号量引出

  • 打个比方:这场电影一共有五十个位置,设置一个信号量n,n = 50;看电影的人必须买票,买一张票信号量n就会减一,当n=0时,也就代表资源已经耗尽,没有位置了。但是如果有人退票的话,n会加1。买了票才能进入观影。
    相应的,每一个进程想进入临界资源,访问临界资源的一部分,不能让进程直接去使用临界资源(不能让用户直接去电影院抢占座位),而是先得申请 信号量(先得买票)。

这样说的话,我们只需要一个int型的变量就可做到计数器的功能了,那还大费周章的提出一个信号量干嘛呢?

1.不是局部变量

  • 这个变量肯定不是局部变量,那么使用一个全局变量可以吗?

2.不是全局变量

  • 如果使用全局变量,父子进程在申请信号量时,会发生写时拷贝,导致这个变量父子进程各自一份,也不太行。

3.不在共享内存中

  • 那就使用最近刚刚学习的共享内存不就好了吗。仔细思考也不可以。
  • 首先共享内存也就是说变量直接存储在内存中。我们创建的几个程序执行时是需要将指令放入cpu中进行执行。
  • 假设只看这个共享区的变量n,它的随着一个进程执行过程如下
    1.将内存中的数据n加载到cpu的寄存器
    2.n–(分析&&执行指令)
    3.将cpu修改完毕的n写回内存。
  • 一个进程执行流在执行的时候,在任何时刻都可能被切换 , 被切换的时候,会带走自己的上下文数据(包括n),然后再被切回来的时候,再把自己的上下文数据写入到cpu的寄存器中,继续执行。
  • 这样就有了一个问题:

假设有10个进程,分别为1,2,3,4…,9,10,而临界资源一共只有5份,所以信号量n也为5.
假设1先申请信号量,但运气不好执行完第一步,就被切走了,然后2,3,4,5,6都正常申请了信号量,此时信号量已经为0,后面7到10的进程都不能再申请了。
但此时1号又开始继续执行,由于第一次进来时n是5,继续执行第2,3步,n–为4,然后再写回到内存,此时n从0变成了4,这不就差了吗,明明都没有资源了,结果信号量成了4,后面的进程又可以继续申请,这样肯定就出错了。
所以n减减时,因为时序问题导致n有中间状态,可能导致数据不一致、但如果n只有一行汇编,那么该操作就是原子的!

4.提出System V信号量

所以就提出了信号量机制


三、什么是SystemV信号量?

信号量的本质是:是一个描述临界资源的计数器

System V信号量是一种在操作系统中提供的进程间通信(IPC)机制,用于实现进程之间的同步和互斥。它通过对计数器进行操作来控制资源的访问。

System V信号量由一个整型的标识符(semaphore identifier)来标识,每个标识符对应着一个信号量集合(semaphore set)。信号量集合中可以包含多个单独的信号量,每个信号量都有一个非负整数值。

四、 SystemV信号量的创建和控制以及操作

分别对一个semget()、semctl()和semop()

头文件:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

1.semget()函数:

首先回顾一下ftok():


ftok()函数生成key
头文件:

#include <sys/types.h>
#include <sys/ipc.h>

格式:

key_t ftok(const char *pathname, int proj_id);
  • 参数:
    pathname指针:一个字符串,用于标识一个文件的路径名。通常会选择一个已经存在的文件,因为 ftok() 函数将使用该文件的inode编号和 proj_id 参数通过算法来生成键值key。
    proj_id:一个整数,作为用于生成键的项目标识号。该参数通常取一个非负整数。
  • 返回值:成功则返回生成的键值,否则返回-1。

格式:

int semget(key_t key, int nsems, int semflg);

参数:

  • key:唯一key值,用于标识要创建或获取的信号量集合。
    key值可以使用ftok()获取

  • nsems:指定信号量集合中信号量的数量。你想创建几个信号量。可以想象成一个数组。

  • semflg:标志参数,用于指定信号量的创建方式和访问权限。有下面两个选项

IPC_CREATE创建共享内存,如果底层已经存在,则获取并返回;如果不存在,则创建共享内存然后再返回,
IPC_CREATE | IPC_EXCL如果底层不存在,则创建共享内存并返回;如果底层存在,则出错返回。言外之意,如果返回成功,那么一定是一个全新的内存块!

使用:
通过指定一个键值和其他参数,调用semget()函数可以创建一个新的信号量集合,或者获取一个已经存在的信号量集合。

返回值:
返回值是一个信号量标识符(semaphore identifier),它用于后续对信号量集合的控制和操作

注意理清一个概念:semget()可以一次申请多个信号量(n1,n2.n3,),其中一个信号量n1就是一个计数器

2.semctl()函数:

int semctl(int semid, int semnum, int cmd, ...);

参数:

  • semid:信号量标识符,用于指定要操作的信号量集合。
  • semnum:注意与seget()区分清楚。指定具体的信号量在集合中的索引,用于标识要操作的信号量。
  • cmd:执行的控制命令,用于指定具体的操作。
  • arg:根据不同的命令,需要提供的参数。

下面是semctl函数cmd形参说明表

命令解 释
IPC_STAT从信号量集上检索semid_ds结构,并存到semun联合体参数的成员buf的地址中
IPC_SET设置一个信号量集合的semid_ds结构中ipc_perm域的值,并从semun的buf中取出值
IPC_RMID从内核中删除信号量集合
GETALL从信号量集合中获得所有信号量的值,并把其整数值存到semun联合体成员的一个指针数组中
GETNCNT返回当前等待资源的进程个数
GETPID返回最后一个执行系统调用semop()进程的PID
GETVAL返回信号量集合内单个信号量的值
GETZCNT返回当前等待100%资源利用的进程个数
SETALL与GETALL正好相反
SETVAL用联合体中val成员的值设置信号量集合中单个信号量的值

用法
semctl()函数用于控制和管理信号量集合。
可以通过指定不同的控制命令(cmd)来实现不同的操作,例如设置信号量的初始值获取或改变信号量的值,以及删除信号量集合等。
具体的参数(如arg)根据不同的命令而有所不同。

3.semop()函数:

int semop(int semid, struct sembuf *sops, unsigned nsops);

参数:

  • semid:信号量标识符,用于指定要操作的信号量集合。由seget()获取
  • sops:指向一个sembuf结构体数组的指针,包含了一组操作。此结构的具体说明如下:(里面的注释很重呀)
struct sembuf {

	short semnum; 指定要操作的信号量在集合中的索引,从0开始计数。

	short op;指定要执行的操作。
如果sem_op的值大于0,则表示进行V(释放)操作,即增加信号量的值。
如果sem_op的值小于0,则表示进行P(等待)操作,即减少信号量的值。
如果sem_op的值等于0,则表示进行Z(零)操作,如果信号量的值为0,则等待。该操作通常用于同步操作,以等待某个特定条件的发生。

    short flag;  用于指定操作的标志。
IPC_NOWAIT:如果无法进行操作(例如信号量的值为0且sem_op为负数),则立即返回,不进行等待。
SEM_UNDO:系统在进程意外终止时,会自动撤销该进程对信号量的操作,以避免死锁。


  };
  • nsops:指定操作的数量。

作用: 用于对指定信号量集【semid】当中的指定数量的信号量【nsops:常常设置为1】,对它做操作【sembuf *sops】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1913219.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通用个人客户关系管理系统设计

设计一个通用个人客户关系管理系统&#xff08;Personal CRM&#xff09;&#xff0c;旨在帮助个人用户管理他们的社交网络、职业联系人、个人项目和日常沟通&#xff0c;需要关注以下几个核心设计原则和功能模块&#xff1a; 核心设计原则 易用性&#xff1a;界面简洁直观&a…

【操作系统】进程管理——信号量机制(个人笔记)

学习日期&#xff1a;2024.7.9 内容摘要&#xff1a;信号量机制&#xff0c;用信号量实现进程的同步与互斥 信号量机制 信号量的概念 在上节内容中&#xff0c;我们学习了进程互斥的软件和硬件解决方案&#xff0c;但这些方案都有各自的问题&#xff0c;双标志法都因为检查和…

机器人三定律及伦理分析

全世界的机器人定律并没有一个统一的标准或体系&#xff0c;但是在科学文献中&#xff0c;最广为人知的是由科幻小说家阿西莫夫提出的“机器人三定律”。本文将以这些定律为基础&#xff0c;分析现有的机器人伦理和实际应用中的问题&#xff0c;给出若干实例&#xff0c;并对相…

LVS集群及其它的NAT模式

1.lvs集群作用&#xff1a;是linux的内核层面实现负载均衡的软件&#xff1b;将多个后端服务器组成一个高可用、高性能的服务器的集群&#xff0c;通过负载均衡的算法将客户端的请求分发到后端的服务器上&#xff0c;通过这种方式实现高可用和负载均衡。 2.集群和分布式&#…

【光伏仿真系统】光伏设计的基本步骤

随着全球对可再生能源需求的不断增长&#xff0c;光伏发电作为一种清洁、可再生的能源形式&#xff0c;正日益受到重视。光伏设计是确保光伏系统高效、安全、经济运行的关键环节&#xff0c;它涉及从选址评估到系统安装与维护的全过程。本文将详细介绍光伏设计的基本步骤&#…

AI大模型走进汽车车机,智驾将是未来

车机里的AI大模型在汽车行业中的应用越来越广泛&#xff0c;主要体现在智能座舱和自动驾驶系统的深度融合上。通过将AI大模型应用于车机系统&#xff0c;可以实现更高智能化的人车交互体验。AI大模型作为人工智能发展的核心引擎&#xff0c;正在成为汽车智能化发展的关键之一。…

【靶机实战】GeoServer 远程代码执行漏洞复现

# 在线靶场 可以通过访问极核官方靶场开启靶机实验&#xff1a;极核靶场 -> 漏洞复现靶场 -> GeoServer-远程代码执行 原文&#xff1a;【靶机实战】GeoServer 远程代码执行漏洞复现 - 极核GetShell (get-shell.com) # 简介 CVE-2024-36401是一个高危的远程代码执行漏…

Springboot项目实训--day2

今天学习的是idea和MySQL的连接&#xff0c;以及一些基本的增删改查的功能实现。 一、软件下载 昨天下载了idea&#xff0c;今天要是西安它们的连接&#xff0c;就需要再下载MySQL&#xff0c;我的MySQL是前面几个学期别人帮忙下载的&#xff0c;所以具体的操作步骤我也不清楚…

VSTO插件功能介绍-清除空行(列)

提示目前我的插件命名为“哆哆Excel”&#xff0c;还没有打包&#xff0c;主要是自己工作中要用到的东西&#xff0c;它能提高我的工作效率&#xff0c;10倍以上开发&#xff1a;Visual Studio 2019语言&#xff1a;VB.net看个图吧 今天要记录的问题是这样子的 当时有一个同事&…

HTTP 概况

Web的应用层协议是超文本传输协议(HyperTextTransferProtocol&#xff0c;HTTP)&#xff0c;它是 Web的核心。HTTP由两个程序实现:一个客户程序和一个服务器程序。客户程序和服务器程序运行在不同的端系统中&#xff0c;通过交换HTTP报文进行会话。HTTP定义了这些报文的结构以及…

基于CentOS Stream 9平台搭建FRP内网穿透

内网穿透方法很多&#xff0c;本文以github上很火的frp为例 1.frp官方 文档&#xff1a;https://gofrp.org/zh-cn/docs/overview/ 1.1 下载 https://github.com/fatedier/frp/releases 选中合适的版本 2. 服务端&#xff08;服务器&#xff09;搭建frps 需要公网IP服务器 选…

Qt Creator仿Visual Studio黑色主题

转自本人博客&#xff1a;Qt Creator仿Visual Studio黑色主题 1.演示 配置文件和步骤在后面&#xff0c;先看成品&#xff0c;分别是QWidget和QML的代码编写界面&#xff1a; 2. 主题配置文件 下载链接&#xff1a;QtCreator _theme_VS_dark.xml 也可以自己新建一个xml文件&…

【单片机毕业设计选题24053】-基于单片机的WiFi控制门禁系统设计

系统功能: 系统上电后OLED显示智能门禁系统 Door:xxxxxx 初始化ESP8266完成后显示 Door:Closed 短按按键SW4可打开电磁锁OLED显示Door:Open&#xff0c;约五秒后电磁锁自动关闭OLED 显示Door:Closed 根据“TCP调试助手使用说明”操作&#xff0c; 在调试助手界面发送Open后…

14-56 剑和诗人30 - IaC、PaC 和 OaC 在云成功中的作用

介绍 随着各大企业在 2024 年加速采用云计算&#xff0c;基础设施即代码 (IaC)、策略即代码 (PaC) 和优化即代码 (OaC) 已成为成功实现云迁移、IT 现代化和业务转型的关键功能。 让我在云计划的背景下全面了解这些代码功能的当前状态。我们将研究现代云基础设施趋势、IaC、Pa…

雷达视频采集卡 HPx-410

产品简介 雷达视频采集卡 HPx-410&#xff0c;应用于接入导航雷达数据&#xff0c;导航雷达视频&#xff0c;适用于JRC雷达、古野furuon雷达、Sperry雷达等多种型号的雷达。 HPx-410 可以接入导航雷达数据&#xff0c;引入导航雷达原始回波&#xff0c;然后将雷达视频采集到计…

PageDTO<T>,PageQuery,BeanUtils,CollUtils的封装

一、PageDTO<T> import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.fasterxml.jackson.annotation.JsonIgnore; import com.tianji.common.utils.BeanUtils; import com.tianji.common.utils.CollUtils; import com.tianji.common.utils.…

人工智能算法工程师(中级)课程2-Opencv视觉处理之高级操作与代码详解

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能算法工程师(中级)课程2-Opencv视觉处理之高级操作与代码详解。在上一节课中的OpenCV基础操作我们了解到OpenCV是一个开源的计算机视觉软件库。它提供了各种视觉处理函数&#xff0c;并支持多种编程语言&…

数据结构基础--------【二叉树题型】

1、前提(待补充) 1.**DFS&#xff08;Depth First Search&#xff09;&#x1f617;*递归法得到最终的数组&#xff08;深度优先算法&#xff09; 其过程简要来说是对每一个可能的分支路径深入到不能再深入为止&#xff0c;如果遇到死路就往回退&#xff0c;回退过程中如果遇…

MMGPL: 多模态医学数据分析与图提示学习| 文献速递-基于深度学习的多模态数据分析与生存分析

Title 题目 MMGPL: Multimodal Medical Data Analysis with Graph Prompt Learning MMGPL: 多模态医学数据分析与图提示学习 01 文献速递介绍 神经学障碍&#xff0c;包括自闭症谱系障碍&#xff08;ASD&#xff09;&#xff08;Lord等&#xff0c;2018年&#xff09;和阿…

使用Maven命令将第三方jar包安装到maven本地仓库

使用Maven命令将第三方jar包安装到maven本地仓库 事例&#xff1a; 第三方jar包 &#xff1a;common-pojo-1.0-SNAPSHOT.jar Maven命令 mvn install:install-file -Dfilejar包在本地磁盘的路径 -DgroupId组织名称 -DartifactId项目名称 -Dversion版本号 -Dpackaging打包方式 完…