linux POSIX 信号量介绍
信号量
一.什么是信号量
信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)使用。
多线程可以同时运行多个线程函数完成功能,但是对于共享数据如果不加以锁定,随意改变共享数据的值会发生期望之外的结果!
本文主要介绍Linux下的 POSIX信号量:有名信号量和无名信号量
有名信号量,其值保存在文件中, 所以它可以用于线程也可以用于进程间的同步;
无名信号量,其值保存在内存中,故只用于线程的同步,多用共享内存。
POSIX信号量包含一个非负整型变量,并且带有两个原子操作wait 和signal。wait 还可以被称为down、P 或lock,signal 还可以被称为up、V、unlock 或post。在Uinx的API中用的是wait和post。
如果信号量的非负整形变量S大于零,wait就将其减1,如果S 等于0,wait 就将调用线程阻塞。对于post 操作,如果有线程在信号量上阻塞(此时S 等于0),signal就会解除对某个等待线程的阻塞,使其从wait 中返回,如果没有线程阻塞在信号量上,post 就将S加1。
简单来说即:当S大于0时,线程正常运行不会阻塞;当S=0时,线程阻塞直到有post操作将其+1。假设S值设为1,信号量可实现互斥的功能。
信号量的一般操作是 创建-->PV操作-->删除
二. 无名信号量
头文件: <semaphore.h>
int sem_init(sem_t *sem, int pshared,unsigned value);
功能:初始化指定的信号量
返回值:成功 0 ; 错误 错误号。
参数说明:sem:信号量变量名;参数value为信号量的初始值。
参数pshared用于说明信号量的共享范围,如果pshared为0,那么该信号量只能由初始化这个信号量的进程中的线程使用,如果pshared非零,任何可以访问到这个信号量的进程都可以使用这个信号量。
必须保证只调用sem_init()进行初始化一次,对于一个已初始化过的信号量调用sem_init()的行为是未定义的
int sem_destroy(sem_t *sem);
功能:销毁一个指定的信号量
返回值:成功 0 ; 错误 错误号。
参数说明:sem:信号量变量名(sem_init内值)
摧毁一个有线程阻塞在其上的信号量的行为是未定义的。
P操作:
int sem_trywait(sem_t *sem);
int sem_wait(sem_t *sem);
int sem_timedwait(sem_t * sem, const struct timespec time);
减1信号量的值。信号量值为0时,sem_wait会阻塞,直到成功使信号量减1或者被信号中断时才返回;
sem_trywait为非阻塞版本,当信号量为0时,该函数返回-1并且将errno置为EAGAIN
sem_timedwait带有超时功能,超时到期并且信号量计数没能减1,sem_timedwait将返回-1且将errno设置为ETIMEDOUT。(毕竟一直阻塞也不是办法。。)
V操作:
int sem_post(sem_t *sem);
信号量加1,若此时有sem_wait正在阻塞则唤醒执行。
取值操作:
int sem_t getvalue(sem_t sem, int *val);
获取信号量的值,一般只用来调试,打印val查看。
三. 有名信号量
sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag,
mode_t mode, unsigned int value);
功能:创建或打开一个信号量
返回值:信号量指针,该指针可供其他对该信号量进行操作的函数使用
参数说明:name:信号量的名字,标识信号量;
oflag参数可以为:0,O_CREAT,O_EXCL。如果为0表示打开一个已存在的信号量,如果为O_CREAT,表示如果信号量不存在就创建一个信号量,如果存在则打开被返回。此时mode和value需要指定。如果为O_CREAT | O_EXCL,表示如果信号量已存在会返回错误。
mode参数用于创建信号量时,表示信号量的权限位,和open函数一样包括:S_IRUSR,S_IWUSR,S_IRGRP,S_IWGRP,S_IROTH,S_IWOTH。
int sem_close(sem_t *sem);
功能:sem_close用于关闭打开的信号量。当一个进程终止时,内核对其上仍然打开的所有有名信号量自动执行这个操作。
返回值:成功返回0,失败返回-1
调用sem_close关闭信号量并没有把它从系统中删除它,POSIX有名信号量是随内核持续的。即使当前没有进程打开某个信号量它的值依然保持。直到内核重新自举或调用sem_unlink()删除该信号量。
int sem_unlink(const char *name);
功能:将有名信号量立刻从系统中删除,但信号量的销毁是在所有进程都关闭信号量的时候(只close是不够的!)
返回值:成功返回0,失败返回-1
有名信号量的PV操作与无名信号量类似。
参考网上代码,自测了使用信号量同步线程的功能:
sem_t sem_g, sem_p;
int g_i_res=; void *pid_g(void)
{
while()
{
sem_wait(&sem_g);
g_i_res++;
Sleep();
if(g_i_res>)
system("pause");
sem_post(&sem_p);
} } void *pid_p(void)
{
while()
{
sem_wait(&sem_p);
printf("%d ", g_i_res);
fflush(stdout);
sem_post(&sem_g); } } int main()
{ pthread_t tid1, tid2;
sem_init(&sem_g, , );
sem_init(&sem_p, , ); pthread_create(&tid1, NULL, pid_g, NULL);
pthread_create(&tid2, NULL, pid_p, NULL); pthread_join(tid1, NULL);
pthread_join(tid2, NULL); return ;
}
说明:头文件按需添加,一般有<pthread.h> <semaphore.h> ,由于虽然是gcc编译但在Windows环境,所以用了<windows.h>的Sleep()

自己运行可以看到数字依次递增的打印过程,若不加system(pause)会无限刷屏的。。。
遇到新内容再更新吧~
linux POSIX 信号量介绍的更多相关文章
- linux Posix 信号量 一
信号量是一种用于提供不同进程间或一个给定进程的不同线程间同步手段的原语. linux提供两种信号量,“内核信号量”和“用户态进程信号量”,“用户态信号量”又分为“Posix”,“System V”信号 ...
- linux Posix 信号量 二
一.Posix信号量 1.Posix信号量分为两种: 1. 有名信号量:使用Posix IPC名字标识(有名信号量总是既可用于线程间的同步,又可以用于进程间的同步) 2. 内存信号量:存放在共 ...
- linux POSIX信号量
POSIX信号量机制是3种IPC机制之一,3种IPC机制源于POSIX.1的实时扩展. 创建一个新的命名信号量或者使用一个现有信号量 #include <fcntl.h> #include ...
- linux Posix 信号量 三 (经典例子)
本文将阐述一下信号量的作用及经典例子,当中包括“<越狱>寄信”,“家庭吃水果”,“五子棋”,“接力赛跑”,“读者写者”,“四方恋爱”等 首先,讲 semWait操作(P操作)和semSig ...
- Linux进程间通信IPC学习笔记之同步二(Posix 信号量)
Linux进程间通信IPC学习笔记之同步二(Posix 信号量)
- Linux进程同步之POSIX信号量
POSIX信号量是属于POSIX标准系统接口定义的实时扩展部分.在SUS(Single UNIX Specification)单一规范中,定义的XSI IPC中也同样定义了人们通常称为System V ...
- Linux多线程实践(5) --Posix信号量与互斥量解决生产者消费者问题
Posix信号量 Posix 信号量 有名信号量 无名信号量 sem_open sem_init sem_close sem_destroy sem_unlink sem_wait sem_post ...
- linux c编程:Posix信号量
POSIX信号量接口,意在解决XSI信号量接口的几个不足之处: POSIX信号量接口相比于XSI信号量接口,允许更高性能的实现. POSIX信号量接口简单易用:没有信号量集,其中一些接口模仿了我们熟悉 ...
- linux网络编程之posix信号量与互斥锁
继上次学习了posix线程之后,这次来讨论一下posix信号量与互斥锁相关的知识: 跟posix消息队列,共享内存的打开,关闭,删除操作一样,不过,上面的函数是对有名信号量进行操作,通过man帮助可以 ...
随机推荐
- es7预览
哈哈,es6才刚刚掌握,就给大家介绍es7了. es7的草案其实早已经定下来了,而且更加向着java这些高级语言看齐了 chrome的高版本其实也已经对es7的部分功能实现了!! 1.数组 inclu ...
- Jmeter调用 Json接口测试之关键点申明Content-Type类型
背景: 最近,在做接口测试发现创建运单接口,通过普通表单请求总是失败,开始我以为是后端接口出现问题,但通过前端页面都能创建运单,F12打开浏览器开发者模式,获取该接口请求入参发现,请求的数据格式是js ...
- Struts2_day04
一.回顾 1什么是值栈 (1)action和servlet区别 2 如何获取值栈对象 3 值栈内部结构 (1)root和context 4 向值栈放数据 (1)向值栈放字符串 (2)向值栈放对象 (3 ...
- javaScript事件系统详解
一个有情怀的猴子
- 【BZOJ4827】【HNOI2017】礼物
强省HN弱省HA……(读作强省湖南弱省蛤 原题: 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一 个送给她.每个手环上各有 n 个装饰物,并且每个 ...
- dubbo服务使用spring-data-mongodb进行时间查询的bug记录
一.项目情况:spring-boot+mongodb+dubbo. 二.问题:调用dubbo服务并使用spring-data-mongodb的gte,lte时间段比较查询, @Reference(re ...
- Linux 之【辨析UPDATE/UPGRADE】和安装/卸载软件(apt-get)
一.[辨析UPDATE/UPGRADE] UPDATE: update is used to download package information from all configured sour ...
- adb环境变量配置
针对win10系统: 搜索“高级系统设置”,点击“环境变量”按钮: 找到“path”双击: 双击“path”,在弹出的环境变量列表中新建,填入adb的文件路径 检查配置是否成功,运行命令adb,出现如 ...
- linux space/mark设置
参考链接: http://blog.csdn.net/zhaozh2000/article/details/6460223 串口数据的发送: 数据的发送: 数据位+检验位+停止位, 进行数据的发送.( ...
- B - Internship (网络流关键割边)
题目链接:https://cn.vjudge.net/contest/281961#problem/B 题目大意:给你n个城市,中间有一些中转站,然后给你终点,再给你l条轨道以及流量,问你增加哪几条轨 ...