进程间通信之——信号量(一)(system V)

2023-05-16

system v信号量又被称为system v信号量集。它的本质就是一个计数器,用来为多个进程共享的数据结构提供受控访问。

信号量支持的操作有:


使用最广泛的信号量为二元信号量,它控制单个资源,对于这种信号量而言,它只有两种合法值: 0 和 1 ,对应一个可用的资源。若当前有资源可用,则与之对应的二值信号量的值为 1 ;若资源已被占用,则与之对应的二值信号量的值为 0 。当进程申请资源时,如果当前信号量的值为 0 ,那么进程会陷入阻塞,直到有其他进程释放资源,将信号量的值加 1 才能被唤醒。

内核为每个信号量集维护者一个semid_ds结构,该结构定义了此信号量的权限、指针、最近修改时间和队列中信号量队列信息:/usr /src/kernels/2.6.32-431.el6.i686/include/Linux/sem.h


——sem_perm权限;

——sem_otime最近semop时间;

——sem_ctime最近修改时间;

——sem_base队列第一个信号量;

——sem_pending阻塞信号量;

——sem_pending_last最后一个阻塞信号量;

——undo表示undo队列;

——sem_nsems表示信号量个数;

每一个信号量还有一个结构:


——semval表示信号量值;

——sempid表示最近一个操作的进程号pid;

当然信号量仍然存在系统限制


——SEMMNI系统容许的信号量集的上限;

——SEMMSL 单个信号量集中信号量的上限;

——SEMMNS 系统容许的信号量的上限

——SEMOPM 单次 semop 调用能够操作的信号量的最大值;

——SEMVMX 信号量值的上限;

信号量集函数

semget

功能:用来创建或打开一个信号量集;

原型:int semget(key_t key, int nsems, int semflg);

参数:key表示信号集的名字,一般由ftok函数产生;

         nsems表示信号集中信号量的个数;

         semflg用来标识信号量集合的权限,和创建文件类似,由九个权限标志为构成如0644,他还可以和以下参数一起使用:


——IPC_CREAT表示如果key不存在就创建;

——IPC_EXCL表示如果key存在就返回失败;

——IPC_NOWAIT表示如果需要等待,则直接返回错误;

返回值成功返回一个非负整数即该信号量的标识码;失败返回-1;

semctl

功能:用来控制信号量集;

原型:int semctl(int semid, int semnum, int cmd, ...);

参数:semid由semget返回的信号量标识;

          semnum信号集中信号量的序号;

          cmd表示将要采取的操作;

          最后一个参数根据命令不同而不同,他是一个类型为senum的联合(下文会有介绍);

cmd可采取的操作有:IPC_RMID、IPC_SET、IPC_STAT和IPC_INFO,定义在:/usr/include/linux/ipc.h中


IPC_RMID、IPC_SET、IPC_STAT和IPC_INFO这四个参数都是system v的通用参数;

——IPC_RMID表示删除信号集

——IPC_STAT表示获取ipc_perm的参数

——IPC_INFO表示获取系统信息

——IPC_SET表示设置ipc_prem的参数,对于这个参数,semctl有单独的规定参数


——GETPID获取信号量拥有者的pid的值;

——GETVAL获取信号量的值;

——GETALL获取所有信号量的值;

——GETNCNT获取等待信号量的值递增的进程数;

——GETZCNT获取等待信号量的值递减的进程数;

——SETVAL设置信号量的值;

——SETALL设置所有信号的值;

第四个参数的senum的联合体定义如下:


接下来介绍几个常用的操作

|cmd操作为GETVAL

semctl第二个参数为信号量编号,若执行成功,semctl返回当前信号量的值,失败返回-1;

|cmd操作为SETVAL

semctl第二个参数为信号量编号,第四个参数为要设置的val

返回值:成功返回0;失败返回-1;

semop

功能:修改集合中一个或多个信号量值;

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

参数:semid信号领=量标识码;

          sops是一个sembuf类型的指针;

          nsops标识信号量个数;

sembuf结构体定义如下:


——sem_num标识信号量编号;

——sem_op信号量一次pv操作时加减的数值,一般会用到两个值:

                   -1,p操作,等待信号量变得可用

                   +1,v操作,发出的信号量变得可用

——sem_flg操作标识,有以下值: IPC_NOWAIT和SEM_UNDO

       IPC_NOWAIT对某一信号量操作,即使其中一个操作失败,也不会导致修改其他信号量的值;

       SEM_UNDO当进程退出后,该进程对sem进行的操作将被撤销;


返回值成功返回0;失败返回-1;

测试案例一:哲学家就餐问题

问题描述:

(由Dijkstra首先提出并解决)5个哲学家围绕一张圆桌而坐,桌子上放着5支筷子,每两个哲学家之间放一支;哲学家的动作包括思考和进餐,进餐时需要同时拿起他左边和右边的两支筷子,思考时则同时将两支筷子放回原处。如何保证哲学家们的动作有序进行?如:不出现相邻者同时要求进餐;不出现有人永远拿不到筷子;

解决思路:五只筷子相当于资源,保证每次会有两位哲学家先进餐,进餐完后在换其他哲学家,能够保证五位哲学家都能进餐

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

int semid;

union semun{
	int value;
};
//获得资源
void get_sour(int num)
{
	struct sembuf sb[2]={
		{num,-1,0},
		{(num+1)%5,-1,0}
	};
	semop(semid,sb,2);
}

//释放资源
void free_sour(int num)
{
	struct sembuf sb[2]={
		{num,1,0},
		{(num+1)%5,1,0}
	};
	semop(semid,sb,2);

}

void phil(int num)
{
	while(1){
		printf("%d is thinking...\n",num);
		sleep(rand()%5);
		get_sour(num);
		printf("%d start eating...\n",num);
		sleep(rand()%3);
		printf("%d end eating...\n",num);
		free_sour(num);
	}
}

int main()
{
	srand(getpid());
	semid=semget(1234,5,IPC_CREAT|0600);//创建信号量
	if(semid == -1){
		perror("semget");
		exit(1);
	}
	union semun s;
	s.value=1;
	//五个信号量分别设初值
	int i=0;
	for(i=0;i<5;i++){
		semctl(semid,i,SETVAL,s);
	}
	//创建五个进程——一个父进程+4个子进程
	int num=0;//为每个进程编号,父进程初始化编号为0
	for(i=1;i<5;i++){
		pid_t pid=fork();
		if(pid == 0){
			num=i;
			break;
		}
	}


	phil(num);
}

运行结果:


本文主要介绍了system v信号量的一些基本概念,目的是能够对信号量有一个基本的初步认识,文中如有不当之处,欢迎大家指正。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

进程间通信之——信号量(一)(system V) 的相关文章

  • Android 中的 System.out.println?

    有什么方法可以在 android studio 中查看我的打印报表而不显示时间和目录 当该文本占用如此多的空间时 它会非常分散注意力并且难以调试 在 Android Studio 的 Android Monitor 视图中 在版本 1 3
  • C中的popen()和system()有什么区别

    我想在我的 C 代码中执行二进制文件 哪个更好执行 popen or system EDIT 我尝试使用system 但是执行的进程似乎最终卡住了并且没有返回到我的代码 有什么建议吗 Thanks popen 使您可以控制进程的输入或输出文
  • 在 PHP 中执行 exec() 或 system() 且不等待输出

    我想从 PHP 脚本中触发 eider exec 或 system 中的 shell 命令 但这是一项需要一段时间才能完成的任务 有没有办法触发它并继续运行 PHP 页面加载而不延迟 编辑 我使用的是 CentOS 6 PHP 5 3 取决
  • 最小化时如何将.net应用程序放入系统托盘中?

    任何人都可以建议一个好的代码示例vb net c 代码 用于在最小化时将应用程序放入系统托盘中 将 NotifyIcon 控件添加到窗体中 然后使用以下代码 private void frm main Resize object sende
  • C++ 向外部程序提供输入和输出管道

    我正在尝试使用一些输入调用外部程序 并在程序中检索其输出 它将看起来像 一些输入 外部程序 检索输出 我首先想到使用popen 但这似乎是不可能的 因为管道不是双向的 有没有什么简单的方法可以处理这种事情linux 我可以尝试制作一个临时文
  • 打开 Internet 属性并等待用户将其关闭 C#

    是否有可能打开 Internet 属性窗口 Code System Diagnostics Process p p System Diagnostics Process Start InetCpl Cpl 4 并等到用户关闭它 然后检查互联
  • 数据对齐:限制内存地址为数据类型大小的倍数的原因

    我理解数据对齐的一般概念 但我不理解的是对内存地址值的限制 强制为基础数据类型大小的倍数 这个答案 https stackoverflow com a 672482 11205473很好地解释了数据对齐 Quote 我们看一下内存映射 00
  • 如何在 OS X C 代码中创建异步计时器?

    所以这个问题实际上是 为什么 time h 在 OS X 和 Linux 上不一样 但是 我已经接受了这些分歧 为了在 Unix 系统上创建计时器 我遵循了本教程http www helsinki fi atk unix dec manua
  • PHP 系统() 参数

    我有以下代码执行C 程序 and 输出它 div div 我怎样才能做到这一点您可以将参数传递给 c 程序 这样说 如果这是c program include
  • 在 docker exec 命令中使用“*”

    我正在尝试在运行的 docker 容器中运行特定命令 Docker exec t containername1 ls tmp sth 作为回报我收到 ls cannot access tmp sth No such file or dire
  • 在 php 中运行 windows 命令

    是否可以从 php 运行 Windows 命令行代码 我的Windows命令行代码是
  • Perl system() 调用会终止吗?

    Can a system 打电话可以永远die在 Perl 5 中 换句话说 为了 100 防崩溃 执行以下操作的程序system call 是否需要将其包装成eval block 或者这是完全没有必要的 我在 中没有发现任何提及这种可能性
  • System.setProperty("sun.net.http.allowRestrictedHeaders", "true") 在詹金斯中不起作用

    我正在尝试在 http 请求标头中发送原始标头 但是当我获取其值时 我得到的是 null 而不是我在原始标头中设置的 url 另外 我还使用以下命令启用了受限标头作为詹金斯作业中请求标头的一部分发送 System setProperty s
  • 将系统命令的结果绑定到 Haskell 中的变量

    如何在 Haskell 中运行系统命令and将其结果 即标准输出 绑定到变量 在伪 Haskell 中 我正在寻找类似以下内容的内容 import System Process main do output lt callCommand e
  • 从多线程程序中调用 system()

    我们正在开发一个用 C 编写的多线程内存消耗应用程序 我们必须执行大量的 shellscript linux 命令 并获取返回码 读完之后article http www linuxprogrammingblog com threads a
  • Python:无法使用 os.system() 打开文件

    我正在编写一个使用该应用程序的 Python 脚本pdftk http www pdflabs com tools pdftk the pdf toolkit 几次来执行某些操作 例如 我可以在 Windows 命令行 shell 中使用
  • 除了 Erlang 之外,还有哪些系统是基于“绿色流程”的?

    我正在阅读这个信息页面绿线 维基百科 http en wikipedia org wiki Green thread我想知道 除了 Erlang 之外 还有哪些编程系统依赖于 绿色进程 Edit 绿线 绿色流程 基于绿色流程 Erlang
  • 如何在 R 中使用别名运行系统可执行文件?

    假设我正在 R 中运行系统命令来运行executable inputfile lt path myfile txt 我该如何更换 path myfile txt在下面的命令中inputfile如下面命令所示 system executabl
  • Android系统应用程序信息

    我想要一些有关系统应用程序的一般信息 我正在与一家制造商合作 他们愿意向我提供使我的应用程序成为系统应用程序所需的信息 但是 我不确切知道这些信息应该是什么 也不知道如何更改我的应用程序以使其成为具有给定信息的系统应用程序 我相信我的清单中
  • 我需要转义该 MATLAB 字符串中的字符吗?

    我想在 MATLAB 中调用以下 bash 命令 grep Up to test linux vision1 1 log awk print 7 I use system 在MATLAB中 但结果有错误 gt gt status strin

随机推荐

  • excel2010取消保护忘记密码宏的方式-针对公务员职位表保护

    excel2010 视图 宏 新建 取消新建 编辑 替换以下内容 Option Explicit Public Sub AllInternalPasswords 39 Breaks worksheet and workbook struct
  • CS5汉化步骤

    CS5汉化步骤 第一步 xff1a 关闭PS xff0c 下载汉化补丁 xff08 zh CN xff09 xff0c 将汉化补丁复制到安装目录下的 Locales 文件夹中 xff0c 通常为 C Program Files Adobe
  • 用eclipse建一个web页面(图文)

    步骤1 xff1a 创建Dynamic Web Project 动态web项目 打开eclipse xff0c 在工具栏选在New gt Dynamic Web Project 在打开的Dynamic Web Project窗口 xff0c
  • pip下载源的两种修改方法

    很多入行网工不久的萌新 xff0c 在使用python进行NetDevOps的过程中 xff0c 需要经常使用python的包管理器pypi下载第三方库 比如paramiko netmiko netaddr等等 但是 xff0c 默认源的下
  • 2、树莓派3 Model B ——— 使用GIT工具安装wiringPi

    1 WiringPi简介 WiringPi是应用于树莓派平台的GPIO控制库函数 xff0c WiringPi遵守GUN Lv3 wiringPi使用C或者C 43 43 开发并且可以被其他语言包转 xff0c 例如python ruby或
  • C语言之文件操作05——矩阵(数据)的读取方法

    数据读取 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 6
  • String和Stringbuff和Stringbuilder区别

    string类型属于引用类型 xff0c 不属于八个基本变量 每次指定一个String a 61 34 a 34 时 xff0c jvm会在内存中新建一个对象 xff0c 当你再给a赋值的时候 xff0c jvm并没有改变a引用的值 xff
  • docker build 后面为什么要跟个 .

    我们在构建镜像文件时无非是使用 xff1a docker build t test ubuntu v1 或者 docker build f docker test Dockerfile 来进行构建镜像 xff0c 用第一个命令时任务 指代的
  • 洛谷P4180 严格次小生成树

    题目描述 小 C 最近学了很多最小生成树的算法 xff0c Prim 算法 Kruskal 算法 消圈算法等等 正当小 C 洋洋得意之时 xff0c 小 P 又来泼小 C 冷水了 小 P 说 xff0c 让小 C 求出一个无向图的次小生成树
  • 【搜索与回溯算法】马的走法

    题目 xff1a 在5X5的棋盘上 xff0c 给定一位置 xff0c 输出马回到原点有多少种不同的方案 注意 xff1a 马走的每一步必须在棋盘上 xff0c 走斜日 xff0c 如下图 xff1a 输入 xff1a 给定一位置 xff0
  • 如何使用mysql api关闭ssl模式提高查询效率

    昨天测试部同事用大呼测试我们的业务系统 xff0c 数据库用的是MySQL 单呼的时候数据库查询正常 xff0c 但是呼叫量一大就出现了数据库查询延迟的情况 经过分析发现是由于MySQL Server的数据库端开启了SSL xff0c 每次
  • iOS开发之多线程--多线程简单介绍

    一 进程和线程 1 什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的 xff0c 每个进程均运行在其专用且受保护的内存空间内 比如同时打开QQ Xcode xff0c 系统就会分别启动2 个进程 通过 活动监视器 可
  • UIImageView的基本用法

    UIViewContentModeScaleTo Fill UIViewContentModeScaleAs pectFit contents scaled to fit with fixed aspect remainder is tra
  • compton透明设置

    compton是一个使你窗口透明化的工具 xff0c 如果你当前使用的软件支持窗口透明的功能 xff0c 那么compton可以帮你设置透明度 xff0c 阴影效果 xff0c 窗口切换效果等 对于我来说就用一个透明度设置的功能就可以了 想
  • ubuntu系统配置i3wm窗口管理器

    我的简书 xff1a https www jianshu com p 81917864271e ubuntu系统配置i3wm窗口管理器 文章目录 ubuntu系统配置i3wm窗口管理器前言i3wm的安装i3wm的配置i3wm快捷键配置介绍i
  • windows 10卸载(注销)WSL,注销(卸载)当前安装的Linux的Windows子系统

    虽然 Linux 发行版可以通过 Microsoft Store 安装 xff0c 但不能通过 Microsoft Store 卸载 不想玩了 xff0c 或者玩腻了就考虑去卸载 xff0c 给电脑节省点空间 1 查看当前环境安装的wsl
  • 获取Chrome浏览器的Cookie

    1 通过查看http请求里header信息 xff0c 查看cookie 2 通过查看浏览器 Chrome 的cookie文件 2 1 进入浏览器设置 2 2 点击隐私设置 gt 内容设置 3 通过查看本地cookies文件 osx上 xf
  • PLSQL 登录时弹出(没有登录)空白提示框

    在登录的时候莫名出现了plsql登录时弹出 没有登录 的空白提示框 在网上找了很多方法之后都不行 然后发现plsql的 oracle主目录名莫名的成了空 然后直接重新把它的目录设置上 重启plsql 就能成功登录了 进入PLSQL gt 工
  • STM32之按键点亮LED灯(中断法)

    目录 1 操作思路 2 用CubeMX工具生成的代码 main的主函数 3 GPIO代码 gpio c 4 编写中断服务函数 5 用外部中断共用入口函数 xff0c 来调用外部中断处理回调函数 6 编写外部中断处理回调函数 xff08 在这
  • 进程间通信之——信号量(一)(system V)

    system v信号量又被称为system v信号量集 它的本质就是一个计数器 xff0c 用来为多个进程共享的数据结构提供受控访问 信号量支持的操作有 xff1a 使用最广泛的信号量为二元信号量 xff0c 它控制单个资源 xff0c 对