LINUX_C编程实战—第十章《进程间的通信》-信号量
来源:互联网 发布:大数据平台需求分析 编辑:程序博客网 时间:2024/06/07 13:07
好久没更新博客啦,今天工作闲了可以做一个终结啦。
System V信号量的概念:可以理解为一个计数器,主要用于对临界资源的访问,进行PV操作(P操作,获取资源,资源数-1;V操作释放资源,资源数+1);信号量的值大于或等于0时表示可供并发进程使用的资源实体数,小于0表示正在等待使用临界资源的进程数。一般用的最多的为二进制信号量,既值取0,1;
键值:可以理解为IPC的一个中间介值,用来进行通信的,由ftok函数创建;
key_t ftok( const char *pathname, int proj_id); //文件的设备编号和节点
函数调用成功返回key_t键值,出错返回-1;其中在unix系统中,proj_id是子序列,为一个8bit的整数,范围为0-255;
此外要特别注意当pathname指向的文件或目录被删除而且又重新创建时,可以正常创建键值,但键值确和之前的值不一样啦,程序运行不会报错,但无法达到传输通信的作用。确保键值不变,要么保证ftok的文件不被删除,要么不用ftok,指定一个固定的key值
一、信号量的创建:
#include<sys/sem.h>
int semget( key_t key, int nsems, int semflg);//执行成功返回信号量标识符,失败返回-1;
nsems:信号量集中包含的信号量个数;
semflg:操作标识,IPC_CREATE | IPC_EXCL(信号集已有则返回错误)
二、信号量的操作(+-1)
int semop( int semid, struct sembuf *sops, size_t nsops);//成功返回0,失败返回-1;
semid;信号集标识符;
struct sembuf {
ushort sem_num;//信号量在信号量集中的索引
short sem_op;//操作类型,+1(释放资源,资源数加1) or -1(使用资源,资源数减少)
short sem_flg;//操作标志,IPC_NOWAIT 或 0;
}
nsops:将要进行操作的信号量个数,>=1
三、信号集控制: 对信号集中的信号量赋值、取值、删除等;
int semctl( int semid, int semnum,int cmd, union semun);//成功返回0,失败返回-1;
semid:信号量集标识符
semnum:操作信号量在信号量集中的编号,第一个信号量的标号为0;
cmd:取值可为SETVAL、GETVAL、IPC_RMID等;
union semun{
int val;
struct semid_ds *buf;
ushort *array;
struct seminfo *buf;
void *pad;
}
测试代码如下:实现进程间的同步
头文件:sem.h
#ifndef _SEM_H_#define _SEM_H_#include<stdio.h>#include<stdlib.h>#include<sys/types.h>#include<sys/ipc.h>#include<sys/sem.h>#include<unistd.h>#include<sys/wait.h>#define PATHNAME "."#define NUMBER 1int creat_sem(int sems);int init_sem(int semid,int which,int value);int get_sem();int p_sem(int semid,int which,int *flag);int v_sem(int semid,int which);int destroy(int semid);#endif
sem.c文件
#include "sem.h"/* 创建信号量集*/int creat_sem(int sems){key_t key;int semid;/* 利用ftok创建键值*/key=ftok(PATHNAME,NUMBER);if(key < 0){perror("ftok error");exit(1);}/* 创建信号量集函数*/semid=semget(key,sems,IPC_CREAT | 0666);if(semid < 0){perror("sem_get error");exit(1);}return semid;}int get_sem(){/* 利用IPC_CREAT打开已创建的信号量集*/return creat_sem(2);}/* 不懂为啥还要重复定义共同体,不定义就找不到定义的参数argc*/union semun{ int val; // value for SETVAL struct semid_ds *buf; // buffer for IPC_STAT & IPC_SET unsigned short *array; // buffer for GETALL & SELALL struct seminfo * __buf; // buffer for IPC_INFO};/* 初始化信号集*/int init_sem(int semid,int which,int value){union semun argc;int ret;argc.val = value;/* semctl函数用于初始化编号为which的信号集;亦可用于删除*/ret = semctl(semid,which,SETVAL,argc);if(ret < 0){perror("semctl error");exit(1);}return 0;}/* P操作获取资源,资源数-1 */int p_sem(int semid,int which,int *flag){struct sembuf sbuf={which,-1,0};int ret;ret = semop(semid,&sbuf,1);if(ret < 0){perror("p_sem error");/* 出错标志位*/*flag = 1;exit(0);}return 0;}/* V操作释放资源,资源数+1 */int v_sem(int semid,int which){struct sembuf sbuf={which,1,0};int ret;ret = semop(semid,&sbuf,1);if(ret < 0){perror("v_sem error");exit(0);}return 0;}/* 清空信号集*/int destroy(int semid){int ret;/* 使用参数IPC_RMID删除信号集*/ret = semctl(semid,0,IPC_RMID,0);if(ret < 0){perror("semctl error");exit(1);}return 0;}主函数:
#include "sem.h"int main(int argc,char **argv){pid_t pid;int semid,sem_id;/* 创建键值 */semid = creat_sem(10);init_sem(semid,0,1);pid = fork();if(pid < 0){perror("fork error");exit(0);}else if(pid == 0){/* 获得键值*/sem_id = get_sem();//printf("sem_id=%d\n",sem_id);while(1){p_sem(sem_id,0);printf("i am child\n");printf("child_flag=%d\n",_flag);printf("c_hello ");sleep(2);printf("c_world!\n");sleep(2);v_sem(sem_id,0); }}else{while(1){/* 获得信号量集中编号为0的资源*/p_sem(semid,0);/*************临界区 *****************************************************/printf("i am father\n");printf("father_flag=%d\n",_flag);printf("f_creat ");sleep(2);printf("sucess!\n");sleep(2);/*************临界区 *****************************************************//* 释放资源*/v_sem(semid,0);}wait(0);}destroy(semid);return 0;}
makefille文件:
all:main clearmain:sem.c main.cgcc sem.c main.c -o mainclear:rm -rf *.o运行结果:
- LINUX_C编程实战—第十章《进程间的通信》-信号量
- LINUX_C编程实战—第十章《进程间的通信》-消息队列
- LINUX_C编程实战-第十章《进程间通信》-管道
- LINUX_C编程实战-《进程间的通信》-共享内存
- 进程间通信—信号量
- 进程间通信—信号量
- 《unix高级环境编程》进程间通信——信号量
- 《unix高级环境编程》进程间通信——信号量
- 进程间通信编程(5) - 信号量
- linux_c 开发(5-6)进程间通讯_信号量
- 进程间通信 信号量
- 进程间通信--信号量
- 进程间通信-信号量
- 进程间通信-信号量
- 进程间通信--信号量
- 【进程间通信】信号量
- 进程间通信----信号量
- 进程间通信:信号量
- Windows 查看硬盘ID
- 依赖Description Resource Path Location Type A cycle was detected in the build pa
- android studio 报错问题汇集
- java二维数组
- 非块级元素的宽高设置
- LINUX_C编程实战—第十章《进程间的通信》-信号量
- C语言:编写一个函数实现一串字符串的左旋或者右旋
- 飘浮盒子,随机色,随机宽高
- 自定义View之Paint
- android中 dp->px和px->dp的工具方法
- C#初入CLR基础(一)
- 深入理解虚拟存储器(1:虚拟存储器概念与工作原理)
- Mac 10.12.6 下环境变量的配置。大坑套小坑。
- LINUX_C编程实战-《进程间的通信》-共享内存