信号量
来源:互联网 发布:mac python环境图标 编辑:程序博客网 时间:2024/06/14 06:47
一、什么是信号量
为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域。临界区域是指执行数据更新的代码需要独占式地执行。而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在访问它,也就是说信号量是用来调协进程对共享资源的访问的。
信号量是一个特殊的变量,程序对其访问都是原子操作,且只允许对它进行等待(即P(信号变量))和发送(即V(信号变量))信息操作。最简单的信号量是只能取0和1的变量,这也是信号量最常见的一种形式,叫做二进制信号量。而可以取多个正整数的信号量被称为通用信号量。这里主要讨论二进制信号量。
二、信号量的使用
创建/获取信号量:
#include <sys/sem.h>int semget(key_t key, int num_sems, int sem_flags);key:非0整数,不相关的进程可以通过它访问一个信号量(一般由ftok函数产生)num_sems: 指定需要的信号量数目,一般是1。sem_flags:是一组标志,当想要当信号量不存在时创建一个新的信号量,可以和值IPC_CREAT做按位或操作。设置了IPC_CREAT标志后,即使给出的键是一个已有信号量的键,也不会产生错误。而IPC_CREAT | IPC_EXCL则可以创建一个新的,唯一的信号量,如果信号量已存在,返回一个错误。12345678910改变信号量的值#include <sys/sem.h>int semop(int sem_id, struct sembuf *sem_opa,size_t num_sem_ops);sem_id: 是semget函数返回的信号量标识符sembuf结构体:struct sembuf{ short sem_num; //除非使用一组信号量,否则它为0 short sem_op;//信号量在一次操作中需要改变的数据,通常是两个数,一个是-1,即P(等待)操作 ,一个是+1,即V(发送信号)操作。 short sem_flg;//通常为SEM_UNDO,使操作系统跟踪信号,并在进程没 有释放该信号量而终止时,操作系统释放信号量 }; num_sem_ops: 设置的信号量值
控制信号量:
#include <sys/sem.h>int semctl(int sem_id, int sem_num, int command,...);sem_id: semget 返回的信号量标识符sem_num: 设置信号量值command : 一般为SETVAL 或者 IPC_RMIDSETVAL:用来把信号量初始化为一个已知的值。p 这个值通过union semun中的val成员设置,其作用是在信号量第一次使用前对它进行设置。IPC_RMID:用于删除一个已经无需继续使用的信号量标识符。如果有第四个参数,一般为union senum 结构体 union semun{ int val; struct semid_ds *buf; unsigned short *arry; };
三、使用信号量进程进程间通信
#include<stdio.h>#include<sys/types.h>#include<string.h>#include<sys/sem.h>#include<sys/ipc.h>#include<stdlib.h>#define PATHNAME "."#define PROJ_ID 6666union SemNo{ int val; struct semid_ds* buf; unsigned short* array; struct seminfo* _buf;};int CreateSemSet(int nums);int GetSemSet();int InitSemSet(int semid, int nums);int P(int semid);int V(int semid);int DestorySemSet(int semid);/******************************************/int CommSemSet(int flags, int nums){ key_t _k=ftok(PATHNAME, PROJ_ID); if(_k < 0){ perror("ftok"); sleep(3); return -1; } int semid = semget(_k, nums, flags); if(semid < 0){ perror("semget"); sleep(3); return -2; } return semid;}/******************************************//******************************************/int CreateSemSet(int nums){ return CommSemSet(IPC_CREAT | IPC_EXCL | 0666, nums);}/******************************************//******************************************/int GetSemSet(){ return CommSemSet(0, 0);}/******************************************//******************************************/int InitSemSet(int semid,int nums){ union SemNo _SenNo; _SenNo.val=1; if(semctl(semid,nums,SETVAL,_SenNo)<0) { perror("semctl"); sleep(3); return -1; } return 0;}/******************************************//******************************************/int CommPV(int semid ,int nums, int flags){ struct sembuf _sf[1]; _sf[0].sem_op=flags; _sf[0].sem_num=nums; if(semop(semid, _sf, 1) < 0){ perror("semop"); sleep(3); return -1; } return 0;}/******************************************//******************************************/int P(int semid){ return CommPV(semid, 0, -1);}/******************************************//******************************************/int V(int semid){ return CommPV(semid, 0 ,1);}/******************************************//******************************************/int DestorySemSet(int semid){ if(semctl(semid, 0, IPC_RMID) < 0) { perror("semctl"); sleep(3); return -1; } return 0;}/******************************************/int main(){ int semid = CreateSemSet(1); InitSemSet(semid,0); pid_t id = fork(); if(id == 0) { int semid = GetSemSet(); while(1){ P(semid); printf("A"); fflush(stdout); usleep(20000); printf("A\n"); fflush(stdout); usleep(30000); V(semid); } } else{ while(1){ P(semid); printf("B"); fflush(stdout); usleep(30000); printf("B\n"); fflush(stdout); usleep(20000); V(semid); } } DestorySemSet(semid);}
编译
gcc -o comm comm.c
阅读全文
0 0
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- <>信号量
- 信号量
- 信号量
- MySQL 之 SQL 语句优化学习
- Eclipse中查看JDK源码
- 36. 编写完成fun函数实现将一行字符串中的最短的单词输出。此行字符串从主函数传递给该函数。
- echarts柱状图虚线显示
- Linux安装flux护眼软件
- 信号量
- UVa400
- 贪污罪量刑标准
- 用1个for语句 实现多个for循环
- TEST
- C语言编程规范
- LeetCode题目:Roman to Integer
- 学习笔记——JavaEE基础<1>HTML基础
- C# 委托实现多线程调用窗体