<Linux>(极简关键、省时省力)《Linux操作系统原理分析之Linux 进程管理 7》(11)

本文主要是介绍<Linux>(极简关键、省时省力)《Linux操作系统原理分析之Linux 进程管理 7》(11),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Linux操作系统原理分析之Linux 进程管理 7》(11)

  • 4 Linux 进程管理
    • 4.7 IPC 信号量机制
      • 4.7.1 信号量与信号量集合
        • 1.信号量
        • 2.信号量集合
        • 3.信号量集合的集中
      • 4.7.2 信号量集合的创建和检索
      • 4.7.3 信号量 PV 操作
      • 4.7.4 信号量操作等待队列
        • 1.信号量操作等待队列
        • 2.将信号量操作移出等待队列
      • 4.7.5 信号量控制操作
      • 4.7.6 信号量的程序例
        • 程序例 1:创建一个信号量集合,并对信号量进行 P 操作。
        • 程序例 2:通过信号量控制函数删除信号量集合。

4 Linux 进程管理

4.7 IPC 信号量机制

Linux 的信号量机制有两种:

1 其本身设置的信号量机制

2 引进 UNIX SYSTEM V 的 IPC(Internal Process Communication)中的信号量机制

IPC(Internal Process Communication)中的信号量机制其涉及到的函数和数据结构分别定义在 Linux 源文件的 ipc/sem.c 和 include/linux/sem.h

4.7.1 信号量与信号量集合

IPC 信号量机制更完善、更方便使用。

1.信号量

定义:
系统中每个信号量对应一个信号量结构体 sem,其定义如下:

Struct sem
{
Short semval; /*信号量的值*/
Unshort sempid; /*记录对信号量最后一次实施操作进程的 PID*/
}

PV 操作
(为了解决死锁)IPC 信号量机制引进了信号量集合的概念,可以使用原语一次对多个信号量进行操作。

2.信号量集合

信号量集合:把进程需要访问资源对应的信号量组成一个信号量集合,并可以使用操作原语一次性地对信号量集中的多个信号量进行 PV 操作。
信号量数组:在 IPC 信号量机制中把多个信号量组成一个信号量集合,该集合由信号量结构体 sem组成,称为信号量数组。
信号量集合描述符:系统中的每个信号量集合用一个描述符描述其特征和记载其管理信息。其定义如下:

Struct semid_ds
{
Struct_ipc_perm sem_perm; /*对信号量集合的访问权限*/
Time_t sem_otime; /*最后一次对信号量集进行操作的时间*/
Time_t sem_ctime; /*最后一次修改信号量集的时间*/
Struct sem *sem_base; /*指向信号量数组*/
Struct sem_queue *sem_pending; /*指向等待队列头*/
Struct sem_queue *sem_pending_last;/* 指向等待队列尾*/
Struct sem_undo *undo; /*进程终止时需要使用 sem_undo 结构体中的信息,对信号量集合进行有关操作*/
Unshort sem_nsems; /*信号量集合中信号量的数目*/
}
3.信号量集合的集中

IPC 对系统中的所有信号量集合进行集中管理,把所有的信号量集合描述符组织在一个 semary[]数组中,其定义如下:

Static struct semid_ds *smeary[SEMMNI];

其中 SEMMNI 为数组大小,是系统中可以设置的信号量集合的最大数目,其缺省值为 128,宏定义如下:

#define SEMMNI 128

4.7.2 信号量集合的创建和检索

1.semget()
系统为每个信号量集合设定了一个唯一的标识号 ID,IPC 提供了创建信号量结合和获取信号量集合标识号的系统调用 semget(),其原型定义如下:

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

该系统调用正常则返回值为信号量集合的标识号,出错则返回负数。
Key:要创建或要获取的信号量集合的标志键值,可以用户指定,也可使用符号常量 IPC_PRIVATE 由系统给定。
Nsems:指出要创建的信号量集合中包含的信号量的个数。
Semflgs:操作标志;指定了信号量集合的访问权限和操作模式。其取值或符号常量及意义如下:
0400 允许创建者读
0200 允许创建者写
0040 允许创建者同组用户读
0020 允许创建者同组用户写
0004 允许其它所有的进程读
0002 允许其它所有的进程写
IPC_CREAT(00001000) 创建新的信号量集合
IPC_EXCL(00002000) 检索信号量集合

前六项指定了信号量集合的访问权限,后两项指定了操作模式。访问权限和操作模式可以使用逻 辑与(|)组合在一起表示复合属性。

2.创建信号量集
若操作模式设定为 IPC_CREAT:

则当系统中尚没有建立与 key 对应的信号量集合,则建立这个新的集合,并返回新集合的标 识号;
当系统中已经存在与键值 key 对应的信号量集合,则返回这个集合的标识号;
当不能创建,则返回-1

若操作模式设定为 IPC_CREAT|IPC_EXCL:

与前不同的是,当系统中已经存在与键值 key 对应的信号量集合,则返回错误值-EEXIST。

例:建立一个健值为 KEY,包含 1 个信号量,允许任何进程读写的信号量集合时,调用函数的形式为: id=semget(KEY,1,0666|IPC_CREAT);
3.检索信号量集 检索信号量集
检索一个信号量集合的标识号时,只需将 semflg 中的操作模式设为 IPC_EXCL。若存在,返回集合的标识号,否则,返回-1;

4.7.3 信号量 PV 操作

IPC 中没有对信号量分别设置 P 和 V 操作原语,而是统一由具有原语性质的系统调用 semop()实现的,通常称其为信号量操作函数。其定义如下:

Int semop(int semid,struct sembuf *sops, unsigned nsops);
//Semid:实施 pv 操作的信号量集合的标识号
//Nsops:本次实施操作的信号量的个数
//Sops:指向一个信号量操作数组。因为每次对信号量集合中实施操作的信号量个数不同,不同信号量实施的操作不同,所以必须指明本次操作是对哪些信号量,实施哪些操作。该数组的元素个数就是 Nsops。
Sops 中的每个元素是一个 sembuf 结构体,它由系统定义:
Struct sembuf
{
Ushort sem_num; /*指出信号量在信号量数组中的下标*/
Short sem_op; /*指出操作的种类*/
Short sem_flg; /*指出操作的标志*/
}

说明:

Sem_op 的值决定操作的类型:
1、Sem_op 的值是负数:表示进程请求资源,则实施 P 操作,把 semval 的值减去 sem_op绝对值。
2、Sem_op 的值是正数:表示进程释放资源,则实施 V 操作,把 semval 的值加上 sem_op以上两种情况下,若对信号量集实施操作后,所有信号量的值 semval 均大于等于 0,则函数返回 0,表示进程所需的多个资源都可用,此时进程可以继续运行;否则,只要有一个 semval结果为负数,则表示进程需要的这种资源不可用,进程被阻塞,并将本次操作加入该信号量集合的等待队列。
3、Sem_op 的值为 0。此时若 semval 也是 0,则函数返回,调用 semop 的进程继续执行;若semval 非 0,则进程被阻塞。
4、sem_flg:控制进程的执行。通常取值 0;若指定为 IPC_NOWAIT,则在执行 semop操作时,即使出现需要进程阻塞的情况,也不阻塞,而是继续运行。

4.7.4 信号量操作等待队列

1.信号量操作等待队列

IPC每个信号量集合都有一个等待队列,分别由其描述符中的成员向 sem_pending 和 sem_pending_last 指向其头部和尾部。该等待队列是由 sem_queue 结构体组成的双向循环链表。Sem_queue 结构体定义如下:

Struct sem_queue
{
Struct sem_queue *next; /*指向队列后一个节点*/
Struct sem_queue *prev; /*指向队列前一个节点*/
Struct wait_queue *sleeper; /*指向被阻塞进程*/
Struct sem_undo *undo;
Int pid; /*实施操作的进程的 PID*/
Int status;
Struct semid_ds *sma; /*指出对哪个信号量集合实施操作*/
Struct sembuf *sops; /*指向是进程阻塞的操作数组*/
Int nsops; /*指出操作数组中操作的个数*/
}
2.将信号量操作移出等待队列

若某个进程在执行 semop()时没有阻塞,函数将检查该信号量集的操作等待队列:

1、若无操作等待, 则返回;
2、若有操作等待, 则依次重新执行这些操作:
1)若进程仍需等待,则操作保留在等待队列中;
2)若进程可以继续执行,则通过该 sem_queue 结构体中的 sleeper 在进程等待队列中找到该进程,并将其唤醒;再将该sem_queue 结构体从操作等待队列中删除。

4.7.5 信号量控制操作

IPC 信号量机制提供了可以对信号量集合进行多种控制操作的系统调用 semctl(),它能实现对信号量的初始化、查询、修改、删除等功能。

Int semctl(int semid,int semnum,int cmd,union semun arg);
Semid:指向操作对象,即信号量集合标记号。
Semnum:信号量的索引号,指明信号量在信号量数组中的下标。
Cmd:指定各种不同操作。
Arg:用于传递执行各种控制操作时所需的参数。
union semun 是 IPC 定义 的一个联合体。其定义 :

Union semum
{
Int val;
Struct semid_ds *buf;
Unshort *array;
Struct seminfo *_buf;
Void*_pad;
}

cmd,对应的符号常量和意义所在:

符号常量意义
IPC_STAT读取信号量集合 semid_ds 结构体的内容,并把它写进参数 arg 给出的 semnum 联合体中成员项 buf 指定的 semid_ds 结构中。此时无视参数 Semnum。
IPC_SET修改信号量集合 semid_ds 结构体的成员项 sem_perm 结构中的某些成员项的值;同时sem_ctime 被自动更新。只有信号量集合创建者、同组用户和超级用户可以执行该操作。修改值取自参数 arg给出的 semun 联合体中 buf 指定的 semid_ds 结构体的第一个成员项。
IPC_RMID从内核中删除信号量集合。只有信号量集合创建者和超级用户。在该信号量集合中等该信号量操作的所有进程被唤醒,并得到错误信息 EIDRM。
GETPID获取信号量数组中以参数 semnum 做为索引值指定信号量的 sempid 值。它是对信号量最后一个执行 semop()操作的进程的 PID。
SETVAL设置信号量数组中以参数 semnum 做为索引值指定信号量的值。Arg 的 semun 联合体成员项 val 中给出要设置的值。
GETVAL获取信号量数组中以参数 semnum 做为索引值指定信号量的 semval 值。其值写入 arg 的semun 联合体成员项 val 中。该值也作为函数返回值返回。
SETALL设置信号量集合中所有信号量的值,设置值存放在 Arg 的 semun 联合体成员项 array 中。
GETALL获取信号量集合中所有信号量的值,并存放在 Arg 的 semun 联合体成员项 array 中。
GETNCNT得到等待以 semnum 为索引指出的信号量的值为非 0 的进程的个数。

4.7.6 信号量的程序例

程序例 1:创建一个信号量集合,并对信号量进行 P 操作。
/*mksem.c*/
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
Int main(void{
Int semid; /*信号量集合标识号*/
Int nsems=1; /*信号量集合中信号量的个数*/
Int flags =6/*对信号量集合的访问权限,允许所有进程进行读写*/
Struct sembuf buf;/*信号量操作数组*/
/*创建信号量集*/
Semid = semget(IPC_PRIVATE,nsems,flags);
If(semid<0) /*若返回值为负,则出错*/
{
Printf(“semapher ceate failer! \n”); 
Exit(EXIT_FAILURE)}
Printf(“semapher ceated:%d\n”,semid); 
/*设置操作数组个成员项的值*/
Buf.sem_num=0; /*下标为 0,因为只有一个信号量*/
Buf.sem_op =1; /*信号量加 1 操作*/
Buf.sem_flg=IPC_NOWAIT; /*进程不阻塞*/
If((semop(semid,&buf, nsems)<0/*执行信号量操作*/
{
/*信号量操作失败*/
Printf(“semapher operation failer! \n”); 
Exit(EXIT_FAILURE)}
System(“ipcs –s”); /*执行键盘命令 ipcs –s,显示 IPC 信号量*/
Exit(EXIT_SUCCESS)/*成功退出*/
}

程序运行结果如下:

$./mksem
semapher ceated:520
-----semapher arrays------
Key semid owner perms nsems status
0x00000000 520 wang 666 1
程序例 2:通过信号量控制函数删除信号量集合。
/*sctlsem.c*/
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
Int main(int argc,char *argv[ ]{
Int semid; /*信号量集合标识号*/
If(argc!=2{
Puts(“USAGE:sctl<semaphore id>”);
exit(EXIT_FAILURE)}
Semid=atoi(argv[1]); /*从命令行参数得到信号量集合标识号*/
/*删除信号量集合*/
If((semctl(semid,0IPC_RMID))<0/*调用信号量控制函数*/
{
/*返回负值,失败退出*/
Printf(“semapher control failer! \n”); 
exit(EXIT_FAILURE)}
Else
{
Puts(“semapher removed! ”);
System(“ipcs –s”); /*执行键盘命令 ipcs –s,显示 IPC 信号量*/
}
Exit(EXIT_SUCCESS)/*成功退出*/
}

程序运行时,需要给出所要删除的信号量集合的标识号,程序运行结果如下:

$./ sctlsem.c 520
semapher removed!

这篇关于<Linux>(极简关键、省时省力)《Linux操作系统原理分析之Linux 进程管理 7》(11)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/432143

相关文章

linux-基础知识3

打包和压缩 zip 安装zip软件包 yum -y install zip unzip 压缩打包命令: zip -q -r -d -u 压缩包文件名 目录和文件名列表 -q:不显示命令执行过程-r:递归处理,打包各级子目录和文件-u:把文件增加/替换到压缩包中-d:从压缩包中删除指定的文件 解压:unzip 压缩包名 打包文件 把压缩包从服务器下载到本地 把压缩包上传到服务器(zip

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

hdu4407(容斥原理)

题意:给一串数字1,2,......n,两个操作:1、修改第k个数字,2、查询区间[l,r]中与n互质的数之和。 解题思路:咱一看,像线段树,但是如果用线段树做,那么每个区间一定要记录所有的素因子,这样会超内存。然后我就做不来了。后来看了题解,原来是用容斥原理来做的。还记得这道题目吗?求区间[1,r]中与p互质的数的个数,如果不会的话就先去做那题吧。现在这题是求区间[l,r]中与n互质的数的和

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

软考系统规划与管理师考试证书含金量高吗?

2024年软考系统规划与管理师考试报名时间节点: 报名时间:2024年上半年软考将于3月中旬陆续开始报名 考试时间:上半年5月25日到28日,下半年11月9日到12日 分数线:所有科目成绩均须达到45分以上(包括45分)方可通过考试 成绩查询:可在“中国计算机技术职业资格网”上查询软考成绩 出成绩时间:预计在11月左右 证书领取时间:一般在考试成绩公布后3~4个月,各地领取时间有所不同

安全管理体系化的智慧油站开源了。

AI视频监控平台简介 AI视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒,省去繁琐重复的适配流程,实现芯片、算法、应用的全流程组合,从而大大减少企业级应用约95%的开发成本。用户只需在界面上进行简单的操作,就可以实现全视频的接入及布控。摄像头管理模块用于多种终端设备、智能设备的接入及管理。平台支持包括摄像头等终端感知设备接入,为整个平台提