• System V 信号量使用相关函数


    System V 信号量

    在提到Posix 信号量时,指的是二值信号量或计数信号量,而System V信号量指的是入了计数信号量集

    二值信号量:其值为0或1,类似于互斥锁,资源被锁住时为0,资源可用为1
    计数信号量:其值在0和某个限制值之间的信号量,信号量的值就是可用资源数
    计数信号量集:一个或多个信号量构成一个集合,集合中每个元素都是计数信号量(每个集合的信号量数存在一个限制)

    semid_ds结构:

    内核为每个信号量集维护的信息结构

    #include <sys/sem.h>
    
    struct semid_ds{
        struct ipc_perm sem_perm;   // 当前信号量的访问权限
        struct sem *sem_base;        // 内核用于维护某个给定信号量的一组值的内部数据结构
        ushort sem_nsems;           // 集合中信号量的数目
        time_t sem_otime;           // 最近一次执行semop()的时间
        time_t sem_ctime;           // 集合创建时间或最近一次IPC_SET的时间
    };
    
    struct sem{
        ushort_t semval;    // 信号量实际值
        short sempid;       // 对信号量值执行最后一次操作的进程的进程ID
        ushort_t semncnt;   // 等待信号量值增长的进程数
        ushort_t semzcnt;   // 等待信号量值变为0的进程数
    };

    semget()函数:

    #include <sys/sem.h>
    
    // 创建一个信号量集或访问一个已存在的信号量集
    // 成功返回非负信号量标识符,出错返回-1
    int semget(key_t key, int nsems, int oflag);
    // key: IPC 键
    // nsems:指定集合中信号量数
    // oflag:SEM_R(读)和SEM_A(改)的组合,还可以按位与IPC_CREAT或IPC_CREAT|IPC_EXCL

    semop()函数:

    #include <sys/sem.h>
    
    // 对信号量集中一个或多个信号量进行操作
    // 成功返回0,出错返回-1
    int semop(int semid, struct sembuf *opsptr, size_t nops);
    // semid:由semget()函数返回的信号量标识符
    // nops: 指出opsptr指向的结构数组的元素数量
    // opsptr:指向一个如下的数组
    
    struct sembuf{
        short sem_num;  // 信号量集中信号量的索引值:0, 1, ... , nsems-1(sem_base[sem_num], 指定对某个特定信号量进行操作)
        short sem_op;   // 指定对特定信号量的操作
        short sem_flg;  // 操作标志,0, IPC_NOWAIT、SEM_UNDO
    };
    // sembuf结构内元素的排列顺序并不保证如上述那样,只保证该结构中有上述三个元素
    // sembuf结构不能静态初始化(struct sembuf value = {0, 0, 0} // Error)
    // sembuf结构需要运行时初始化(struct sembuf value; value.sem_num = 0; ...)
    
    // sem_op:每个特定的操作有sem_op确定,它可以是负数、0、正数
    // sem_op为正数时,其值加到semval(信号量当前值)上,对应于释放信号量控制的资源
    //       如果指定了SEM_UNDO标志,就从相应信号量的semadj(所指定信号量针对调用进程的调整值)减去sem_op
    // sem_op为0,调用者等待semval变为0,如果semval已经为0,则立即返回
    // sem_op为负数,调用者希望等待semval变为大于或等于sem_op的绝对值,这对应于分配资源

    semctl()函数:

    #include <sys/sem.h>
    
    // 对一个信号量执行各种控制操作
    // 成功返回非负值,出错返回-1
    int semctl(int semid, int semnum, int cmd, ... /* union semun arg */);
    // semid: 标识其操作待控制的信号量集
    // semnum: 标识信号量集内的某个成员(sem_base[sem_num])
    
    // cmd:可选值如下(除非另外说明,操作成功函数返回值为0,出错为-1)
    // GETVAL:将semval的当前值作为函数返回值返回
    // SETVAL:将semval设为arg.val(若操作成功,那么相应信号量的semadj被设为0)
    // GETPID:将sempid的当前值作为函数返回值返回
    // GETNCNT:将semncnt(等待semval变为大于其当前值的线程数)的当前值作为函数返回值返回
    // GETZCNT:将semzcnt(等待semval变为0的线程数)的当前值作为函数返回值返回
    // GETALL:返回指定信号量集内每个成员的semval值(这些值通过arg.array指针返回)
    // SETALL:设置指定信号量集内每个成员的semval值(这些值通过arg.array指针传递)
    // IPC_RMID:将由semid指定的信号量集从系统删除
    // IPC_SET:设置指定信号量集的semid_ds结构中的sem_perm.uid、sem_perm.gid、sem_perm.mode,这些值由arg.buf参数指向的结构中的相应成员指定
    // IPC_STAT:返回指定信号量集当前的semid_ds结构(通过arg.buf)
    
    // arg: 可选参数,根据 cmd 参数而定
    union semun{
        int val;
        struct semid_ds *buf;
        ushort *array;
    };
  • 相关阅读:
    树的直径、重心、中心
    DP优化--四边形不等式
    P5569 【SDOI2008】 石子合并(黑科技)
    P3147 262144游戏
    P3205 【HNOI2010】合唱队
    Windows Server 2012 虚拟化实战:网络(一)
    Windows Server 2012 虚拟化实战:存储(二)
    Android使用最小宽度限定符时最小宽度的计算
    Eclipse调试Android App若选择“Use same device for future launches”就再也无法选择其他设备的问题
    Python的模块引用和查找路径
  • 原文地址:https://www.cnblogs.com/lnlin/p/9741943.html
Copyright © 2020-2023  润新知