【Linux】进程间通信(3)system V信号量

目录

[一 system V信号量](#一 system V信号量)

[1 并发编程 补充概念](#1 并发编程 补充概念)

[2 信号量是什么](#2 信号量是什么)

[3 为什么要有信号量](#3 为什么要有信号量)

[4 怎么办?](#4 怎么办?)

[二 内核时如何管理IPC资源的](#二 内核时如何管理IPC资源的)

​编辑


一 system V信号量

共享内存本质是没有任何保护机制的,所以我们引入一种新的计数--->system V 信号量(用来保护共享内存)

1 并发编程 补充概念

当不同进程看到同一份共享资源时,如果不做任何保护,就会出现并发访问错误(比如数据混乱、结果不一致)---->解决问题提出新方案:信号量和锁

多个执行流(进程)能够看到的同一份公共资源:共享资源
被保护起来的共享资源叫做临界资源(管道就是典型的临界资源)

保护的方式常见:互斥与同步

任何时刻,只允许一个执行流访问资源,叫做互斥
多个执行流访问临界资源时,具有一定的顺序性,叫做同步

系统中某些资源一次只允许一个进程使用,称这样的资源为临界资源或互斥资源

在进程中涉及到互斥资源的程序段叫临界区
你写的代码 = 访问临界资源的代码(临界区) + 不访问临界资源的代码(非临界区)

所谓对共享资源进行保护,本质是对访问共享资源的代码进行保护

临界资源的本质
互斥 + 同步 + 共享资源 = 临界资源。

也就是说,共享资源只有在需要被互斥 / 同步访问时,才会成为临界资源
临界区的意义

程序员通过代码访问共享资源,因此:

你的代码 = 临界区(访问共享资源) + 非临界区(不访问共享资源)。

保护共享资源的关键,就是保护临界区的执行过程

举例

父子进程同时调用 printf 输出内容到 stdout:

stdout 是共享资源,父子进程的 printf 代码段属于临界区。如果没有互斥保护,输出内容会出现混乱、交错,导致结果错误。

有的代码会访问共同资源-->在临界区访问--->临界区被保护起来,访问公共资源的代码

有的代码不会访问公共资源--->在非临界区

保护,就是再进入临界区之前加锁

2 信号量是什么

信号量和信号完全没有关系,有些教材里面也把信号量叫做信号灯

信号量是用来实现同步和互斥的一种技术。

应用场景:公共资源:整体访问(ATM机器)或局部使用(电影院座位)

信号量本质:是一个计数器,用来衡量临界资源,资源数量的计数器

理解:电影院有很多座位,是被所有人共享的,但是很少有人因为座位争执,是因为保证了资源可控,每个人都有份;当我们想看电影的时候,要先申请资源,也就是座位,那这个座位真正属于的时候是什么时候?当你买完票并坐在你的座位上的时候,就开始访问资源。注意:当你买到票时,你就必有座位;即使你没有去,别人也不能占你的座位

买票的本质:对共享资源的一种预定机制

总票数是有限制的,是一个计数器;电影院就相当于内存块

每一个进程进入公共资源或临界区,必须先买票-->申请信号量:本质是对;临界资源进行预定

信号量计数器,做减减操作,叫做p操作,计数器减到0,就不会访问临界区

信号量计数器,做加加操作(离开电影院),叫做v操作

信号量的本质作用:对临界资源的一种预定资源

代码角度:

cs 复制代码
// 信号量计数器
int count = 40;

// P操作:申请信号量
void P() {
    if (count > 0) {
        count--;
    } else {
        // 当前进程阻塞等待
    }
}

// V操作:释放信号量
void V() {
    count++;
}

信号量就是一段代码和属性的集合

细节:

  1. 跨进程共享信号量属于 IPC(进程间通信)资源,目的是让不同进程能够访问同一个信号量,从而实现跨进程的同步与互斥。

  2. 自身安全(原子性) 信号量本身也是共享资源,因此 P、V 操作必须设计为原子操作,确保操作过程不会被打断,避免数据竞争导致信号量状态出错。

  3. 统一遵守的代码规范所有进程访问共享资源(如共享内存)前,都必须先执行 P 操作申请信号量,不允许任何进程绕过信号量直接访问资源,否则保护机制会失效。

  4. 保护逻辑的本质 信号量的保护逻辑,是通过保护访问共享资源的临界区代码,间接实现对临界资源的保护。

  5. 资源分配由程序员维护信号量只负责控制访问权限,不负责划分共享资源的使用范围;进程该访问共享资源的哪一部分,需要由程序员自行设计和管理。

原子的:要么做完,要么不做。绝不能被打断。

为什么重要:信号量(P/V 操作)如果不是原子的,多个进程同时修改计数器,会导致计数错乱,从而让共享资源的保护彻底失败。

如果电影院里只有一个资源,那它就是互斥的,因为只有一份资源,本质也是信号量

3 为什么要有信号量

因为有问题,会发生并发访问;信号量就是为了访问共享资源产生的并发读写问题

4 怎么办?

我们要用到信号量集--->是一个数组 int counter[n],可管理多种不同资源

,semget 是 System V 信号量 的核心系统调用,用来创建或获取一个信号量集(semaphore set)的标识符

bash 复制代码
NAME
       semget - get a System V semaphore set identifier

LIBRARY
       Standard C library (libc, -lc)

SYNOPSIS
       #include <sys/sem.h>

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

参数解释:

参数名 作用
key_t key 信号量集的唯一标识,由 ftok() 生成,用来让不同进程找到同一个信号量集
int nsems 信号量集中包含的信号量个数(创建时指定,获取时也必须和创建时一致)
int semflg 创建 / 获取标志位,和 shmget 用法几乎一致: • IPC_CREAT:不存在则创建,存在则获取 • `IPC_CREAT IPC_EXCL:不存在则创建,存在则报错(确保新建)<br>• 额外加上权限(如 0666`)

注意:开辟空间和初始化的工作是分开的

int semstl:控制信号量

cpp 复制代码
int semctl(int semid, int semnum, int cmd, ...);

union semun:对信号量进行初始化

struct semid_ds:获取信号量集合


二 内核时如何管理IPC资源的

操作系统是统一管理所有的IPC资源的!

IPC资源包括有:共享内存,消息队列,信号量 ;对应的结构体中都有 struct ipc_perm(其中最重要的元素是key)

柔性数组:

cpp 复制代码
struct data {
    int size;
    char buffer[0]; // 柔性数组/零长度数组
};

buffer不占用结构体本身的空间,仅作为一个占位符,指向结构体末尾之后的内存区域

C语言结论:结构体变量的地址,和结构体第一个成员的地址,在数字层面上是相等的

struct ipc_idary 是 Linux 内核 中专门用于批量获取 IPC(进程间通信)对象标识符的内核数据结构

struct ipc_idary里包含一个指针数组,表面上数组的每个元素,都是struct ipc_perm;但实际上,由上面的C语言结论得知,我们知道每个元素实际上是共享内存,消息队列,信号量的结构体--->也就是子类结构体

我们观察发现,共享内存,消息队列,信号量的结构体开头都包含struct kern_ipc_perm

Linux 内核利用 C 语言结构体嵌入特性,将公共权限结构体 kern_ipc_perm 作为所有 IPC 对象结构体的首个成员,以此实现统一管理、权限复用和类型安全转换,模拟面向对象的公共基类继承效果

那么struct ipc_idary不就是基类结构体

这个指针数组,是由父类结构体,指向子类对象

这不就是继承(基类结构体放在子类结构体的开头处)和多态嘛!

返回的时候,xxxid也是一个数组下标、假设已知的指针数组的下标为p,那么强转成对应的结构体类型 (struct serm_array*)p-> 就能访问该结构体的内容

但是怎么找到struct ipc_ids这个入口?你怎么知道指向的内容是什么?
在内核中存在三个静态全局变量:msg_ids,sem_ids,shm_ids,有三张表,分别管理自己的IPC资源

内核定义了三个全局变量作为系统 IPC 资源的总入口。

msg_ids:管理消息队列的全局 descriptor。

sem_ids:管理信号量集的全局 descriptor。

shm_ids:管理共享内存的全局 descriptor。

作用:它们是系统启动时初始化的 "总指挥部",告诉内核去哪里找这三类资源的 ID 数组

相关推荐
峥无2 小时前
Linux 调试效率革命:CGDB
linux·运维·服务器
骥龙2 小时前
第九篇:安全审计与运维——自动化防线建设
运维·安全·自动化
莫回首�8 小时前
ubuntu 20.04 多网卡配置,遇到问题总结
linux·网络·ubuntu
网络安全许木8 小时前
自学渗透测试第11天(Linux压缩解压与磁盘管理)
linux·网络安全·渗透测试
问简10 小时前
虚拟化对比
服务器
航Hang*10 小时前
Windows Server 配置与管理——第3章:文件系统管理
运维·服务器·windows·vmware
lifewange10 小时前
Linux ps 进程查看命令详解
linux·运维·服务器
功德+n11 小时前
Linux下安装与配置Docker完整详细步骤
linux·运维·服务器·开发语言·docker·centos