Linux中的信号量

十念  论坛元老 | 2025-4-21 13:25:02 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1626|帖子 1626|积分 4878

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
目次

信号量概念
界说
操作
范例
应用
信号量封装
一、创建信号量
头文件
函数原型
参数说明
返回值
示例
二、设置信号量初始值
头文件
函数原型
参数解释
返回值
示例
三、信号量的P操作
头文件
函数原型
参数解释
返回值
示例
四、信号量的V操作
示例


信号量概念

   界说

          信号量是一种用于多历程 / 线程同步的整数变量,用于控制对共享资源的访问。凡是遇到内存操作就可以实现加锁。
  操作

          P 操作:信号量值减 1,若值小于 0 则历程壅闭,否则继承实验。
          V 操作:信号量值加 1,如有历程壅闭则叫醒一个。
  范例

          二进制信号量:值为 0 或 1,用于互斥访问。        
          ​​​​​计数信号量:值为非负整数,控制多资源访问。
  应用

          互斥访问:确保同一时间只有一个历程 / 线程访问共享资源。
          资源管理:控制对多个雷同资源的并发访问。
          历程同步:包管历程或线程按顺序实验。
  信号量封装

   1、创建/获取信号量
  2、设置初始值,一样平常为1
  3、P操作
  4、V操作
  一、创建信号量

        semctl 是一个在 Unix 和类 Unix 系统中用于控制信号量集的系统调用函数。
头文件

  1. #include <sys/types.h>
  2. #include <sys/ipc.h>
  3. #include <sys/sem.h>
复制代码
函数原型

  1. int semget(key_t key, int nsems, int semflg);
复制代码
参数说明

           key:唯一标识。
          nsems:要创建的信号量会合信号量的数量。
         semflg:标志位,用于指定创建信号量集的权限和其他选项。它可以是以下值的组合:           
                  IPC_CREAT:如果信号量集不存在,则创建它。
                  IPC_EXCL:与 IPC_CREAT 一起使用,如果信号量集已经存在,则返回错误。
                  权限标志(如 0666):指定信号量集的访问权限。
  返回值

        成功时,返回一个非负整数,即信号量集的标识符(semaphore identifier),后续的信号量操作将使用这个标识符。
        失败时,返回 -1,并设置 errno 以指示错误范例。
示例

  1. int sem_create(key_t key, int num_sems)
  2. {
  3.         int res = 0;
  4.         res = semget(key, num_sems, IPC_CREAT | 0666);
  5.         if (res < 0)
  6.         {
  7.                 perror("semget error");
  8.         }
  9.         return res;
  10. }
复制代码
二、设置信号量初始值

        semctl 是类 Unix 系统中用于控制信号量集的一个系统调用,借助它可以或许对信号量集进行多种操作,比方设置信号量的值、获取信号量的值、删除信号量集等。
头文件

  1. #include <sys/types.h>
  2. #include <sys/ipc.h>
  3. #include <sys/sem.h>
复制代码
函数原型

  1. int semctl(int semid, int semindex, int cmd, ...);
复制代码
参数解释

           semid:信号量集的标识符,由 semget 函数返回,用于指定要操作的信号量集。
          semindex:为第几个信号量设置值。
          cmd:要实验的命令,常见的命令如下:
                  SETVAL:把单个信号量的值设置为传入的参数值。
                  GETVAL:获取单个信号量的值。
                  SETALL:设置信号量会合全部信号量的值。
                  GETALL:获取信号量会合全部信号量的值。
                  IPC_RMID:删除信号量集。
          ...:这是可选参数,依据 cmd 的不同而有所不同。在使用 SETVAL 或 SETALL 时,需要传入对应的参数值。通常使用 union semun 范例的变量来传递该参数,union semun 的界说如下:
  1. union semun
  2. {
  3.     int              val;    /* Value for SETVAL */
  4.     struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
  5.     unsigned short  *array;  /* Array for GETALL, SETALL */
  6.     struct seminfo  *__buf;  /* Buffer for IPC_INFO
  7.                                 (Linux-specific) */
  8. };
复制代码
返回值

        成功时,依据 cmd 的不同返回不同的值。比方,GETVAL 命令返回信号量的值,IPC_RMID 命令成功时返回 0。
        失败时,返回 -1,并设置 errno 以指示错误范例。
示例

  1. union semun
  2. {
  3.         int              val;    /* Value for SETVAL */
  4.         struct semid_ds* buf;    /* Buffer for IPC_STAT, IPC_SET */
  5.         unsigned short* array;  /* Array for GETALL, SETALL */
  6.         struct seminfo* __buf;  /* Buffer for IPC_INFO
  7.                                                                 (Linux-specific) */
  8. };
  9. int sem_setval(int semid, int semindex, int val)
  10. {
  11.         union semun arg;
  12.         arg.val = val;
  13.         int res = semctl(semid, semindex, SETVAL, arg);
  14.         if (res < 0)
  15.         {
  16.                 perror("semctl error");
  17.         }
  18.         return res;
  19. }
复制代码
三、信号量的P操作

        semop 是类 Unix 系统中用于对信号量集进行操作的系统调用,它答应历程原子性地对一个或多个信号量进行改变,常用于实现历程间的同步和互斥。
头文件

  1. #include <sys/types.h>
  2. #include <sys/ipc.h>
  3. #include <sys/sem.h>
复制代码
函数原型

  1. int semop(int semid, struct sembuf *sops, size_t nsops);
复制代码
参数解释

           semid:信号量集的标识符,由 semget 函数返回,用于指定要操作的信号量集。
          sops:一个指向 struct sembuf 范例数组的指针,struct sembuf 结构体界说了对信号量的详细操作,其结构如下:
  1. struct sembuf
  2. {
  3.     unsigned short sem_num;  // 信号量集中信号量的编号,从 0 开始
  4.     short          sem_op;   // 对信号量的操作值
  5.     short          sem_flg;  // 操作标志
  6. };
复制代码
        sem_num:指定要操作的信号量在信号量会合的编号。
          sem_op:表现对信号量的操作值,有以下几种情况:
                  若 sem_op 为正数,则表现释放相应数量的资源,信号量的值会增长 sem_op。
                  若 sem_op 为负数,则表现请求相应数量的资源,信号量的值会减少 sem_op。若信号量当前值小于 |sem_op|,则历程可能会壅闭,详细取决于 sem_flg。
                  若 sem_op 为 0,则表现等待信号量的值变为 0。
          sem_flg:操作标志,常用的标志有:
                  IPC_NOWAIT:若操作不能立刻实验,则不壅闭,直接返回错误。
                  SEM_UNDO:当历程停止时,系统会自动撤销该历程对信号量的操作。
          nsops:sops 数组中元素的个数,即要实验的操作数量。
  返回值

        成功时,返回 0。
        失败时,返回 -1,并设置 errno 以指示错误范例。
示例

  1. // 3、信号量的P操作
  2. int sem_p(int semid, int semindex)
  3. {
  4.         int res = 0;
  5.         struct sembuf buf = { semindex,-1,SEM_UNDO };
  6.         res = semop(semid, &buf, 1);
  7.         if (res < 0)
  8.         {
  9.                 perror("sem_p error");
  10.         }
  11.         return res;
  12. }
复制代码
四、信号量的V操作

        v操作唯一的变化就是从-1变成+1
示例

  1. // 4、信号量的V操作
  2. int sem_v(int semid, int semindex)
  3. {
  4.         int res = 0;
  5.         struct sembuf buf = { semindex,1,SEM_UNDO };
  6.         res = semop(semid, &buf, 1);
  7.         if (res < 0)
  8.         {
  9.                 perror("sem_p error");
  10.         }
  11.         return res;
  12. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

十念

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表