linux的ipc信号量简单实例

信号量实现进程间访问互斥的资源测试例子。
主要涉及到的函数及原型如下(加粗、颜色表示要重点关心的上下文相关变量)
1: key_tftok(char *fileName, int id);//目的获取key值

2: intsemget(key_t key, int nsems, int semflg)//目的获取id

3:int semctl(int semid, int semnum, int cmd, union semunarg)//目的设置信号量的值,获取信号量的值等等,功能通过cmd变量控制
//其中semunarg必须由用户自身定义,格式如下
union semun {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
    struct seminfo *__buf;
    //other linux specific
};

4: int semop(int semid, struct sembuf *sops, unsign ednsops)//目的改变信号量的值,在sembuf中。

可通过每个函数大体功能,man手册中查找一些说明,进行研究测试。
以下测试代码非常简单,仅仅是为了熟悉api的基本功能,如果有错误和需要说明的地方,欢迎指正。

#include <sys/types.h>
#include <sys/sem.h>
#include <stdio.h>
#include <errno.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <unistd.h>

union semun {//semctl函数的第三个参数结构定义,现只关心设置val,其它成员可忽视,起到初始化资源数目的作用
    int val;
    // struct semid_ds *buf;
    // unsigned short *array;
    // struct seminfo *__buf;
};

int sem_init(int semid, int initval)//初始化信号量 init val
{
    union semun arg;

    arg.val = initval;
    semctl(semid, 0, SETVAL, arg);//SETVAL 是semctl的cmd参数,意思是设置信号量为arg.val的值,0是信号量中第1个资源的下标
    //fixme if some error
    return 0;
}

int creat_sem(char *fileName)//创建一个信号灯,信号量默认写了1个,如果没有该信号量,创建,如果有,获取id
{
    int id;
    key_t key;

    key = ftok(fileName, 1);
    if (key < 0) {
        perror("ftok()");
        key = 5;//any number just for test
    }

    if ((id = semget(key, 1, IPC_CREAT | IPC_EXCL |0660)) < 0) {//1个信号量 creat? or exist?
        if ((id = semget(key, 1, IPC_CREAT | 0660)) < 0) {//1个信号量 if exist,only get the id
            printf("semget error: id = %d\n", id);
        }
        printf("sem allready exist: id = %d\n", id);
    } else {//init the number when first use
        sem_init(id, 0);
    }

    return id;
}

void P(int semid)//申请资源,资源数sembuf中的sem_op - 1
{
    int ret = 0;
    struct sembuf sb;
    sb.sem_num = 0;
    sb.sem_op = -1;
    sb.sem_flg = 0;

    ret = semop(semid, &sb, 1);
    if (ret < 0) {
        printf("error in p(s)\n");
    }
}

void V(int semid)//释放资源,资源数sembuf中的sem_op - 1
{
    int ret = 0;
    struct sembuf sb;
    sb.sem_num = 0;
    sb.sem_op = 1;
    sb.sem_flg = 0;

    ret = semop(semid, &sb, 1);
    if (ret < 0) {
        printf("error in v(s)\n");
    }
}

void showStat(int semid)
{
    int ret = semctl(semid, 0, GETVAL, 0);

    printf("now %d val is %d\n", semid, ret);
}

int main(int argc, char **argv)
{
    int sem_id0, sem_id1;

    if (fork() == 0) {//子进程 进程1
        sem_id0 = creat_sem("/tmp/2");
        sem_id1 = creat_sem("/tmp/3");
        V(sem_id1);
        while (1) {
            P(sem_id0);
            printf("working : process11111\n");
            showStat(sem_id0);
            showStat(sem_id1);
            sleep(1);
            V(sem_id1);
        }
    } else {//父进程 进程2
        sem_id0 = creat_sem("/tmp/2");
        sem_id1 = creat_sem("/tmp/3");
        sleep(2);
        while (1) {
            P(sem_id1);
            printf("working : process2222222222\n");
            showStat(sem_id0);
            showStat(sem_id1);
            sleep(2);
            V(sem_id0);
        }
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值