二.System V信号量和Posix信号量区别

信号量有两种实现:传统的System V信号量和新的POSIX信号量。它们所提供的函数很容易被区分:对于所有System V信号量函数,在它们的名字里面没有下划线。例如,应该是semget()而不是sem_get()。然而,所有的的POSIX信号量函数都有一个下划线。下面列出了它们提供的所有函数清单:

Systm V POSIX
semctl() sem_getvalue()
semget() sem_post()
semop() sem_timedwait()
  sem_trywait()
  sem_wait()
   
  sem_destroy()
  sem_init()
   
  sem_close()
  sem_open()
  sem_unlink()

另外一个区别是,对于POSIX信号量,你可以有命名的信号量,例如,信号量有一个文件

关联它们,

对于最后三个函数,被用来创建,关闭和删除这样一个命名的信号量。

而sem_init()和sem_destroy()仅仅供非命名信号量使用。

他们是有关信号量的两组程序设计接口函数。POSIX信号量来源于POSIX技术规范的实时

扩展方案(POSIX Realtime Extension),常用于线程;system v信号量,常用于进程的同步。

这两者非常相近,但它们使用的函数调用各不相同。前一种的头文件为semaphore.h,函数

调用为sem_init(),sem_wait(),sem_post(),sem_destory()等等。后一种头文件为<sys/sem.h>,

函数调用为semctl(),semget(),semop()等函数。

---------------------------------------------------------我是分割线--------------------------------------------------------

信号量函数由semget、semop、semctl三个函数组成。下面的表格列出了这三个函数的函数原型及具体说明。

1.   semget函数原型

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

所需头文件

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

函数说明

得到一个信号量集标识符或创建一个信号量集对象并返回信号量集标识符

函数原型

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

函数传入值

key

0(IPC_PRIVATE):会建立新信号量集对象

大于0的32位整数:视参数semflg来确定操作,通常要求此值来源于ftok返回的IPC键值

nsems

创建信号量集中信号量的个数,该参数只在创建信号量集时有效

msgflg

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

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

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

函数返回值

成功:返回信号量集的标识符

出错:-1,错误原因存于error中

附加说明

上述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。

2.   semop函数原型

semop(完成对信号量的P操作或V操作)

所需头文件

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

函数说明

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

函数原型

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

函数传入值

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,只完成对一个信号量的操作

函数返回值

成功:返回信号量集的标识符

出错:-1,错误原因存于error中

错误代码

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

EACCESS:权限不够

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

EFAULT:sops指向的地址无效

EIDRM:信号量集已经删除

EINTR:当睡眠时接收到其他信号

EINVAL:信号量集不存在,或者semid无效

ENOMEM:使用了SEM_UNDO,但无足够的内存创建所需的数据结构

ERANGE:信号量值超出范围

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标志,就可以避免因为进程异常退出而造成的死锁。

3.   semctl函数原型

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

所需头文件

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

函数说明

得到一个信号量集标识符或创建一个信号量集对象并返回信号量集标识符

函数原型

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

函数传入值

semid

信号量集标识符

semnum

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

cmd

见下文表15-4

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;

函数返回值

成功:大于或等于0,具体说明请参照表15-4

出错:-1,错误原因存于error中

附加说明

semid_ds结构见上文信号量集内核结构定义

错误代码

EACCESS:权限不够

EFAULT:arg指向的地址无效

EIDRM:信号量集已经删除

EINVAL:信号量集不存在,或者semid无效

EPERM:进程有效用户没有cmd的权限

ERANGE:信号量值超出范围

表15-4 semctl函数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成员的值设置信号量集合中单个信号量的值

信号量函数(semget、semop、semctl)相关推荐

  1. 信号量函数 semget() semop() semctl()

    semget()      可以使用系统调用semget() 创建一个新的信号量集,或者存取一个已经存在的信号量集 : 系统调用:semget(); 原型:intsemget(key_t key,in ...

  2. SystemV 信号量(一) —— SystemV信号量的相关操作函数(semget / semop /semctl)

    SystemV IPC 方案的相关内容都是通过 "房间密码"来创建房间,获取到房间的ID,后面其他进程也可以根据这个房间密码来拿到同一个房间的ID.这是理解下面这些操作函数的关键. ...

  3. C语言sem Take函数,信号量函数sem.c

    信号量函数sem.c 来源:华强电子网 作者:华仔 浏览:148 时间:2016-08-10 14:18 标签: 摘要: ;;; MantisOS中下信号量函数sem.c,主要调用了Linux底层的A ...

  4. 信号量 Linux函数 semget();semctl();semop();

    Linux进程通信之信号量 信号量(semaphore)是变量,是一种特殊的变量.它紧取正值.对信息号量的操作只有2中: 等待(wait)和发送信号(signal). 信号量比较难理解.下面我们一个个 ...

  5. 系统编程04-消息队列(ftok、msgget、msgsnd、msgrcv、msgctl、shmget、shmat、shmdt、shmctl、semget、semctl、semop)

    目录 一.linuxIPC对象 (Inter Process Communicate) 1.什么是IPC对象 1)想要操作文件(设备文件/dev): 2)想要操作消息队列: 2.查看系统中所有的IPC ...

  6. 十六:CreateSemaphore创建信号量,ReleaseSemaphore增加信号量 函数

    在开发软件的过程中,多线程的程序往往需要实现相互通讯,比如几个线程添加一个消息到队列里,而另一个线程在睡眠时,就需要唤醒那个线程来处理事情.在这其中,就需要使用到信号量来进行同步.CreateSema ...

  7. Linux 3.进程间通信(shmget shmat shmdt shmctl 共享内存、signal signaction sigqueue 信号、semget semctl semop 信号量)

    Linux 3.进程间通信(IPC) 共享内存 共享内存的接口指令 shmget 创建获取获取共享内存 shmat 映射:连接共享内存到当前进程的地址空间 shmdt 断开与共享内存的连接 shmct ...

  8. 专题 13 IPC之信号量

    1.概述 信号量是一种计数器,用来控制对多个进程共享的资源所进行的访问.它们常被用做一个锁机制. 2.相关数据结构与函数 信号量数据结构: structsemun { intval;//当执行SETV ...

  9. linux系统调用函数---12

    Linux应用编程学习笔记                                 周学伟 一.系统调用文件编程   1.文件打开函数 /*************************** ...

  10. linux 编程函数原型与用法

    函数原型以及部分实例应用 --------------------------------------------------------------------------------------- ...

最新文章

  1. cygwin用命令安装软件_软件安装、命令行、Github
  2. 天翼云从业认证课后习题(3.2天翼云存储产品和3.4云数据库)
  3. MySQL数据类型:UNSIGNED注意事项
  4. 【深度学习】深度学习在视觉搜索和匹配中的应用
  5. “有一个产品经理的女朋友是什么体验?”
  6. LeetCode 684. Redundant Connection
  7. micropython web ws2812_MicroPython实例之TPYBoard v102炫彩跑马灯WS2812B
  8. 推荐一个比FiddlerCore好用的HTTP(S)代理服务器
  9. Redis应用学习——Redis Cluster故障转移
  10. 转 Ubuntu16.04+QT4.8.7开发环境搭建
  11. Gmail priority inbox帮助你减少工作量
  12. html滑动门原理,HTML+CSS:雪碧图和滑动门制作
  13. 【算力网络白皮书学习】
  14. Mac环境下安装、配置liteide
  15. icem合并面网格_ICEM CFD中合并多个网格
  16. 机房巨佬的随机名称生成器
  17. 5G无线接入网架构及关键技术
  18. 简易四六级成绩管理系统
  19. Kafaka的消息消费方式
  20. 【毕业设计】基于大数据的销量数据预测 -python销量预测 大数据 可视化

热门文章

  1. 1203.1——条件语句 之 if语句
  2. 命名空间“System.Web”中不存在类型或命名空间名称“HttpUtility”。是否缺少程序集引用?...
  3. 使用DirectPlay进行网络互联(1)
  4. xgboost算法_xgboost算法学习心得
  5. panel items 添加指定位置_通过gitlab-ci自动添加prometheus业务监控
  6. k8s api文档 调用heapster metrics
  7. 爬取猎聘大数据岗位相关信息--Python
  8. linux 添加链接与删除链接(ln命令的用法)
  9. 如何开发一款高大上的android应用的必备知识
  10. Centos7安装Docker-1.9.1