6.15 信号灯(有名信号灯、无名信号灯、system V信号灯)

本文详细介绍了信号量的概念和作用,包括POSIX信号量的初始化、P/V操作,以及SystemVIPC中的信号灯使用,包括信号灯的创建、初始化、P/V操作和信号灯集的管理。重点讲解了信号量在进程和线程同步中的应用,以及如何通过sem_init、sem_wait、sem_post等函数进行操作。
摘要由CSDN通过智能技术生成

目录

信号量/灯

信号量-P/V操作

Posix  信号量

信号量初始化 – sem_init

信号量 – P / V 操作

System V IPC - 信号灯

System V IPC - 信号灯特点

System V信号灯使用步骤

信号灯创建/打开 – semget

信号灯初始化 – semctl

信号灯集初始化 -  示例

信号灯P/V操作 – semop

信号灯操作 – sembuf

笔记


信号量/灯

信号量代表某一类资源,其值表示系统中该资源的数量

信号量是一个受保护的变量,只能通过三种操作来访问
初始化
P操作(申请资源)
V操作(释放资源)

信号量-P/V操作

P(S) 含义如下:
     if  (信号量的值大于0) {   
          申请资源的任务继续运行;
          信号量的值减一;
}
     else {   申请资源的任务阻塞;} 
V(S) 含义如下:
    信号量的值加一;
     if (有任务在等待资源) {
          唤醒等待的任务,让其继续运行
 }

Posix  信号量

posix中定义了两类信号量:
无名信号量(基于内存的信号量,linux仅支持线程同步)
有名信号量 

pthread库常用的信号量操作函数如下:
int sem_init(sem_t *sem,  int pshared,  unsigned int value); 
int sem_wait(sem_t *sem);   //  P操作
int sem_post(sem_t *sem);  // V操作 

信号量初始化 – sem_init

 #include  <semaphore.h>
 int  sem_init(sem_t *sem, int pshared, unsigned int val);

 成功时返回0,失败时EOF
 sem  指向要初始化的信号量对象
 pshared   0 – 线程间   1 – 进程间
 val  信号量初值

信号量 – P / V 操作

 #include  <semaphore.h>
 int  sem_wait(sem_t  *sem);       P操作
 int  sem_post(sem_t  *sem);       V操作

 成功时返回0,失败时返回EOF
 sem  指向要操作的信号量对象

System V IPC - 信号灯

信号灯也叫信号量,用于进程/线程同步或互斥的机制

信号灯的类型
  Posix 无名信号灯
  Posix有名信号灯
  System V  信号灯

信号灯的含义
  计数信号灯

System V IPC - 信号灯特点

System V 信号灯是一个或多个计数信号灯的集合

可同时操作集合中的多个信号灯

申请多个资源时避免死锁

System V信号灯使用步骤

打开/创建信号灯   semget

信号灯初始化   semctl

P/V操作   semop

删除信号灯  semctl

信号灯创建/打开 – semget

 #include <sys/ipc.h>
 #include <sys/sem.h>
 int semget(key_t key, int nsems, int semflg);

  成功时返回信号灯的id,失败时返回-1
  key   和消息队列关联的key  IPC_PRIVATE 或 ftok
  nsems   集合中包含的计数信号灯个数
  semflg   标志位  IPC_CREAT|0666   IPC_EXCL

信号灯初始化 – semctl

#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, …);
  成功时返回0,失败时返回EOF
  semid    要操作的信号灯集id
  semnum   要操作的集合中的信号灯编号
  cmd   执行的操作  SETVAL  IPC_RMID
  union  semun      取决于cmd

信号灯集初始化 -  示例

要求:假设信号灯集合中包含两个信号灯;
第一个初始化为2,第二个初始化为0
  union  semun  myun;

  myun.val = 2;
  if (semctl(semid, 0, SETVAL, myun) < 0) {
     perror(“semctl”);     exit(-1);
  }
  myun.val = 0;
  if (semctl(semid, 1, SETVAL, myun) < 0) {
     perror(“semctl”);     exit(-1);
  }

信号灯P/V操作 – semop

#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, unsigned nsops);

  成功时返回0,失败时返回-1
  semid    要操作的信号灯集id
  sops    描述对信号灯操作的结构体(数组)
  nsops   要操作的信号灯的个数

信号灯操作 – sembuf

 struct  sembuf 
 {
     short  sem_num;
     short  sem_op;
     short  sem_flg;
 };

 semnum         信号灯编号
 sem_op           -1:P操作   1:V操作
sem_flg           0 / IPC_NOWAIT


笔记

信号灯/信号量(semaphore)
概念:是不同进程间或一个给定进程内部不同线程间同步的机制。类似我们的
PV操作概念:
生产者和消费者场景
P(S) 含义如下:
     if  (信号量的值大于0) {  
 申请资源的任务继续运行;
           信号量的值减一;
} else {   
申请资源的任务阻塞;

V(S) 含义如下:
     信号量的值加一;
     if (有任务在等待资源) {   
唤醒等待的任务,让其继续运行 
}

三种信号灯:
Posix 有名信号灯
Posix 无名信号灯 (linux只支持线程同步)
System V 信号灯


Posix 有名信号灯和无名信号灯使用:

有名信号灯打开:
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:name是给信号灯起的名字
oflag:打开方式,常用O_CREAT 
mode:文件权限。常用0666
value:信号量值。二元信号灯值为1,普通表示资源数目

信号灯文件位置:/dev/shm

有名信号灯关闭
int sem_close(sem_t *sem);

有名信号灯的删除
int sem_unlink(const char* name);

无名信号灯初始化
int sem_init(sem_t *sem, int shared, unsigned int value);
参数:
sem:需要初始化的信号灯变量
shared: shared指定为0,表示信号量只能由初始化这个信号量的进程使用,不能在进程间使用,linux 不支持进程间同步。
Value:信号量的值

无名信号灯销毁
int sem_destroy(sem_t* sem);

信号灯P操作
int sem_wait(sem_t *sem);
获取资源,如果信号量为0,表示这时没有相应资源空闲,那么调用线程就将挂起,直到有空闲资源可以获取

信号灯V操作
int sem_post(sem_t *sem);
释放资源,如果没有线程阻塞在该sem上,表示没有线程等待该资源,这时该函数就对信号量的值进行增1操作,表示同类资源多增加了一个。如果至少有一个线程阻塞在该sem上,表示有线程等待资源,信号量为0,这时该函数保持信号量为0不变,并使某个阻塞在该sem上的线程从sem_wait函数中返回

注意:编译posix信号灯需要加pthread动态库。


System V 信号灯使用:

int semget(key_t key, int nsems, int semflg);
功能:创建/打开信号灯
参数:key:ftok产生的key值(和信号灯关联的key值)
         nsems:信号灯集中包含的信号灯数目
         semflg:信号灯集的访问权限,通常为IPC_CREAT |0666
返回值:成功:信号灯集ID ; 失败:-1

int semop ( int semid, struct sembuf *opsptr, size_t nops);
功能:对信号灯集合中的信号量进行P - V操作
参数:semid:信号灯集ID
   struct sembuf {
    short sem_num; // 要操作的信号灯的编号
    short sem_op;  // 1 : 释放资源,V操作
 // -1 : 分配资源,P操作  
    short sem_flg;  // 0(阻塞),IPC_NOWAIT, SEM_UNDO
   };//对某一个信号灯的操作,如果同时对多个操作,则需要定义这种结构体数组

   nops: 要操作的信号灯的个数 ,1个
返回值:成功 :0 ; 失败:-1

int semctl ( int semid, int semnum, int cmd…/*union semun arg*/);
功能:信号灯集合的控制(初始化/删除)
参数:semid:信号灯集ID
   semnum: 要操作的集合中的信号灯编号
   cmd:
   GETVAL:获取信号灯的值,返回值是获得值
   SETVAL:设置信号灯的值,需要用到第四个参数:共用体
   IPC_RMID:从系统中删除信号灯集合
返回值:成功 0 ; 失败 -1


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值