linux进程间通信--信号量
Posted sucfrperperseverance
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux进程间通信--信号量相关的知识,希望对你有一定的参考价值。
信号灯(信号量)集
在多任务操作系统环境下,多个进程或线程会同时运行,多个任务可能可能为了完成同一个目标会相互协作,这样形成任务之间的同步关系;同样,在不同任务之间为了争夺有限的系统资源(硬件或软件资源)会进入竞争状态,这就是任务之间的互斥关系
任务之间的同步与互斥关系存在的根源在于临界资源。临界资源是指同一个时刻只允许有限个(通常只有一个)任务可以访问(读)或修改(写)的资源,通常包括硬件资源和软件资源,访问临界资源的代码称为临界区
POSIX 线程中的同步用的是无名信号量
进程间的同步使用的是IPC 对象[信号灯集]
信号灯集:信号灯集合,每一个信号灯都可以用来表示一类资源,其值表示资源的个数
其中信号量(信号灯集)对应于某一种资源,取一个非负整数值,信号量值指的是当前可用的资源数量,若它为0这意味着目前没有可用的资源
1.获得key值
第一种:
key_t ftok(const char *pathname, int proj_id);
参数:
@pathname 已经存在的文件路径
@proj_id 获取这个整数的低8bit
返回值:
成功返回 key值,失败返回-1
第二种:
将key值指定为IPC_PRIVATE ,当IPC对象在亲缘关系进程间通信的时候
(1)创建信号灯集
int semget(key_t key, int nsems, int semflg);
参数:
@key IPC_PRIVATE , ftok()
@nsems 信号灯集中信号灯的个数
@semflg IPC_CREAT | 0666,IPC_CREAT | IPC_EXCL
返回值:
成功返回ID,失败返回-1
(2)初始化信号灯集中信号灯的值
int semctl(int semid, int semnum, int cmd, union semun arg);
参数:
@semid 信号灯集的ID
@semnum 信号灯的编号[编号从0开始]
@cmd SETVAL[设置信号灯的值] ,GETVAL(获取信号灯的值),IPC_RMID[删除信号灯集]
返回值:
成功返回0,失败返回-1
思考:将信号灯集中的1号信号灯初始化为1?
其中arg:是union semnum 结构,可能在某些系统中不给出改结构的定义,这时必须由程序员自己定义
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */
};
//初始化指定编号的sem_num信号灯集为value
void init_sem_value(int sem_id,int sem_num,int value)
{
union semun sem_val;
sem_val.val = value;
if(semctl(sem_id,sem_num,SETVAL,sem_val) < 0)
{
...
}
return ;
}
PV原子操作的具体定义:
P操作:如果有可用资源(信号量值大于0),则占用一个资源(信号量值减一,进入临界区代码);如果没有可用资源(信号值等于0),则被阻塞,直到系统将资源分配给该任务(进入等待队列,一直等到有资源时被唤醒)
V操作:如果该信号量在等待队列中有任务在等待资源,则唤醒一个阻塞任务,如果没有任务等待他,则释放一个资源(信号量值加1)
(3)PV操作
int semop(int semid, struct sembuf *sops, unsigned nsops);
功能: 完成PV操作
参数:
@semid 信号灯集的ID
@sops 操作方式结构体首地址
@nsops 操作信号灯的个数
返回值:
成功返回0,失败返回-1
struct sembuf
{
unsigned short sem_num; /* semaphore number ,信号量的编号,使用单个信号量时,通常取值为0*/
short sem_op; /* semaphore operation 信号量操作,取-1表示P操作,取+1表示V操作*/
short sem_flg; /* operation flags 通常设置为SEM_UNDO,这样在进程没有释放信号量退出时,系统会自动释放该进程中未释放的信号量 */
};
sem_op :
<1>0 等待信号灯的值变成0
<2>1 释放资源,V操作
<3>-1 申请资源,P操作
sem_flg:
0 : 阻塞方式
IPC_NOWAIT : 非阻塞方式调用
SEM_UNDO : 进程结束的时候,它申请的资源自动释放
-----------------------------------------------------------------
P/V操作封装如下:
void P(int sem_id,int sem_num)
{
struct sembuf sem;
sem.sem_num = sem_num;
sem.sem_op = -1;
sem.sem_flg = 0;
if(semop(sem_id,&sem,1) < 0)
{
....
}
}
void V(int sem_id,int sem_num)
{
struct sembuf sem;
sem.sem_num = sem_num;
sem.sem_op = 1;
sem.sem_flg = 0;
if(semop(sem_id,&sem,1) < 0)
{
....
}
}
以上是关于linux进程间通信--信号量的主要内容,如果未能解决你的问题,请参考以下文章