zoukankan      html  css  js  c++  java
  • System V信号量

    信号量对比

    二值信号量:其值要么0要么1,比如互斥锁就是这种类型
    计数信号量:其值为0或某个正整数,比如POSIX 信号量
    计数信号量:一个或多个信号量构成一个集合,每个都是计数信号量,比如System V信号量
    shell查看命令:ipcs -s

    基本函数

    #include <sys/ipc.h>
    key_t ftok(char *fname,int id);
    #include <sys/sem.h>
    int semget(key_t key,int nsems,int oflag);
    int semop(int semid,struct sembuf opsptr[],size_t nops);
    int semctl(int semid,int semnum,int cmd,... /* union semun arg */);
     
    //system V信号量结构
    struct sem{
        ushort semval; //信号量的当前值
        short sempid; //最后一次修改进程的PID
        ushort_t semncnt;
        ushort_t semzcnt;
    }
    struct sembuf{
        short sem_num; //单个信号量的下标,取值范围[0,nsems-1]
        short sem_op; //操作值,如负数,0,正数
        short sem_flg; //具体的操作,如加或减,可选项有:0,IPC_NOWAIT,SEM_UNDO
    };
    //senum结构和System V消息队列中的消息结构类似
    //只是一个建议结构,在使用时需要在代码中自已定义
    union semun{
        int val; //SETVAL
        struct semid_ds *buf; //IPC_SET, IPC_STAT
        ushort; //GETALL, SETALL
    };
    

    ftok函数:用于生成一个唯一的key_t, fname为一个已存在的文件名, id取0-255之间的正整数, 两者组合形成一个key
    semget函数:用于创建或打开System V信号量,nsems表示信号量集合中信号量的个数,oflag为IPC_CREAT|IPC_EXCL|0644类似的组合
    semctl函数:cmd如下
    IPC_STAT, 返回指定信号量集当前的semid_ds结构
    IPC_RMID, 删除指定的信号量集
    SETALL, 设置信号量集中每个成员的semval值
    GETALL, 返回信号量集中每个成员的semval值
    IPC_SET, 设置指定信号量集的semid_ds结构中三个成员,sem_perm.uid,sem_perm.gid,sem_perm.mode
    semop函数:nops指定前面的opsptr数组的数量, semop分两种操作,一种是等待,一种是增减
    等待,当sem_op为0时等待信号量的值为0时返回
    加减,当sem_op为负数时,等待信号量的值为大于或等于该负数的绝对值时返回,同时会将信号量的值减去该负数的绝对值

    例子

    通过信号量来同步父子进程的输出

    #include "unpipc.h"
    #include <sys/sem.h>
     
    int main(int argc, char *argv[]){
        int c,i,semid,nops;
        struct sembuf *ptr;
        semid=semget(ftok(argv[1],0),1,0644|IPC_CREAT|IPC_EXCL);
        semctl(semid,0,SETVAL,mun.val);
        ptr=calloc(3,sizeof(struct sembuf));
     
        //ptr[0]加2,ptr[1]等待为0,ptr[2]减1
        for(i=0;i<3;i++){
            ptr[i].sem_num=0;
            ptr[i].sem_op=1-i;
            ptr[i].sem_flg=0;
        }
        ptr[0].sem_op=2;
     
        if(Fork() == 0){
            puts("left hand");
            semop(semid,&ptr[2],1);
            semop(semid,&ptr[2],1);
            puts("left foot");
            semop(semid,&ptr[2],1);
        }else{
            semop(semid,&ptr[1],1);
            puts("right hand");
            semop(semid,&ptr[0],1);
            semop(semid,&ptr[1],1);
            puts("right foot");
            sleep(1);
            semctl(semid,0,IPC_RMID);
        }
        exit(0);
    }
    
  • 相关阅读:
    mongodb3.6 (四)net 客户端如何连接、访问mongodb集群
    mongodb3.6 副本集(三)mongodb 如何做数据备灾
    winform中如何使用确认对话框
    Centos6.5在线配置安装Java环境与Tomcat环境
    IBatis.Net 下使用SqlBulkCopy 大批量导入数据 问题解决
    【easyui-combobox】下拉菜单自动补全功能,Ajax获取远程数据源
    IDEA创建springboot异常(Failed to load class "org.slf4j.impl.StaticLoggerBinder")
    Elasticsearch6.5安装&&常见问题与答案解释
    JS实现多Div模块拖拽功能
    IView入门练习~CDN模式全局加载JS
  • 原文地址:https://www.cnblogs.com/cfans1993/p/5813729.html
Copyright © 2011-2022 走看看