Skip to content

Latest commit

 

History

History
138 lines (89 loc) · 5.83 KB

20171109.md

File metadata and controls

138 lines (89 loc) · 5.83 KB

信号量

最近在具体的工程中,在Solaris系统上遇到了信号量设置不当,导致平台通信服务支持的进程数不足的问题。本文主要对信号量一些相关知识进行择要总结,以备忘。

信号量的基本概念

信号量(Semaphore)是E.W.Dijkstra在1965年提出的一种解决进程间通信的方法,它使用一个整型变量来累积唤醒次数,以供以后使用,这个新型的变量称作信号量。一个信号量的值可以为0,表示没有积累下来的唤醒操作;后者为正值,表示有一个或多个被积累下来的唤醒操作。

信号量具备两种操作,之前称为P(wait())和V(signal())。

对一个信号量执行P操作时检查其值是否大于0。若是则将其减去1(即用掉一个保存的唤醒信号)并继续。若值为0,则P操作被阻塞,进程将睡眠。P操作是一个原子操作,保证在操作完成或阻塞之前别的进程均不允许访问该信号量。

V操作递增信号量的值。如果一个或者多个进程在该信号量上睡眠,无法完成先前的P操作,则由系统选择其中一个并允许其完成它的P操作。递增信号量的值和唤醒一个进程同样也是不可分割的。不会有进程因执行V操作而阻塞。

如果信号量只有二进制的0或1,称为二进制信号量。在Linux上,二进制信号量还有一个更广为人知的名字,互斥锁(mutex)。

信号量的参数设置

Linux信号量内核参数

在Linux操作系统中,信号量的内核限制参数通常在/etc/sysctl.conf配置。

kernel.sem=512 32000 100 256

以上的四个参数分别是SEMMSL,SEMMNS,SEMOPM和SEMMNI。这四个参数可以动态修改,而无需重启操作系统。

SEMMSL是每个信号量组内的信号量的最大值。

SEMMNS是整个系统的信号量的最大值。

SEMOPM是每个semop系统调用的操作最大值。

SEMMNI是信号量组的最大值。

我们可以通过ipcs -l命令来显示系统信号量的限制的具体值。

# ipcs -l

------ Semaphore Limits --------
max number of arrays = 256
max semaphores per array = 512
max semaphores system wide = 32000
max ops per semop call = 100
semaphore max value = 32767

Solaris信号量内核参数

在Solaris操作系统中,信号量的内核限制参数在/etc/system中配置。

set semsys:seminfo_semmni=100
set semsys:seminfo_semmsl=256
set semsys:seminfo_semmns=1024
set semsys:seminfo_semopm=100
set semsys:seminfo_semvmx=32767

其中参数的含义和Linux系统基本一致。

这里需要特别提到一个参数,这个参数从Solaris 10开始已经被取消了。但是在一些使用之前Solaris系统的工程中,需要格外注意。引子中提到的问题也与这个参数有关。这个参数就是SEMMNU。

set semsys:seminfo_semmnu = 2048       (removed in Solaris 10 and 11)

SEMMNU参数的含义是整个系统的信号量撤销结构的最大值,通常会将其设置的大小和SEMMNS一致。有这样一个参考公式:

SEMMNS = SEMMNU = (SEMMIN * SEMMSL)

而在Sloaris 8上的SEMMNU默认值30,在使用信号量作为进程间通信基础的场景中,这个设置值太低了。

信号量操作

信号量作为IPC的方式之一,通常使用IPC的操作命令 ipcsipcrm 对信号量进行查看和操作。

IPCS

ipcs 用于输出IPC相关内容的信息,可以使用 -s 参数来查看系统的信号量信息。

# ipcs -s 
------ Semaphore Arrays --------
key        semid      owner      perms      nsems     
0x4e00645c 32769      test      666        1         
0x2b6d5d5e 65538      test      666        1         
0xd631c667 98307      test      666        1         
0xc5b35482 131076     test      666        1         
0x71b6a0a7 163845     test      666        256       
0x4073f280 196614     test      666        1         
0xf4e14d7c 229383     test      666        1         
0xa6da2602 262152     test      666        1         
0x387e3d95 491532     test      644        3         
0xc8ff5d03 524301     test      644        3         
0x3324c83c 557070     test      644        3         
0xe2a5046d 589839     test      644        3         
0x79e72ebd 622608     test      644        3         
0x880ddd3a 655377     test      644        3         
0x37cf505a 688146     test      644        3         
0xd70924a5 720915     test      644        3         
0x8be73547 753684     test      644        3  

IPCRM

ipcrm 用于删除IPC相关的共享资源(如消息队列、信号量或共享内存),可以通过 -s-S 参数来操作信号量。

# ipcrm -s semid
# ipcrm -S semkey

基于信号量的程序设计

待补充

参考资料

  1. 操作系统设计与实现 上册

  2. 维基百科 - 信号量

  3. Setting Semaphore Parameters - Red Hat Custom Portal

  4. 在 Solaris 上配置共享内存和信号量

  5. Perpare Solaris systems for installation

  6. Linux - Kernel Semaphore parameters

  7. ipcrm

  8. ipcs