【Linux】System V 信号量

简介: 【Linux】System V 信号量

一、信号量的概念理论渗透

1.1 基本概念

  • 共享资源:多个执行流,可以看到的一份资源
  • 临界资源:被保护起来的资源 —— 保护的方式:同步和互斥
  • 互斥:任何时候只能有一个进程在访问共享资源
  • 资源,一定要被程序员进行访问的,我们使用代码进行访问, 代码 = 访问共享资源的代码(临界区) + 不访问共享资源的代码(非临界区)
  • 所谓的对共享资源进行保护——临界资源——本质上就是对访问共享资源的代码的保护

1.2 什么是同步和互斥

  • 由于各进程要求共享资源,而且有些资源需要互斥使用,因此各进程间竞争使用这些资源,进程的这种关系为进程的互斥
  • 系统中某些资源一次只允许一个进程使用,称这样的资源为临界资源或互斥资源。
  • 在进程中涉及到互斥资源的程序段叫临界区

1.3 特性方面

      IPC资源必须删除,否则不会自动消除,除非重启,所以System V IPC资源的生命周期随内核

二、如何理解信号量的理论

      信号量(信号灯):用于保护共享资源(临界资源)

      我们来举个例子:电影院买票,我们需要进行买票。我们在之前的共享内存是一个整体使用的,但是在电影院中,会有很多的座位供我们挑选。信号量本质上是一个计数器,当我们购买电影票时,我们需要进行电影票的预定,申请信号量的本质就是对公共资源的一种预定机制。

      信号量分为二元信号量和多元信号量,在二元信号量中,信号量的个数为1(相当于将临界资源看成一整块),二元信号量本质解决了临界资源的互斥问题,以下面的伪代码进行解释:

while (1)
{
    if(sem == 1)
         sum--;
    else 
      // 挂起
  // 写入共享内存
     sem++;
}

      根据以上代码,当进程A申请访问共享内存资源时,如果此时sem为1(sem代表当前信号量个数),则进程A申请资源成功,此时需要将sem减减,然后进程A就可以对共享内存进行一系列操作,但是在进程A在访问共享内存时,若是进程B申请访问该共享内存资源,此时sem就为0了,那么这时进程B会被挂起,直到进程A访问共享内存结束后将sem加加,此时才会将进程B唤起,然后进程B再对该共享内存进行访问操作。

      在这种情况下,无论什么时候都只会有一个进程在对同一份共享内存进行访问操作,也就解决了临界资源的互斥问题。

      实际上,代码中计数器sem减减的操作就叫做P操作,而计数器加加的操作就叫做V操作,P操作就是申请信号量,而V操作就是释放信号量。

                         

三、信号量的操作

3.1 信号量的函数

3.1.1 semget函数

函数的原型:

函数的功能:

      创建一个新的信号量或获取一个已经存在的信号量的键值。

函数的参数:

  • key:为整型值,用户可以自己设定。有两种情况:键值是IPC_PRIVATE,该值通常为0,意思就是创建一个仅能被进程进程给我的信号量。键值不是IPC_PRIVATE,我们可以指定键值,例如1234;也可以一个ftok()函数来取得一个唯一的键值。
  • nsems:表示初始化信号量的个数。比如我们要创建一个信号量,则该值为1.,创建2个就是2。
  • semflg:信号量的创建方式或权限。有IPC_CREAT,IPC_EXCL。IPC_CREAT如果信号量不存在,则创建一个信号量,否则获取。IPC_EXCL只有信号量不存在的时候,新的信号量才建立,否则就产生错误。

函数的返回值:

      成功返回信号量的标识码ID。失败返回-1

3.1.2 semctl函数

函数的原型:

函数的功能:

      控制信号量的函数,在这个函数中我们可以删除信号量或初始化信号量。

函数的参数:

  • semid:信号量的标志码(ID),也就是semget()函数的返回值
  • semnum:操作信号在信号集中的编号。从0开始
  • cmd:表示要进行的操作

cmd参数可以使用的命令:

  • IPC_STAT读取一个信号量集的数据结构semid_ds,并将其存储在semun中的buf参数中。
  • IPC_SET设置信号量集的数据结构semid_ds中的元素ipc_perm,其值取自semun中的buf参数。
  • IPC_RMID将信号量集从内存中删除。
  • GETALL用于读取信号量集中的所有信号量的值。
  • GETNCNT返回正在等待资源的进程数目。
  • GETPID返回最后一个执行semop操作的进程的PID。
  • GETVAL返回信号量集中的一个单个的信号量的值。
  • GETZCNT返回这在等待完全空闲的资源的进程数目。
  • SETALL设置信号量集中的所有的信号量的值。
  • SETVAL设置信号量集中的一个单独的信号量的值。

函数的返回值:

      成功返回0,失败返回-1        

3.1.3 semop函数

函数的原型:

函数的功能:

      用户改变信号量的值。也就是使用资源还是释放资源使用权

函数的参数:

  • shmid:信号量的标识码。也就是semget()的返回值。
  • sops是一个指向结构体数组的指针。
struct   sembuf{
 
     unsigned short  sem_num;//第几个信号量,第一个信号量为0;
 
     short  sem_op;//对该信号量的操作。
 
     short _semflg;
 
};
  • nsops:操作结构的数量,恒大于或等于1。

函数的返回值:

      成功返回0,失败返回-1

四、信号量的指令

// 查看系统中的信号量
ipcs -s
// 删除系统中的信号量
ipcrm -s shmid

五、操作系统如何把共享内存、消息队列、信号量管理起来

      通过对system V系列进程间通信的学习,可以发现共享内存、消息队列以及信号量,虽然它们内部的属性差别很大,但是维护它们的数据结构的第一个成员确实一样的,都是ipc_perm类型的成员变量。

      这样设计的好处就是,在操作系统内可以定义一个struct ipc_perm类型的数组,此时每当我们申请一个IPC资源,就在该数组当中开辟一个这样的结构。

相关文章
|
3月前
|
Docker 容器
14 response from daemon: open \\.\pipe\docker_engine_linux: The system cannot find the file speci
14 response from daemon: open \\.\pipe\docker_engine_linux: The system cannot find the file speci
40 1
|
4月前
|
消息中间件 Linux 开发者
Linux进程间通信秘籍:管道、消息队列、信号量,一文让你彻底解锁!
【8月更文挑战第25天】本文概述了Linux系统中常用的五种进程间通信(IPC)模式:管道、消息队列、信号量、共享内存与套接字。通过示例代码展示了每种模式的应用场景。了解这些IPC机制及其特点有助于开发者根据具体需求选择合适的通信方式,促进多进程间的高效协作。
176 3
|
3月前
|
Linux
linux内核 —— 读写信号量实验
linux内核 —— 读写信号量实验
|
4月前
|
开发者 API Windows
从怀旧到革新:看WinForms如何在保持向后兼容性的前提下,借助.NET新平台的力量实现自我进化与应用现代化,让经典桌面应用焕发第二春——我们的WinForms应用转型之路深度剖析
【8月更文挑战第31天】在Windows桌面应用开发中,Windows Forms(WinForms)依然是许多开发者的首选。尽管.NET Framework已演进至.NET 5 及更高版本,WinForms 仍作为核心组件保留,支持现有代码库的同时引入新特性。开发者可将项目迁移至.NET Core,享受性能提升和跨平台能力。迁移时需注意API变更,确保应用平稳过渡。通过自定义样式或第三方控件库,还可增强视觉效果。结合.NET新功能,WinForms 应用不仅能延续既有投资,还能焕发新生。 示例代码展示了如何在.NET Core中创建包含按钮和标签的基本窗口,实现简单的用户交互。
72 0
|
4月前
|
关系型数据库 Linux 数据库
linux设置信号量系统参数
linux设置信号量系统参数
|
5月前
|
Linux
【Linux】生产者消费者模型——环形队列RingQueue(信号量)
【Linux】生产者消费者模型——环形队列RingQueue(信号量)
49 0
|
5月前
|
消息中间件 Linux
【Linux】进程间通信——system V(共享内存 | 消息队列 | 信号量)(下)
【Linux】进程间通信——system V(共享内存 | 消息队列 | 信号量)(下)
74 0
|
5月前
|
消息中间件 存储 Linux
【Linux】进程间通信——system V(共享内存 | 消息队列 | 信号量)(上)
【Linux】进程间通信——system V(共享内存 | 消息队列 | 信号量)(上)
78 0
|
6月前
|
消息中间件 Linux
【Linux】System V 消息队列(不重要)
【Linux】System V 消息队列(不重要)
|
6月前
|
消息中间件 算法 Unix
【Linux】System V 共享内存
【Linux】System V 共享内存