Linux--进程间通信机制--信号量

1.什么是信号量:
信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有。
信号量的值为正的时候,说明它空闲。所测试的线程可以锁定而使用它。若为0,说明它被占用,测试的线程要进入睡眠队列中,等待被唤醒。

信号量是一种特殊的变量,访问具有原子性。
只允许对它进行两个操作:
1)等待信号量
当信号量值为0时,程序等待;当信号量值大于0时,信号量减1,程序继续运行。
2)发送信号量
将信号量值加1。
讲个比喻:比如有一个房间,门上有一把锁,这个房间同时只允许一个人进去,那么开锁的钥匙,我们就称为信号量,如果同时有很多把钥匙和锁,那么那些钥匙我们叫信号量集,房间叫做临界资源。

2.信号量的api:
semget
原型:

int semget(key_t key,int num_sems,int sem_flags);

第一个参数就是信号量的键值用ftok()获取,第二个是信号量集中信号量的个数,第三个参数就是两个宏:
IPC_CREATE和IPC_EXCL,
IPC_CREATE表示若信号量已存在,返回该信号量标识符。
IPC_EXCL表示若信号量已存在,返回错误。
一般我们选IPC_CREATE
示例:

semget(key,1,IPC_CREAT|0666);//0666权限可读可写

semop
原型:

int semop(int sem_id,struct sembuf *sem_opa,size_t num_sem_ops);

我们在调用p操作和v操作时使用这个函数,p操作就是取钥匙,v操作是放钥匙
第一个参数是semget的返回值,即信号量的ID,第二个是一个结构体 sembuf,用来设定信号量的变化以及初值,第三个是有几个信号量
示例:

void pgetkey(int id)
{
        struct sembuf set;
        set.sem_num=0;
        set.sem_op=-1;
        set.sem_flg=SEM_UNDO;

        semop(id,&set,1);
}

semclt
原型:

int semctl(int sem_id,int sem_num,int command,[union semun sem_union]);

第一个参数是semget返回值,即信号量ID,第二个是操作第几个信号量,从第0个开始,第三个是控制命令有两个值SETVAL,IPC_RMID,分别表示初始化和删除信号量,第四个参数是联合体需要我们配置
示例:

union semun{
        int val;
        struct seemid_ds *buf;
        unsigned short *array;
        struct seminfo *_buf;
};
int main()
{
        union semun initsem;
        semctl(semid,0,SETVAL,initsem);
        initsem.val=0;
  return 0;
  }

应用场景,在父进程创建子进程后,我们一般要控制其先后,sleep(),wait()命令都可以实现,今天我们用信号量来控制实现先运行子进程,再运行父进程,原理是,一开始没有信号量,父进程拿不到信号量无法执行,只能由子进程执行完毕后获得信号量再执行父进程
示例代码:

#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>

union semun{
        int val;
        struct seemid_ds *buf;
        unsigned short *array;
        struct seminfo *_buf;
};

void pgetkey(int id)
{
        struct sembuf set;
        set.sem_num=0;
        set.sem_op=-1;
        set.sem_flg=SEM_UNDO;

        semop(id,&set,1);
        printf("get key\n");

}

void vputbackkey(int id)
{
        struct sembuf set;
        set.sem_num=0;
        set.sem_op=1;
        set.sem_flg=SEM_UNDO;

        semop(id,&set,1);
        printf("put back the key\n");


}


int main(int argc,char *argv[])
{
        key_t key;
        int semid;

        key=ftok(".",2);
        semid=semget(key,1,IPC_CREAT|0666);

        union semun initsem;
        initsem.val=0;
        semctl(semid,0,SETVAL,initsem);

        printf("there is no key\n");

        int pid=fork();

        if(pid>0){
        pgetkey(semid);
        printf("this is father\n");
        vputbackkey(semid);
        semctl(semid,0,IPC_RMID);
        }
        else if(pid==0){
        printf("this is child\n");
        vputbackkey(semid);
        }
        else{
        printf("fork error\n");
        }

return 0;
}

运行结果:

在这里插入图片描述以上就是关于Linux中信号量的介绍,尚有不足之处,请各位大师指正。
salute CLC

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值