zoukankan      html  css  js  c++  java
  • 【linux高级程序设计】(第十一章)System V进程间通信 3

    信号量通信机制

    可以看到,跟消息队列类似,也是包括两个结构。

    int semget (key_t __key, int __nsems, int __semflg) : 创建信号量集合

      第一个参数:ftok产生的key值

      第二个参数:创建的信号量个数

      第三个参数:权限信息

    创建信号量例子:

    #include<stdio.h>
    #include<unistd.h>
    #include<stdlib.h>
    #include<sys/ipc.h>
    #include<sys/sem.h>
    #include<sys/types.h>
    
    int main(int argc, char * argv[])
    {
        int sem;
        key_t key;
        if((key = ftok(".",'B'))==-1)
        {
            perror("ftok");
            exit(EXIT_FAILURE);
        }
        if((sem = semget(key, 3, IPC_CREAT|0770)) == -1)
        {
            perror("semget");
            exit(EXIT_FAILURE);
        }
        printf("sem1 id is: %d
    ", sem);
        semctl(sem, 0, IPC_RMID, (struct msquid_ds*)0);  //删除信号量集合
        return 0;
    }

    int semctl (int __semid, int __semnum, int __cmd, ...) :控制信号量集合、信号量

      第一个参数:要操作的信号量集合标识

      第二个参数:信号量编号。如果操作整个信号量集合无意义;如果是某个信号量,为信号量下标。

      第三个参数:执行的操作。 如果对整个集合操作,则包括:IPC_RMID, IPC_SET, IPC_STAT, IPC_INFO

                  如果是对某个或某些信号量操作,则包括GETPID、GETVAL、GETALL、GETNCNT、GETZCNT、SETVAL、SETALL.具体见图

    设置读取信号量的例子

    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/sem.h>
    #include<errno.h>
    #define MAX_SEMAPHORES 5
    int main(int argc, char *argv[])
    {
        int i, ret, semid;
        unsigned short sem_array[MAX_SEMAPHORES];
        unsigned short sem_read_array[MAX_SEMAPHORES];
        union senmun
        {
            int val;
            struct semid_ds *buf;
            unsigned short *array;
        }arg;
        //创建信号量集合
        semid = semget(IPC_PRIVATE, MAX_SEMAPHORES, IPC_CREAT|0666);
        if(semid != -1)
        {
            //初始化
            for(i = 0; i < MAX_SEMAPHORES; i++)
                sem_array[i] = (unsigned short)(i + 1);
            arg.array = sem_array;
            //设置所有信号量的值
            ret = semctl(semid, 0, SETALL, arg);
            if(ret == -1)
                printf("SETALL failed (%d)
    ", errno);
            
            arg.array = sem_read_array;
            //获取所有信号量的值
            ret = semctl(semid, 0, GETALL, arg); //获取所有信号量的值
            if(ret == -1)
                printf("GETALL failed (%d)
    ", errno);
            
            for(i = 0; i < MAX_SEMAPHORES; i++)
                printf("Semaphore %d, value %d
    ", i, sem_read_array[i]);
            
            //逐次获取信号量值
            for(i = 0; i < MAX_SEMAPHORES; i++)
            {
                ret = semctl(semid, i, GETVAL);
                printf("Semaphore %d, value %d
    ", i, sem_read_array[i]);
            }
            //删除信号量集合
            ret = semctl(semid, 0, IPC_RMID);
        }
        else
        {
            printf("Could not allocate semaphore (%d)
    ", errno);
        }
        return 0;
    }

    int semop (int __semid, struct sembuf *__sops, size_t __nsops) :操作信号量

    第一个参数:要操作的信号量集合ID

    第二个参数

    struct sembug{
        unsigned short sem_num;
        short sem_op;
        short sem_flg;
    };
    • sem_num:操作的信号量编号
    • sem_op:用于信号量的操作,正数表示增加信号量的值;负数表示减小信号量的值;0表示测试当前值是否为0
    • sem_flg:操作标识,IPC_NOWAIT,如果等待立即返回;SEM_UNDO,当进程退出后,该进程对sem进行的操作将被撤销。

    下面的代码,对信号量1做P操作(get),对信号量2做V操作(release)

    struct sembuf sops[4];
    sops[0].sem_num = 1;
    sops[0].sem_op = -1;
    sops[0].sem_flg = 0;
    
    sops[1].sem_num = 2;
    sops[1].sem_op = 1;
    sops[1].sem_flg = 0;
    
    semop(mysemid, sops, 2)

    信号量解决生产者消费者问题,设有100个空位的缓冲池。

    下面代码,经验证可用。

    生产者代码:

    #include<unistd.h>
    #include<stdlib.h>
    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/ipc.h>
    #include<sys/sem.h>
    #include<errno.h>
    int sem_id;
    void init()
    {
        key_t key;
        int ret;
        unsigned short sem_array[2];
        union semun
        {
            int val;
            struct semid_ds *buf;
            unsigned short *array;
        }arg;
        key = ftok(".",'s');
        sem_id = semget(key, 2, IPC_CREAT|0644);
        sem_array[0] = 0;   //0号下标 生产者
        sem_array[1] = 100;
        arg.array = sem_array;
        ret = semctl(sem_id, 0, SETALL, arg);  //初始化
        if(ret == -1)
            printf("SETALL failed (%d)
    ", errno);
        printf("productor init is %d
    ", semctl(sem_id, 0, GETVAL));
        printf("space init is %d
    
    ", semctl(sem_id, 1, GETVAL));
    }
    void del()
    {
        semctl(sem_id, 0, IPC_RMID);
    }
    int main(int argc, char *argv[])
    {
        struct sembuf sops[2];
    
        sops[0].sem_num = 0;
        sops[0].sem_op = 1;          //生产者数量加一
        sops[0].sem_flg = 0;
        
        sops[1].sem_num = 1;
        sops[1].sem_op = -1;         //消费者数量减一
        sops[1].sem_flg = 0;
        
        init();
        printf("this is productor
    ");
        while(1)
        {
            printf("
    
    before produce:
    ");
            printf("productor number is %d
    ", semctl(sem_id, 0, GETVAL));
            printf("space init is %d
    
    ", semctl(sem_id, 1, GETVAL));
            semop(sem_id, (struct sembuf *)&sops[1], 1);  //先预定一个空位
            printf("now producing.....
    ");
            semop(sem_id,(struct sembuf *)&sops[0], 1); //生产出一个产品 释放一个产品
            printf("
    after produce:
    ");
            printf("productor number is %d
    ", semctl(sem_id, 0, GETVAL));
            printf("space number is %d
    ", semctl(sem_id, 1, GETVAL));
            sleep(4);
        }
        del();
    }

    消费者代码:

    #include<unistd.h>
    #include<stdlib.h>
    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/ipc.h>
    #include<sys/sem.h>
    #include<errno.h>
    int sem_id;
    void init()
    {
        key_t key;
        key = ftok(".", 's');
        sem_id = semget(key, 2, IPC_CREAT|0644);
    }
    int main(int argc, char *argv[])
    {
        init();
        struct sembuf sops[2];
    
        sops[0].sem_num = 0;
        sops[0].sem_op = -1;          //产品数量减一
        sops[0].sem_flg = 0;
        
        sops[1].sem_num = 1;
        sops[1].sem_op = 1;         //空位数量加一
        sops[1].sem_flg = 0;
        printf("this is customer
    ");
        
        while(1)
        {
            printf("
    
    before consume:
    ");
            printf("productor is %d
    ", semctl(sem_id, 0, GETVAL));
            printf("space is %d
    ", semctl(sem_id, 1, GETVAL));
            semop(sem_id, (struct sembuf *)&sops[0], 1); //预定一个要消费的产品
            printf("now consuming.....
    ");
            semop(sem_id,(struct sembuf *)&sops[1], 1); //增加一个空位
            printf("
    after consume:
    ");
            printf("productor is %d
    ", semctl(sem_id, 0, GETVAL));
            printf("space is %d
    ", semctl(sem_id, 1, GETVAL));
            sleep(3);
        }
    }
  • 相关阅读:
    Node.js Event Loop 的理解 Timers,process.nextTick()
    Ajax关于readyState(状态值)和status(状态码)的研究
    原生 JavaScript 实现 AJAX、JSONP
    Python selenium.webdriver.chrome.options.Options() Examples
    【python】统一转换日期格式dateutil.parser.parse
    python读取doc
    大规模爬虫流程总结
    如何巧妙的利用selenium和requests组合来进行操作需要登录的页面
    使用pandas进行数据清洗
    twilio打电话和发短信
  • 原文地址:https://www.cnblogs.com/dplearning/p/4687337.html
Copyright © 2011-2022 走看看