信号量的基本概念与使用semget,semop

1、信号量的基本概念

信号量是一个计数器,常用于处理进程或线程的同步问题,特别是对临界资源的同步访问。

临界资源可以简单的理解为在某一时刻只能由一个进程或线程进行操作的资源,这里的资源

可以是一段代码、一个变量或某种硬件资源。信号量的值大于或等于0时表示可供并发进程使用的

资源实体数;小于0时代表正在等待使用临界资源的进程数。

注意:这里的信号量跟信号是没有关系的。

与消息队列类似,linux内核也为每个信号量维护了一个semid_ds 数据结构实例,

在文件/usr/include/linux/sem.h中

struct semid_ds {
struct ipc_perm sem_perm; /* permissions .. see ipc.h */
__kernel_time_t sem_otime; /* last semop time */
__kernel_time_t sem_ctime; /* last change time */
struct sem *sem_base; /* ptr to first semaphore in array */
struct sem_queue *sem_pending; /* pending operations to be processed */
struct sem_queue **sem_pending_last; /* last pending operation */
struct sem_undo *undo; /* undo requests on this array */
unsigned short sem_nsems; /* no. of semaphores in array */
};

2、信号量的创建与使用

linux下使用semget创建或打开信号量集,

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

该函数执行成功则返回一个信号量集的标识符,失败返回-1。返回的参数key是由ftok得到的键值;

第二个参数nsems指明要创建的信号量集包含的信号量个数。如果只是打开信号量,把nsems设置为0即可。该参数只在创建信号量集时有效。

第三个参数semflg为操作标识,可取如下值:

0:取信号量集标识符,若不存在则函数会报错

IPC_CREAT:当semflg&IPC_CREAT为真时,如果内核中不存在键值与key相等的信号量集,则新建一个信号量集;如果存在这样的信号量集,返回此信号量集的标识符

IPC_CREAT|IPC_EXCL:如果内核中不存在键值与key相等的信号量集,则新建一个消息队列;如果存在这样的信号量集则报错

上述semflg参数为模式标志参数,使用时需要与IPC对象存取权限(如0600)进行|运算来确定信号量集的存取权限

错误代码:

EACCESS:没有权限

EEXIST:信号量集已经存在,无法创建

EIDRM:信号量集已经删除

ENOENT:信号量集不存在,同时semflg没有设置IPC_CREAT标志

ENOMEM:没有足够的内存创建新的信号量集

ENOSPC:超出限制

如果用semget创建了一个新的信号量集对象时,则semid_ds结构成员变量的值设置如下:

?        sem_otime设置为0。

?        sem_ctime设置为当前时间。

?        msg_qbytes设成系统的限制值。

?        sem_nsems设置为nsems参数的数值。

?        semflg的读写权限写入sem_perm.mode中。

?        sem_perm结构的uid和cuid成员被设置成当前进程的有效用户ID,gid和cuid成员被设置成当前进程的有效组ID。

--------------------------------------------------

3、信号量的操作

信号量的值与相应资源的使用情况有关,当它的值大于0时,表示当前可用资源的数量,当他的值小于0时,其绝对值表示等待

使用这个资源的进程个数。信号量的值仅能由PV操作来改变。

在linux下,pv操作通过调用函数semop实现。该函数定义在头文件sys/sem.h中,原型:

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

对信号量集标识符为semid中的一个或多个信号量进行P操作或V操作

semid:信号量集标识符

sops:指向进行操作的信号量集结构体数组的首地址,此结构的具体说明如下:

struct sembuf {

short semnum; /*信号量集合中的信号量编号,0代表第1个信号量*/

short val;/*若val>0进行V操作信号量值加val,表示进程释放控制的资源 */

/*若val<0进行P操作信号量值减val,若(semval-val)<0(semval为该信号量值),则调用进程阻塞,直到资源可用;若设置IPC_NOWAIT不会睡眠,进程直接返回EAGAIN错误*/

/*若val==0时阻塞等待信号量为0,调用进程进入睡眠状态,直到信号值为0;若设置IPC_NOWAIT,进程不会睡眠,直接返回EAGAIN错误*/

short flag;  /*0 设置信号量的默认操作*/

/*IPC_NOWAIT设置信号量操作不等待*/

/*SEM_UNDO 选项会让内核记录一个与调用进程相关的UNDO记录,如果该进程崩溃,则根据这个进程的UNDO记录自动恢复相应信号量的计数值*/

};

nsops:进行操作信号量的个数,即sops结构变量的个数,需大于或等于1。最常见设置此值等于1,只完成对一个信号量的操作

错误代码:

E2BIG:一次对信号量个数的操作超过了系统限制

EACCESS:权限不够

EAGAIN:使用了IPC_NOWAIT,但操作不能继续进行

EFAULT:sops指向的地址无效

EIDRM:信号量集已经删除

sops为指向sembuf数组,定义所要进行的操作序列。下面是信号量操作举例。

struct sembuf sem_get={0,-1,IPC_NOWAIT}; /*将信号量对象中序号为0的信号量减1*/

struct sembuf sem_get={0,1,IPC_NOWAIT};  /*将信号量对象中序号为0的信号量加1*/

struct sembuf sem_get={0,0,0};           /*进程被阻塞,直到对应的信号量值为0*/

flag一般为0,若flag包含IPC_NOWAIT,则该操作为非阻塞操作。若flag包含SEM_UNDO,则当进程退出的时候会还原该进程的信号量操作,这个标志在某些情况下是很有用的,

比如某进程做了P操作得到资源,但还没来得及做V操作时就异常退出了,此时,其他进程就只能都阻塞在P操作上,于是造成了死锁。若采取SEM_UNDO标志,就可以避免因为进程异常退出而造成的死锁。

4、semctl (得到一个信号量集标识符或创建一个信号量集对象)

int semctl(int semid, int semnum, int cmd, union semun arg)

semid:信号量集标识符

semnum:信号量集数组上的下标,表示某一个信号量

cmd:


命令


解   释


IPC_STAT


从信号量集上检索semid_ds结构,并存到semun联合体参数的成员buf的地址中


IPC_SET


设置一个信号量集合的semid_ds结构中ipc_perm域的值,并从semun的buf中取出值


IPC_RMID


从内核中删除信号量集合


GETALL


从信号量集合中获得所有信号量的值,并把其整数值存到semun联合体成员的一个指针数组中


GETNCNT


返回当前等待资源的进程个数


GETPID


返回最后一个执行系统调用semop()进程的PID


GETVAL


返回信号量集合内单个信号量的值


GETZCNT


返回当前等待100%资源利用的进程个数


SETALL


与GETALL正好相反


SETVAL


用联合体中val成员的值设置信号量集合中单个信号量的值

arg:

union semun {

short val;          /*SETVAL用的值*/

struct semid_ds* buf; /*IPC_STAT、IPC_SET用的semid_ds结构*/

unsigned short* array; /*SETALL、GETALL用的数组值*/

struct seminfo *buf;   /*为控制IPC_INFO提供的缓存*/

} arg;

5、信号量的应用实例:

server创建一个信号量集,并对信号量循环减1,相当于分配资源。

client执行时jian‘cha信号量,如果其值大于0代表有资源可用,继续执行,如果小于等于0代表资源已经分配完毕,进程client推出。

server:

client:

时间: 2024-08-09 10:34:27

信号量的基本概念与使用semget,semop的相关文章

semctl semget semop 函数系列构成的 信号量

a:focus { outline: thin dotted #333; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } a:hover { outline: 0; } a:active { outline: 0; } a:hover { color: #005580; text-decoration: underline; } blockquote small:before { content: '\201

Linux进程间通信 -- 信号量 semget()、semop()、semctl()

这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信 -- 信号.下面就进入信号量的讲解. 一.什么是信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域.临界区域是指执行数据更新的代码需要独占式地执行.而信号量就可以提供这样的一种访问机制,让一个临界区同

semget 信号量创建

Linux进程间通信(六)---信号量通信之semget().semctl().semop()及其用法:http://www.educity.cn/linux/1241661.html 信号量 Linux函数 semget();semctl();semop();:http://blog.csdn.net/ta893115871/article/details/7505560 信号量函数 semget() semop() semctl():http://blog.chinaunix.net/uid

在Linux下信号量的semop操作的sembu结构体中sem_flag的设置值的含义

semop函数主要功能是对信号量进行P/V操作. P操作责把当前进程由运行状态转换为阻塞状态,直到另外一个进程唤醒它.操作为:申请一个空闲资源(把信号量减1),若成功,则退出:若失败,则该进程被阻塞: V操作负责把一个被阻塞的进程唤醒,它有一个参数表,存放着等待被唤醒的进程信息.操作为:释放一个被占用的资源(把信号量加1),如果发现有被阻塞的进程,则选择一个唤醒之. semop函数原型如下: int semop(int semid, struct sembuf  *sops, unsigned

Linux 进程通信之 ——信号和信号量总结

如今最经常使用的进程间通信的方式有:信号,信号量,消息队列,共享内存.       所谓进程通信,就是不同进程之间进行一些"接触",这种接触有简单,也有复杂.机制不同,复杂度也不一样.通信是一个广义上的意义,不仅仅指传递一些massege.他们的用法是基本相同的,所以仅仅要掌握了一种的用法,然后记住其他的用法就能够了. 1. 信号       在我学习的内容中,主要接触了信号来实现同步的机制,据说信号也能够用来做其他的事      情,可是我还不知道做什么.       信号和信号量是

linux进程间的通信(C): 信号量

一.信号量简介 信号量: 用于管理对资源的访问. 荷兰计算机科学家Edsger Dijkstra提出的信号量概念 是在并发编程领域迈出的重要一步. 信号量是一个特殊的变量, 它只取正数值, 并且程序对其访问都是原子操作. 二.信号量的定义 它是一个特殊变量, 只允许对它进行等待(wait)和发送信号(signal)这两种操作, P(信号量变量): 用于等待. V(信号量变量): 用于发送信号. 这两个字母分别源于荷兰语单词 passeren, 传递,      就好像进入临界区域之前的检查点,(

【转载】Linux的进程间通信-信号量

原文:Linux的进程间通信-信号量 Linux的进程间通信-信号量 版权声明: 本文章内容在非商业使用前提下可无需授权任意转载.发布. 转载.发布请务必注明作者和其微博.微信公众号地址,以便读者询问问题和甄误反馈,共同进步. 微博ID:orroz 微信公众号:Linux系统技术 前言 信号量又叫信号灯,也有人把它叫做信号集,本文遵循<UNIX环境高级编程>的叫法,仍称其为信号量.它的英文是semaphores,本意是“旗语”“信号”的意思.由于其叫法中包含“信号”这个关键字,所以容易跟另一个

Linux 信号量互斥编程

所谓信号量,其实就是一个数字.内核给这个数字赋予一定的含义,让它等于不同的值时所表示的意义不同.这样就可以用它来标示某种资源是否正被使用.信号的分类其实挺多的,主要还是二值和计数器.这里讨论二值 现在有个文件,有两个进程要同时访问它.进程A 要往里面写入 "Math class is cancel",进程B 要往里面写入“English test”.正常情况下这两个信息会被完整的写入文件中.但是如果进程A写到"Math class" 就暂停,接着B进程就开始写“En

临界区,互斥量,信号量,事件的区别(线程同步)

(转)临界区,互斥量,信号量,事件的区别(线程同步) (转)临界区,互斥量,信号量,事件的区别(线程同步) . 分类: C++ windows 核心编程 2012-04-10 14:55 3321人阅读 评论(0) 收藏 举报 semaphoremfcnulleventsthreadhttp服务器 四种进程或线程同步互斥的控制方法 1.临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问. 2.互斥量:为协调共同对一个共享资源的单独访问而设计的. 3.信号量:为控制一个