十念 发表于 6 天前

Linux中的信号量

目次

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

信号量概念

   界说

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

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

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

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

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

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

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h> 函数原型

int semget(key_t key, int nsems, int semflg); 参数说明

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

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

int sem_create(key_t key, int num_sems)
{
        int res = 0;
        res = semget(key, num_sems, IPC_CREAT | 0666);
        if (res < 0)
        {
                perror("semget error");
        }
        return res;
} 二、设置信号量初始值

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

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h> 函数原型

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 的界说如下:
union semun
{
    int            val;    /* Value for SETVAL */
    struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
    unsigned short*array;/* Array for GETALL, SETALL */
    struct seminfo*__buf;/* Buffer for IPC_INFO
                              (Linux-specific) */
};
返回值

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

union semun
{
        int            val;    /* Value for SETVAL */
        struct semid_ds* buf;    /* Buffer for IPC_STAT, IPC_SET */
        unsigned short* array;/* Array for GETALL, SETALL */
        struct seminfo* __buf;/* Buffer for IPC_INFO
                                                                (Linux-specific) */
};

int sem_setval(int semid, int semindex, int val)
{
        union semun arg;
        arg.val = val;
        int res = semctl(semid, semindex, SETVAL, arg);
        if (res < 0)
        {
                perror("semctl error");
        }
        return res;
} 三、信号量的P操作

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

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h> 函数原型

int semop(int semid, struct sembuf *sops, size_t nsops);
参数解释

           semid:信号量集的标识符,由 semget 函数返回,用于指定要操作的信号量集。
        sops:一个指向 struct sembuf 范例数组的指针,struct sembuf 结构体界说了对信号量的详细操作,其结构如下:
struct sembuf
{
    unsigned short sem_num;// 信号量集中信号量的编号,从 0 开始
    short          sem_op;   // 对信号量的操作值
    short          sem_flg;// 操作标志
};
        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 以指示错误范例。
示例

// 3、信号量的P操作
int sem_p(int semid, int semindex)
{
        int res = 0;
        struct sembuf buf = { semindex,-1,SEM_UNDO };
        res = semop(semid, &buf, 1);
        if (res < 0)
        {
                perror("sem_p error");
        }
        return res;
} 四、信号量的V操作

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

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