码迷,mamicode.com
首页 > 系统相关 > 详细

【linux高级程序设计】(第十一章)System V进程间通信 3

时间:2015-07-29 22:53:45      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:

信号量通信机制

技术分享

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

 

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\n", 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)\n", errno);
        
        arg.array = sem_read_array;
        //获取所有信号量的值
        ret = semctl(semid, 0, GETALL, arg); //获取所有信号量的值
        if(ret == -1)
            printf("GETALL failed (%d)\n", errno);
        
        for(i = 0; i < MAX_SEMAPHORES; i++)
            printf("Semaphore %d, value %d\n", i, sem_read_array[i]);
        
        //逐次获取信号量值
        for(i = 0; i < MAX_SEMAPHORES; i++)
        {
            ret = semctl(semid, i, GETVAL);
            printf("Semaphore %d, value %d\n", i, sem_read_array[i]);
        }
        //删除信号量集合
        ret = semctl(semid, 0, IPC_RMID);
    }
    else
    {
        printf("Could not allocate semaphore (%d)\n", 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)\n", errno);
    printf("productor init is %d\n", semctl(sem_id, 0, GETVAL));
    printf("space init is %d\n\n", 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\n");
    while(1)
    {
        printf("\n\nbefore produce:\n");
        printf("productor number is %d\n", semctl(sem_id, 0, GETVAL));
        printf("space init is %d\n\n", semctl(sem_id, 1, GETVAL));
        semop(sem_id, (struct sembuf *)&sops[1], 1);  //先预定一个空位
        printf("now producing.....\n");
        semop(sem_id,(struct sembuf *)&sops[0], 1); //生产出一个产品 释放一个产品
        printf("\nafter produce:\n");
        printf("productor number is %d\n", semctl(sem_id, 0, GETVAL));
        printf("space number is %d\n", 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\n");
    
    while(1)
    {
        printf("\n\nbefore consume:\n");
        printf("productor is %d\n", semctl(sem_id, 0, GETVAL));
        printf("space is %d\n", semctl(sem_id, 1, GETVAL));
        semop(sem_id, (struct sembuf *)&sops[0], 1); //预定一个要消费的产品
        printf("now consuming.....\n");
        semop(sem_id,(struct sembuf *)&sops[1], 1); //增加一个空位
        printf("\nafter consume:\n");
        printf("productor is %d\n", semctl(sem_id, 0, GETVAL));
        printf("space is %d\n", semctl(sem_id, 1, GETVAL));
        sleep(3);
    }
}

 

【linux高级程序设计】(第十一章)System V进程间通信 3

标签:

原文地址:http://www.cnblogs.com/dplearning/p/4687337.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!