信号量是一种用于提供不同进程间或一个给定进程的不同线程间同步手段的原语。有三种类型:Posix有名信号量,使用Posix IPC名字标识。Posix基于内存的信号量,存放在共享内存区中;System V信号量。在内核中维护。

这三种信号量都可用于进程间或线程间的同步。

图1 由两个进程使用的一个二值信号量

图2 由两个进程使用的一个Posix有名二值信号量

图3 由一个进程内的两个线程共享的基于内存的信号量

一个进程可以在某个信号量上运行的三种操作:

1、创建一个信号量,这要求调用者指定初始值,对于二值信号量来说。它一般是1,也但是0。

2、等待一个信号量,该操作会測试这个信号量的值。假设小于0,就堵塞。也称为P操作。

3、挂出一个信号量。该操作将信号量的值加1,也称为V操作。

信号量、相互排斥锁和条件变量之间的三个差异:

1、相互排斥锁必须总是给它上锁的线程解锁,信号量的挂出却不必由运行过它的等待操作的同一线程运行。

2、相互排斥锁要么被锁住,要么被解开。

3、既然信号量有一个与之关联的状态。那么信号量挂出操作总是被记住。

然而当向一个条件变量发送信号时。假设没有线程等待在该条件变量上。信号丢失。

Posix提供两类信号量:有名信号量和基于内存的信号量(也称无名信号量)。

使用函数例如以下:

#include <semaphore.h>
/*sem_open创建一个新的有名信号量或打开一个已存在的有名信号量,value參数指定信号量的初始值。返回值是一个指向某个sem_t数据类型的指针,用作其它函数的參数*/
sem_t   *sem_open(const char *name, int oflag, .../*mode_t mode, unsigned int value*/);
int sem_close(sem_t *sem); /*一个进程终止时,内核对其上仍打开着的全部信号量自己主动运行关闭操作*/
int     sem_unlink(const char *name); /*sem_unlink函数:当引用计数大于0时,name就能从文件系统中删除,然而信号量的析构却要等到最后一个sem_close发生时为止*/
int     sem_wait(sem_t *sem); /*測试所指定信号量的值,大于0。将它减1并返回,等于0,调用线程休眠。直到该值大于0,将它减1,函数随后返回*/
int     sem_trywait(sem_t *sem); /*所指定信号量值为0时,不休眠,而是返回一个EAGAIN错误*/
int     sem_post(sem_t *sem);
int     sem_getvalue(sem_t *sem, int  *valp);/* 由valp指向的整数中返回所指定信号量的当前值。

*/

semcreate程序:

#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)int
main(int argc, char **argv)
{int    c, flags;sem_t  *sem;unsigned int value;flags = O_RDWR | O_CREAT;value = 1;while((c = getopt(argc, argv, "ei:")) != -1){switch(c){case 'e':flags |= O_EXCL;case 'i':value = atoi(optarg);break; }   }if(optind != argc - 1){printf("usage:semcreate [-e] [-i initalvalue] <name>\n");  return -1;}sem = sem_open(argv[optind], flags, FILE_MODE, value);sem_close(sem);exit(0);
}

semunlink程序:

#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int
main(int argc, char **argv)
{if(argc != 2){printf("usage:semunlink <name>.\n");    return -1;}sem_unlink(argv[1]);exit(0);
}

semgetvalue程序:

#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int
main(int argc, char **argv)
{sem_t  *sem;int    val;if(argc != 2){printf("usage:semgetvalue <name>.\n");   return -1;}sem = sem_open(argv[1], 0);sem_getvalue(sem, &val);printf("value = %d\n", val);exit(0);
}

semwait程序:

#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int
main(int argc, char **argv)
{sem_t  *sem;int    val;if(argc != 2){printf("usage: semwait <name>"); return -1;}sem = sem_open(argv[1], 0);sem_wait(sem);sem_getvalue(sem, &val);printf("pid %ld has semaphore, value = %d\n", (long)getpid(), val);pause();             /*block until killed*/exit(0);
}

sempost程序:

#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int
main(int argc, char **argv)
{sem_t  *sem;int        val;if(argc != 2){printf("usage:sempost <name>\n");    return -1;}sem = sem_open(argv[1], 0);sem_post(sem);sem_getvalue(sem, &val);printf("value = %d\n", val);exit(0);
}

Posix基于内存的信号量,由应用程序分配信号量的内存空间(也就是分配一个sem_t数据类型的内存空间),然后由系统初始化它们的值。

#include <stmaphore.h>
int sem_init(sem_t *sem, int shared, unsigned int value);  /*出错返回-1*/
int     sem_destroy(sem_t *sem);            <span style="white-space:pre"> </span>/*成功返回0,出错返回-1*/

基于内存的信号量是由sem_init初始化的,sem參数指向应用程序必须分配的sem_t变量。假设shared为0,那么待初始化的信号量是在同一进程的各个线程间共享的,否则该信号量是在进程间共享的。

当不须要使用与有名信号量关联的名字时,可改用基于内存的信号量。

彼此无亲缘关系的不同进程须要使用信号量时,通常使用有名信号量。其名字就是各个进程标识信号量的手段。基于内存信号量至少具有进程持续性,然而它们真正的持续性却取决于存放信号量的内存区的类型。

仅仅要含有某个基于内存信号量的内存区保持有效,该信号量就一直存在。

进程间共享信号量

进程间共享基于内存信号量的规则非常easy:信号量本身必须驻留在由全部希望共享它的进程所共享的内存区中,并且sem_init的第二个參数必须是1。

有名信号量,不同进程总是可以訪问同一个有名信号量。仅仅要它们在调用sem_open时指定同样的名字就可以。

信号量限制

Posix定义了两个信号量限制:

SEM_NSEMS_MAX 一个进程可同一时候打开着的最大信号数

SEM_VALUE_MAX 一个信号量的最大值

这两个常值定义在<unistd.h>头文件里。可在运行时通过sysconf函数获取。

转载于:https://www.cnblogs.com/xfgnongmin/p/10651200.html

Linux环境编程之同步(四):Posix信号量相关推荐

  1. Linux环境编程之同步(三):读写锁

    概述 相互排斥锁把试图进入我们称之为临界区的全部其它线程都堵塞住.该临界区通常涉及对由这些线程共享一个或多个数据的訪问或更新.读写锁在获取读写锁用于读某个数据和获取读写锁用于写直接作差别. 读写锁的分 ...

  2. 林世霖. linux环境编程图文指南,linux环境编程图文指南

    linux环境编程图文指南是一本linux编程环境配置指南,由林世霖.钟锦辉和李建辉三人共同编著.本书定位Linux环境编程入门与提高,全书拥有近400余幅案例图表,200多篇源代码,作者很多编程初入 ...

  3. Linux环境编程05

    目录 Linux环境编程05 一.信号相关基本概念 二.信号捕获 三.进程休眠信号 四.信号集和信号阻塞 五.附带数据信息的信号处理(较难) 六.定时器 Linux环境编程05 声明:本学习笔记为个人 ...

  4. Linux 环境编程 用户层定时器使用二 timer_create的使用

    用户层定时器有两种,一种是timerfd,另一种是timer_create,前者比较新,使用比较方便. Linux环境编程 用户层定时器使用一 timerfd的使用 https://blog.csdn ...

  5. Linux 环境编程 day01 Linux系统介绍、GNU编译工具、静态/共享库、环境变量表

    Linux 环境编程 day01 Linux系统介绍.GNU编译工具.静态/动态库.环境变量表 学习Linux环境编程的原因 UNIX系统介绍 Linux系统介绍 GNU工程 POSIX标准 GNU通 ...

  6. linux环境编程从应用,linux环境编程:从应用到内核

    <UNIX环境高级编程>(简称APUE)几乎是Linux领域程序员人手必备的一本书.但在掌握和理解APUE的内容后,又该如何继续提高自己的技能,如何更深入地理解Linux环境编程及其背后的 ...

  7. Linux环境编程(4)文件操作相关内容补充

    Linux环境编程(4) 文件同步: 1.在写入数据时内存与磁盘之间也有一个缓冲区,这种机制降低了磁盘读写次数,提高了读写的效率. 2.但这种机制带来的后果就是磁盘中的数据与实写入的数据不匹配,系统提 ...

  8. Linux环境编程姜林美,Linux环境编程习题_编程题_答案.pdf

    Linux环境编程习题_编程题_答案 Linux 境编程-人民邮电出版社-姜林美 课后习题(编程题)答案 第三章 1 第五章 4 第六章 9 第七章 19 第八章 22 第九章 35 第十章 38 三 ...

  9. Linux环境编程多线程定时器、延时队列以及分布式定时器的现实与原理分析

    Linux环境编程多线程定时器.延时队列以及分布式定时器的现实与原理分析丨线程池丨中间件丨后端开发丨C/C++linux服务器开发 视频讲解如下,点击观看: Linux环境编程多线程定时器.延时队列以 ...

最新文章

  1. window.postMessage跨文档通信
  2. Python多线程3:queue
  3. android动画文档,Android 动画系统汇总
  4. sql主键可以有多个_干货 | 新手请速戳!30个精选SQL面试问题Qamp;A集锦
  5. 个人工作总结10(冲刺二)
  6. java的tomcat_JAVA程序获取Tomcat的运行状态
  7. 华泰证券python算法工程师_华泰证券高薪诚聘 技术大牛/运维平台架构师
  8. AAE 对抗自编码(一)
  9. php的外文参考文献_php英文文献翻译及参考文献
  10. 企业如何实现在线客服功能?
  11. linux12k8s --> 03二进制安装
  12. 伯克利AI实验室最新发文:公布用于机器人抓取的Dexterity Network (Dex-Net) 2.0数据集...
  13. mysql 投影运算_数据库查询 - 通俗易懂解释:选择、投影、并、差、笛卡尔积、连接 - 小黑电脑...
  14. 记录一个因为使用masonry 布局造成的宽度不准确的问题
  15. 基于Opencv实现连续检测yuv转bmp后的每一帧的sobel算法实现
  16. Windowser Server 2012 开放端口方法
  17. 智能电子秤方案控制板设计开发
  18. 南蛮图腾 (洛谷 P1498)
  19. maven-compiler-plugin和maven-jar-plugin报错飘红
  20. 亚马逊kindle设置_前所未有的阅读能力:使用亚马逊Kindle并没有死树的情况,对四个懒惰年份的分析

热门文章

  1. 用面向对象封装ASP中的cookie操作
  2. MongoDB系列(一):简介及安装
  3. NSLog (Log信息的输出)
  4. RHEL6入门系列之十,常用命令3
  5. ubuntu下安装openfetion
  6. MYSQL 表锁情况查看
  7. RoR开发环境搭建 RAILS install log
  8. Java文件操作:文件夹中搜索文件
  9. Vue 路由router的两种模式
  10. 探讨8.0版本下后台service存活机制及保活