Linux进/线程同步方式4——信号量

一、信号量的定义

信号量是一种用于提供不同进程间或一个给定进程下的不同线程间进行同步的手段。

信号量类别使用方式
Posix有名信号量使用Posix IPC名字标识
Posix基于内存的信号量存放在共享内存区
System V信号量在内核中维护

二、Posix信号量的选择

  1. 单个进程的各个线程共享,可以使用基于内存的信号量;
  2. 彼此无亲缘关系的不同进程需要使用信号量时,通常使用有名信号量。

    基于内存的信号量的持续性

    1. 如果某个基于内存的信号量是由单个进程的各个线程共享的(sem_init的shared参数为0),那么该信号量具有随进程的持续性,当该进程终止时它也消失。
    2. 如果某个基于内存的信号量是在不同进程间共享的(sem_init的shared参数为1),那么该信号量必须存放在共享内存区中,因而只要该共享内存区依然存在,该信号量也就继续存在。

三、信号量分类

Posix二值信号量其值为0或1的信号量
计数信号量其值在0或某个限制值
System V计数信号量集一个或多个信号量(构成一个集合),其中每个都是计数信号量

注意: 当谈论Posix信号量时,所指的是单个计数信号量;当谈论System V信号量时,所指的是计数信号量集。

四、Posix信号量

  1. sem_open()函数
    用于创建一个新的有名信号量或打开一个已经存在的有名信号量。sem_open不需要类似于shared的参数或类似于PTHREAD_PROCESS_SHARED的属性,因为有名信号量总是可以在不同进程间共享。
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <semaphore.h>
    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_CREAT|O_EXCL;
    参数mode:指定权限位(设置O_CREAT时才需要);
    参数value:指定信号量的初值(设置O_CREAT时才需要)。
    返回值:若成功则返回指向信号量的指针,出错则返回SEM_FAILED。
  2. sem_close()函数
    关闭由sem_open()打开的有名信号量。
    #include <semaphore.h>
    int sem_close(sem_t *sem);
    
    参数sem:要关闭的有名信号量的指针;
    返回值:若成功则返回0,若出错则返回-1。

    注意: 关闭一个信号量并没有将它从系统中删除,即使当前没有进程打开着这个信号量,它的值也仍然会保持。

  3. sem_unlink()函数
    从系统中删除有名信号量。
    #include <semaphore.h>
    int sem_unlink(const char *name);
    
    参数name:有名信号量的名字;
    返回值:若成功则返回0,若出错则返回-1。

    注意: 当引用计数大于0时,name就能从文件系统中删除,然而其信号量的析构(不同于将它的名字从文件系统删除)却要等最后一个sem_close发生为止。

  4. sem_wait()函数
    等待信号量,如果该值大于0,那么就将它减1并立即返回。如果该值等于0,调用线程就将进入睡眠,直到该值变为大于0,此时再将它减1,函数随后返回。
    #include <semaphore.h>
    int sem_wait(sem_t *sem);
    
    参数sem:等待的信号量的指针;
    返回值:若成功则返回0,若出错则返回-1。
  5. sem_trywait()函数
    当所指定的信号量为0时,调用线程将不会进入睡眠等待,而是直接返回一个EAGAIN的错误。如果信号量的值大于0,则把信号量减1,然后返回。
    #include <semaphore.h>
    int sem_trywait(sem_t *sem);
    
    参数sem:等待的信号量的指针;
    返回值:若成功则返回0,若失败则返回-1
  6. sem_post()函数
    释放信号量,把所指定的信号量加1,然后唤醒正在等待该信号量变为正数的所有线程。
    #include <semaphore.h>
    int sem_post(sem_t *sem);
    
    参数sem:待释放的信号量的指针;
    返回值:若成功则返回0,若出错则返回-1。
  7. sem_getvalue()函数
    获取指定信号量的当前值。
    #include <semaphore.h>
    int sem_getvalue(sem_t *sem, int *sval);
    
    参数sem:指定的信号量的指针;
    参数sval:用于保存所指定信号量的当前值。若有一个或者多个线程正在调用sem_wait()阻塞在该信号量上,该函数返回阻塞在该信号量上进程或线程的个数。
    返回值:若成功则返回0,若出错则返回-1。
  8. sem_init()函数
    基于内存的信号量初始化。
    #include <semaphore.h>
    int sem_init(sem_t *sem, int pshared, unsigned int value);
    
    参数sem:要初始化的内存信号量。
    参数shared:如果为0,那么待初始化的信号量是在同一进程的各个线程间共享的,否则该信号量是在进程间共享的。
    参数value:信号量的初始值。
    返回值:若成功则返回0,若出错则返回-1。
  9. sem_destroy()函数
    销毁基于内存的信号量。
    #include <semaphore.h>
    int sem_destroy(sem_t *sem);
    
    参数sem:待销毁的信号量的指针;
    返回值:若成功则返回0,若出错则返回-1。
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值