信号量(Posix)
Posix信号量分为有名信号量和无名信号量
1. Posix有名信号量
有名信号量既可以用于线程间的同步也可以用于进程间的同步
sem都是创建在/dev/shm目录下,名字格式sem.xxx,只需要指定一个name名字即可。这是为什么名字被限制在NAME_MAX-4
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:选择创建或打开一个现有的信号灯
mode:权限位
value:信号灯初始值
返回值
成功时返回指向信号灯的指针,出错时为SEM_FAILED
oflag参数可以是0、O_CREAT(创建一个信号灯)或O_CREAT|O_EXCL(如果没有指定的信号灯就创建),如果指定了O_CREAT,那么第三个和第四个参数是需要的;该初始不能超过SEM_VALUE_MAX,这个常值必须低于为32767。二值信号灯的初始值通常为1,计数信号灯的初始值则往往大于1
如果指定了O_CREAT(而没有指定O_EXCL),那么只有所需的信号灯尚未存在时才初始化它。所需信号灯已存在条件下指定O_CREAT不是一个错误。该标志的意思仅仅是“如果所需信号灯尚未存在,那就创建并初始化它”。但是所需信号灯等已存在条件下指定O_CREAT|O_EXCL却是一个错误
int sem_unlink(const char *name);
要等到所有打开该信号量的进程关闭该信号量后才删除该信号
2. 举例
sem_t *sem;
//创建信号量,返回sem_t类型指针
if((sem = sem_open(argv[1],O_RDWR | O_CREAT,0644,atoi(optarg))) == SEM_FAILED)
{
perror("sem_open() error");
exit(-1);
}
//关闭打开的信号量
sem_close(sem);
sem_unlink(argv[1]);
3. Posix无名信号量
基于内存的信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);
pshared:信号量是由进程内线程共享,还是由进程之间共享
value:信号量的初始值
如果 pshared 的值为 0,那么信号量将被进程内的线程共享,并且应该放置在这个进程的所有线程都可见的地址上(如全局变量,或者堆上动态分配的变量);如果 pshared 是非零值,那么信号量将在进程之间共享
int sem_destroy(sem_t *sem);
销毁一个有其它线程或进程当前阻塞的信号量将导致未定义行为
使用一个已经销毁的信号量将导致未定义结果
int sem_post(sem_t *sem);
sem_post函数的作用是给信号量的值加上一个“1”,它是一个“原子操作”,即同时对同一个信号量做加“1”操作的两个线程是不会冲突的
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
sem_wait函数也是一个原子操作,它的作用是从信号量的值减去一个“1”,但它永远会先等待该信号量为一个非零值才开始做减法
sem_trywait()是函数sem_wait的非阻塞版,它直接将信号量sem减1,同时返回错误代码
int sem_getvalue(sem_t *sem, int *sval);
sem 指向的信号量当前值放置在 sval 指向的整数上
注:信号量的值可能在 sem_getvalue() 返回时已经被更改
4. 举例
建两个线程,这两个线程各自将自己的一个整型变量i从1 递增到100,并通过信号量控制递增的过程,即这两个整型变量的差不能超过5
void* th_fn1(void* arg)
{
int i;
for(i = 0; i < 100; ++i)
{
sem_wait(&sem1);
printf("number in thread1 is %d\n",i);
sem_post(&sem2);
}
pthread_exit((void*)"thread1exit\n");
}
void* th_fn2(void* arg)
{
int i;
for(i = 0; i < 100; ++i)
{
sem_wait(&sem2);
printf("number in thread2 is %d\n",i);
sem_post(&sem1);
}
pthread_exit((void*)"thread2exit\n");
}
int main(void)
{
void *tret;
sem_init(&sem1,0,5);
sem_init(&sem2,0,5);
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,th_fn1,NULL);
pthread_create(&tid2,NULL,th_fn2,NULL);
pthread_join(tid1,&tret);
pthread_join(tid2,&tret);
sem_destroy(&sem1);
sem_destroy(&sem2);
return 0;
}
5. 互斥量和信号量的区别
互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的
同步:是指在互斥的基础上,通过其它机制实现访问者对资源的有序访问
信号量(Posix)的更多相关文章
- Linux多线程实践(5) --Posix信号量与互斥量解决生产者消费者问题
Posix信号量 Posix 信号量 有名信号量 无名信号量 sem_open sem_init sem_close sem_destroy sem_unlink sem_wait sem_post ...
- Linux 信号量之Posix基于内存的信号量
信号量(semaphore),也和互斥锁一样提供了线程间或者进程间的同步功能. 信号量有三种: Posix有名字的信号量 Posix基于内存的信号量 System V信号量 信号量比互斥锁高级,互斥锁 ...
- Linux 信号量之Posix有名字的信号量
信号量(semaphore),也和互斥锁一样提供了线程间或者进程间的同步功能. 信号量有三种: Posix有名字的信号量 Posix基于内存的信号量 System V信号量 信号量比互斥锁高级,互斥锁 ...
- 第二章:Posix IPC
2.1:概述 以下三种类型的IPC合称为“Posix IPC”: Posix消息队列 Posix信号量 Posix共享内存区 Posix IPC在访问它们的函数和描述它们的信息上有一些类似点.本章讲述 ...
- 【转载】Linux的进程间通信-信号量
原文:Linux的进程间通信-信号量 Linux的进程间通信-信号量 版权声明: 本文章内容在非商业使用前提下可无需授权任意转载.发布. 转载.发布请务必注明作者和其微博.微信公众号地址,以便读者询问 ...
- POSIX 进程间通信 (可移植操作系统接口)
1.什么是POSIX标准 Portable Operating System Interface for Computing System. 他是一个针对操作系统(准确地说是针对类Unix操作系统)的 ...
- System IPC 与Posix IPC(semaphore信号灯)
POSIX下IPC主要包括三种: posix message queue posix semaphores posix shared memory sysytem v IPC包括: system v ...
- IPC之信号量
无名信号量 POSIX标准提出了有名信号量和无名信号量来同步进程和线程,而linux(2.6以前)只实现了无名信号量. sem_overview中有详细介绍:man 7 sem_overview. S ...
- Linux多线程编程-信号量
在Linux中.信号量API有两组.一组是多进程编程中的System V IPC信号量.另外一组是我们要讨论的POSIX信号量. 这两组接口类似,但不保证互换.POSIX信号量函数都已sem_开头,并 ...
- linux内核信号量
用户态的信号量: System V 信号量 Posix 信号量 信号量是用于保护临界区的一种常用方法.它的使用和自旋锁类似.相同的是,只有得到信号量的进程才能执行临界区代码:不同的是,当获取不到信号量 ...
随机推荐
- 使history命令显示时间
添加环境变量HISTTIMEFORMAT就行了 # export HISTTIMEFORMAT='%F %T ' .csharpcode, .csharpcode pre { font-size: ...
- CodeForces-1257D (贪心+双指针)
题意 https://vjudge.net/problem/CodeForces-1257D 你需要操作m个英雄去打败n只怪物,每个英雄的力量值为pi,可以打败si只怪物:每只怪物的力量值为ai. 当 ...
- Pwn-level2(x64)
题目地址 https://dn.jarvisoj.com/challengefiles/level2_x64.04d700633c6dc26afc6a1e7e9df8c94e 已经知道了它是64位了, ...
- 有关csp自我反思
首先说说体会把 这次前几个都是模拟,最后一道题以为自己可能会结果是半吊子根本不会,导致浪费了三个小时写第五题只有十分 如果不畏惧字符串而专心的写第三题的话,应该结果会不一样把.希望下次能好好考 第一题 ...
- C语言中,如何输出一个菱形!
int zh,zl,h,l; //zh:行的总数 zl:列的总数 h:当前行 l:当前列 for( ...
- 【2019.8.8 慈溪模拟赛 T1】开箱(chest)(暴力DP水过)
转化题意 这题目乍一看十分玄学,完全不可做. 但实际上,假设我们在原序列从小到大排序之后,选择开的宝箱编号是\(p_{1\sim Z}\),则最终答案就是: \[\sum_{i=1}^Za_{p_i} ...
- codevs 3304 水果姐逛水果街Ⅰ
这道题可以用ST表过: 题目链接 记录4个数组:maxval[][], minval[][], ans[][], rans[][] maxval[i][j]表示从i号元素开始,长度为(1<< ...
- Paper | Noise2Noise: Learning Image Restoration without Clean Data
目录 故事背景 算法原理 点估计 神经网络算法与点估计的关系 核心思想 回头品味 实验 高斯 其他生成噪声 发表在2018 ICML. 摘要 We apply basic statistical re ...
- Angular命令和基础操作
本文档假设你已经熟悉了 HTML,CSS,JavaScript和来自最新标准的一些知识,比如类和模块. 一.Angular命令 命令语法: 大多数命令以及少量选项,会有别名.别名会显示在每个命令的语法 ...
- (十九)golang--函数参数的传递方式
两种传递方式: 值传递:值类型参数默认 引用传递:引用类型参数默认 一般来说,地址传递效率高,因为数据量小. 值类型:int.float.bool.string.数组.结构体: 引用类型:指针.切片. ...