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)的更多相关文章

  1. Linux多线程实践(5) --Posix信号量与互斥量解决生产者消费者问题

    Posix信号量 Posix 信号量 有名信号量 无名信号量 sem_open sem_init sem_close sem_destroy sem_unlink sem_wait sem_post ...

  2. Linux 信号量之Posix基于内存的信号量

    信号量(semaphore),也和互斥锁一样提供了线程间或者进程间的同步功能. 信号量有三种: Posix有名字的信号量 Posix基于内存的信号量 System V信号量 信号量比互斥锁高级,互斥锁 ...

  3. Linux 信号量之Posix有名字的信号量

    信号量(semaphore),也和互斥锁一样提供了线程间或者进程间的同步功能. 信号量有三种: Posix有名字的信号量 Posix基于内存的信号量 System V信号量 信号量比互斥锁高级,互斥锁 ...

  4. 第二章:Posix IPC

    2.1:概述 以下三种类型的IPC合称为“Posix IPC”: Posix消息队列 Posix信号量 Posix共享内存区 Posix IPC在访问它们的函数和描述它们的信息上有一些类似点.本章讲述 ...

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

    原文:Linux的进程间通信-信号量 Linux的进程间通信-信号量 版权声明: 本文章内容在非商业使用前提下可无需授权任意转载.发布. 转载.发布请务必注明作者和其微博.微信公众号地址,以便读者询问 ...

  6. POSIX 进程间通信 (可移植操作系统接口)

    1.什么是POSIX标准 Portable Operating System Interface for Computing System. 他是一个针对操作系统(准确地说是针对类Unix操作系统)的 ...

  7. System IPC 与Posix IPC(semaphore信号灯)

    POSIX下IPC主要包括三种: posix message queue posix semaphores posix shared memory sysytem v IPC包括: system v ...

  8. IPC之信号量

    无名信号量 POSIX标准提出了有名信号量和无名信号量来同步进程和线程,而linux(2.6以前)只实现了无名信号量. sem_overview中有详细介绍:man 7 sem_overview. S ...

  9. Linux多线程编程-信号量

    在Linux中.信号量API有两组.一组是多进程编程中的System V IPC信号量.另外一组是我们要讨论的POSIX信号量. 这两组接口类似,但不保证互换.POSIX信号量函数都已sem_开头,并 ...

  10. linux内核信号量

    用户态的信号量: System V 信号量 Posix 信号量 信号量是用于保护临界区的一种常用方法.它的使用和自旋锁类似.相同的是,只有得到信号量的进程才能执行临界区代码:不同的是,当获取不到信号量 ...

随机推荐

  1. python中的随机模块random

    random模块是 python 中为随机数所使用的模块 ```import random # 随机生成0-1范围内的随机浮点数i = random.random()print(i) # 随机生成范围 ...

  2. Centos7安装vsftp服务

    我们需要向centos操作系统的服务器上上传文件或者下载文件,这时候,ftp有必要安装下, 我们选择主流的vsftp: 第一步:安装vsftp yum install -y vsftpd 第二步:设置 ...

  3. Docker 类面试题(常见问题)

    Docker 常见问题汇总   镜像相关 1.如何批量清理临时镜像文件? 可以使用sudo docker rmi $(sudo docker images -q -f danging=true)命令 ...

  4. react的路由中的switch和exact的使用

    刚刚接触react不久,发现在项目中的路由配置中会有switch和exact的使用,现总结如下 switch  为了解决route的唯一渲染(仅仅渲染一个路由路径)出现的 <Switch> ...

  5. axios如何先请求A接口然后在请求B接口

    总结:在第一个then的请求结束后,在添加一个then,表示请求第二个接口,在第二个then里面写第二个接口的请求方式 axios.get("./a.json").then(res ...

  6. 6.gitlab 备份

    在配置文件有有默认的  备份路劲 sudo vim /etc/gitlab/gitlab.rb 默认在这个  路径下面 /var/opt/gitlab/backups 然后默认的备份时间是  7天 , ...

  7. Pwnable-cmd1

    ssh cmd1@pwnable.kr -p2222 (pw:guest) 先看一下c的源码 #include <stdio.h> #include <string.h> in ...

  8. 2019.6.11_MySQL进阶一:索引

    所谓索引就是为特定的mysql字段进行一些特定的算法排序,比如二叉树的算法和哈希算法,哈希算法是通过建立特征值,然后根据特征值来快速查找.MySQL索引的建立对于MySQL的高效运行是很重要的,索引可 ...

  9. Vue 变异方法filter和正则RegExp对评论进行搜索

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. CodeForces - 545CWoodcutters

    传送门 题目大意:n棵树(10^5),坐标xi,高度hi,把这棵树砍到,可以向右倒[xi,xi+hi]被占, 向左倒[xi-hi,xi]被占,必须要倒的坐标没有被占才能倒,不砍倒就xi被占,问最多砍几 ...