进程间通信之信号量(三)
来源:互联网 发布:动态截图软件 编辑:程序博客网 时间:2024/05/23 22:06
信号量
信号量是记录和统计临界资源数目的计数器;
(一)创建信号量:
信号量的申请是以信号量集为单位的;
int semget(key_t key,int nsems,int semflag);
返回值:信号量集的标识符;
参数:
key:用key_t ftok(const char* pathname,int proj_id)来获取;
nsems:表示要创建的这个信号量集中信号量的个数;
semflag:(1)IPC_CREAT:创建这个信号量集,若没有就创建,若有则打开即可;
(2)IPC_CREAT | IPC_EXCL:若创建的信号量不存在,则:创建;若创建的信号量存在,则:错误返回;
(二)初始化信号量
int semctl(int semid,int semnum, int cmd,);
返回值:(1)返回值为0表示初始化成功;
(2)初始化失败,返回-1;
参数:
semid:要初始化的信号量所在的信号量集的id;
semnum:要初始化的信号量是该信号量集的第几个信号(从0开始);
cmd:设为SETVAL表示对信号量进行初始化;
(三)删除信号量
int semctl(int semid,int semnum,int cmd)
返回值:(1)返回值为0表示删除信号量成功;
(2)返回值为-1表示删除失败;
参数:
semid:要删除的信号量集的id;
semnum:设置为0;
cmd:设置为IPC_RMID表示删除操作;
(四)P操作
int semop(int semid,struct sembuf*sops,unsigned nsops)
返回值:(1)返回值为0,表示操作成功;
(2)返回值为-1,表示操作成功;
参数:
semid:为操作的信号量所处的信号量集的id;
sops:所操作的信号量所在的数组;
struct sembuf
{
unsigned short sem_num; //操作信号量集中的哪一个信号量
short sem_op; //对于信号量执行什么操作
short sem_flg;
}
sops.sem_op = -1,位P操作;
nsops:操作的信号量的数目;
(五)V操作
int semop(int semid,struct sembuf*sops,unsigned nsops)
返回值:(1)返回值为0,表示操作成功;
(2)返回值为-1,表示操作失败;
参数:semid:为操作的信号量所处的信号量集的id;
sops:所操作的信号量所在的数组;
sops.sem_op = 1,位V操作;
nsops:操作的信号量的数目
common.h
#ifndef _COMMON_H_#define _COMMON_H_#include<stdio.h>#include<sys/types.h>#include<sys/ipc.h>#include<sys/sem.h>#define PATHNAME "/home/cm/code"#define PROJ_ID 0x6666union semun{ int val; struct semid_ds *buf; unsigned short *array; struct seminfo *_buf;};int Creat_Sem();int Get_Sem();int Init_Sem(int sem_id,int val);int Destory_Sem(int sem_id);int P(int sem_id,int who);int V(int sem_id,int who);#endif
common.c
#include"common.h"static int CommonCreat_Sem(int flags){ key_t key = ftok(PATHNAME,PROJ_ID); int sem_id =0; if(key<0) { perror("ftok"); return -1; } else { sem_id = semget(key,1,flags); if(sem_id < 0) { perror("semget"); return -2; } } return sem_id;}int Creat_Sem(){ int sem_id = CommonCreat_Sem(IPC_CREAT | IPC_EXCL | 0666); return sem_id;}int Get_Sem(){ int sem_id = CommonCreat_Sem(IPC_CREAT); return sem_id;}int Init_Sem(int sem_id,int Val){ union semun _un; _un.val = Val; int ret = semctl(sem_id,0,SETVAL,_un); if(ret < 0) //init failed { perror("semctl"); return -1; } return 0; //init success}int Destory_Sem(int sem_id){ int ret = semctl(sem_id,0,IPC_RMID); if(ret < 0) { perror("semctl"); return -1; } return 1;}static int CommonPV(int sem_id,int who,int op){ struct sembuf _sf; _sf.sem_num = who; _sf.sem_op = op; //P:-1;V:1 _sf.sem_flg = 0; int ret = semop(sem_id,&_sf,1); if(ret<0) { perror("semop"); return -1; } return 0;}int P(int sem_id,int who){ return CommonPV(sem_id,who,-1);}int V(int sem_id,int who){ return CommonPV(sem_id,who,1);}
Makefile
test:test_sem.c common.c gcc -o $@ $^.PHONY:cleanclean: rm -f test
#include"common.h"int main(){int sem_id = Creat_Sem();int val = 1;Init_Sem(sem_id,val);int pid = fork();if(pid == 0){ //child while(1) {P(sem_id,0);printf("A");fflush(stdout);usleep(123456);printf("A");fflush(stdout);usleep(123456);V(sem_id,0); }}else{while(1){ P(sem_id,0);printf("B");fflush(stdout);usleep(123456);printf("B");fflush(stdout);V(sem_id,0);}wait(NULL);} printf("\n"); Destory_Sem(sem_id); return 0;}
注;
struct sembuf{ unsigned short sem_num; //操作信号量集中的哪一个信号量 short sem_op; //对于信号量执行什么操作 short sem_flg;}sem_flg:
sem_flg是用来说明semop的操作方式;
(1)IPC_NOWAIT:对信号的操作不成功时,semop不会阻塞,并且立即返回。
(2)SEM_UNDO:程序结束的时候,对于数据进行回滚,避免造成数据的二义性;
对于二元信号量来说,为了防止造成死锁问题,必须在程序退出时,对于数据进行回滚,防止造成二义性;产生结果的不确定性;
作者水平有限,若有问题,请留言,谢谢!!!
阅读全文
0 0
- 进程间通信之信号量(三)
- 进程间通信(三)---- 信号量
- 进程间通信之信号量(灯)
- 进程间通信之信号量
- 进程间通信之信号量
- 进程间通信之信号量
- 进程间通信之信号量
- 进程间通信之信号量
- 进程间通信之信号量
- 进程间通信之信号量
- 进程间通信之信号量
- 进程间通信之信号量通信
- Linux进程间通信(IPC)之三——信号量(Semaphore)
- 进程通信之信号量
- 进程通信之信号量
- 进程通信之信号量
- 进程通信之信号量
- 【进程通信】之信号量
- 安卓实现滚动选择器
- 史上最简单的 MySQL 教程(十三)「列属性 之 空属性、列描述和默认值」
- MIPI转RGB芯片ICN6211规格书详细内容
- Kotlin:Android世界的Swift
- Oracle中查询条件
- 进程间通信之信号量(三)
- Webrtc delay-base-bwe代码分析(1): RateStatistics模块
- 二叉树线索化
- 数据库增删改练习
- 图解NIO(1) Buffer 与 Channel
- opencv(24)---轮廓特征属性及应用之最小外接圆
- 《lua程序设计》读书笔记 第二章:类型与值
- 关于select2默认选中 动态选中 显示,刷新选中
- 数据库—(5)