进程间通讯——信号量
来源:互联网 发布:大众网络投资产品排行 编辑:程序博客网 时间:2024/06/05 00:21
信号量:通过管理对资源的访问,实现进程间同步控制。
在了解信号量的机制之前我们先了解几个与信号量有关的知识点:
(1) 临界资源:同一时刻只能呗同一个进程访问的资源;
(2) 原子操作:任何情况下都不能被打断的操作 ;
(3) 内核对象:用于进程通讯时,多进程能够访问同一资源的记录;
1、信号量的定义:
它是一个特殊变量,它只取正整数值,并且程序对信号量的访问都是原子操作,只允许对它进行等待和发送信号两种操作,下面
会解释这两种操作。
2、信号量的操作:
(1) 创建或获取:如果是创建必须初始化;如果是获取则不能初始化;
(2) 减一操作(P操作):假设一个信号量变量sv(下同),如果sv的值大于零,就给它减去一;如果sv的值等于零,就挂起该进程的执
行;
(3) 加一操作(v操作):如果有其他进程因等待sv而被挂起,就让它恢复运行;如果没有进程因等待sv而被挂起,就给它加一;
(4) 删除操作:因为有内核对象。
3、信号量有关的函数:
(1) semget函数:创建一个新信号量或获取一个已有信号量的键。
int semget(key_t key,int sems,int flag);
key:键值,一个非零整数,类似于信号量组中信号量的一个“身份证号”,不相关的进程可以通过它访问同一个信号量;
sems:指定需要的信号量数目,它的取值几乎总是1;
flag:其作用类似于文件的访问权限,可以和IPC_CREAT做按位或操作,信号量不存在时创建,存在时即获取;
返回值:semget函数成功时返回一个正数值,即信号量标识符;失败则返回-1.
(2) semop函数:用于改变信号量的值,即完成p操作或v操作。
int semop(int semid,struct sembuf *buf,size_t num_sem_ops);
semid:由semget返回的信号量标识符;
buf:指向一个结构数组的指针,每个数组元素包括以下几个成员:
struct sembuf{
short sem_num; //信号量编号,除非使用一组信号量,否则一般为0;
short sem_op; //信号量再一次操作中需要改变的数值,p操作:-1,v操作:+1;
short sem_flag; //通常为SEM_UNDO,是操作系统跟踪当前进程对这个信号量的修改情况
};
(3) semctl函数:用来直接控制信号量信息。
int semctl(int sem_id,int sem_num,int command,/*union semun un*/);
sem_id:由semget返回的信号量标识符;
sem_num:信号量编号,当需要用到组信号量时就需要用到这个参数,一般取值为0,表示这是第一个也是唯一的一个信号
量。
command:将要采取的动作,SETVAL初始化信号量,IPC_RMID删除一个无需继续使用的信号量标识符;
un:是一个union_semun的结构体,次结构体必须由程序员自己定义,包含以下几个成员:
union semun{
int val;
struct semid_ds *buf;
unsigned short *array;
}
4、信号量函数的封装:
// 头文件
#ifndef SEM_H
#define SEM_H
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
int semid;
union semun
{
int val;
};
void sem_get(int key,int len,int val);
void sem_p();
void sem_v();
void sem_del();
#endif
//.c文件
#include"sem.h"
void sem_get(int key,int len,int val)
{
semid = semget((key_t)key,len,0666);
if(semid == -1)
{
semid = semget((key_t)key,len,0666|IPC_CREAT);
assert(semid != -1);
union semun v;
v.val = val;
if(semctl(semid,0,SETVAL,v) == -1)
{
perror("error");
exit(0);
}
}
}
void sem_p()
{
struct sembuf sem;
sem.sem_num = 0;
sem.sem_op = -1;
sem.sem_flg = SEM_UNDO;
if(semop(semid,&sem,1) == -1)
{
perror("error");
exit(0);
}
}
void sem_v()
{
struct sembuf sem;
sem.sem_num = 0;
sem.sem_op = 1;
sem.sem_flg = SEM_UNDO;
if(semop(semid,&sem,1) == -1)
{
perror("error");
exit(0);
}
}
void sem_del()
{
if(semctl(semid,0,IPC_RMID) == -1)
{
perror("error");
exit(0);
}
}
- 进程间通讯——信号量
- 进程间通讯——信号量
- 进程间通讯——信号量
- Linux—进程间通讯—信号量
- 进程间通讯:信号量
- 进程间通讯--信号量
- 进程间通讯——信号量(一)
- 进程间通讯(3)—信号量&管道
- linux 进程间通讯--信号量
- Linux笔记_进程通讯——信号量
- 进程间通讯——消息队列、信号量以及共享内存
- Linux进程间通讯之信号量
- Linux进程间通讯之信号量sem
- 进程间通讯之信号量(实例)
- 进程间通讯---信号量练习(二)
- 进程间通讯(二)信号量
- 进程间的通讯方式_信号量
- 进程通讯-信号量
- leetCode_234. Palindrome Linked List(判断是否为回文串)
- Qt 5.7.0 (32 bit) 配置 Android 环境
- UVALive 3353 Optimal Bus Route Design
- Android移动开发-调用方向传感器开发简易指南针的实现
- 如何将一个已存在的目录转换为一个 GIT 项目并托管到 GITHUB 仓库
- 进程间通讯——信号量
- linux之getopt 函数
- 常见web错误码 404 500
- Android_Menu
- 虚拟机管理
- Linux入门学习——ssh基础操作
- 方法就是完成特定功能的代码块。 方法的格式: 修饰符 返回值的类型 方法名(参数类型 参数名1,参数类型 参数名2、、、、、、、、、 ){ 方法体; Return 返回值; } 赋值调用的格式:
- Python中使用SMTP发送邮件以及POP收取邮件
- 0-1背包问题:(回溯算法)