IPC进程间通信---信号量
信号量
信号量:信号量是一个计数器,常用于处理进程或线程的同步问题,特别是对于临界资源访问的同步。临界资源可以
理解为在某一时刻只能由一个进程或线程操作的资源,这里的资源可以是一段代码、一个变量或某种硬件资源。信号量的
值大于或等于0时表示可供并发进程使用的资源实体数,小于0时表示正在等待使用临界资源的进程数。
Linux内核也为每个信号集维护了一个semid_ds数据结构实例,该结构定义在头文件linux/sem.h中,各个字段含义为:
struct semid_ds
{
struct ipc_perm sem_perm; //对信号进行操作的许可权
__kernel_time_t sem_otime; //对信号进行操作的最后时间
__kernel_time_t em_ctime; //对信号进行修改的最后时间
struct sem *sembase; //指向第一个信号
struct sem_queue sem_pending; //等待处理的挂起操作
struct sem_queue **sem_pending_last; //最后一个正在挂起的操作
struct sem_undo *undo; //撤销的请求
ushort sem_nsems; //数组中的信号数
};
信号量使用key_t值作为它的名字。头文件<sys/types.h>把key_t这个数据类型定义为一个整数,它通常是一个至少32位
的整数。这些整数值通常由ftok函数赋予的。函数ftok把一个已存在的路径名和一个整数标识符转换成一个key_t值,称为
IPC键。该函数原形为:
#include <sys/ipc.h>
key_t ftok(const char *pathname,int proj_id);
创建或打开信号量前需要使用ftok函数得到key值,下面是ftok函数的包裹函数:
key_t Ftok(const char *pathname,int proj_id)
{
key_t key= ftok(pathname,proj_id);
if(key== -)
{
perror("ftok.");
exit();
}
return key;
}
信号量的创建或打开:
Linux下使用系统函数semget函数创建或打开信号量。该函数定义在头文件<sys/sem.h>中,该函数的原形为:
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key,int nsems,int semflg);
该函数执行成功返回一个信号量的标示符,失败返回-1。函数的第一个参数为ftok()函数得到的键值,第二个参数nsems
指明要创建的信号量包含的信号量个数,如果只是打开信号量,把nsems设置为0即可,第三个参数semflg为操作标志,可
以取如下值:
- IPC_CREAT:调用semget()时,它会将此值与系统中其它信号量的key值进行比较,如果存在相同的key,说明此信号量
已存在,此时返回该信号量的标识符,否则新建一个信号量并返回其标识符。
- IPC_EXCL:该宏必须和IPC_CREAT一起使用,否则没有意义。当semflg取IPC_CREAT|IPC_EXCL时,表示如果发现信号
量已经存在,则返回错误,错误码为EEXIST。
信号量的控制:
使用信号量时,往往需要对信号量进行一些控制操作,比如删除信号量、对内核维护的信号量的数据结构semid_ds进行
设置、获取信号量中信号值等。通过semctl控制函数可以完成这些操作,该函数定义在<sys/sem.h>中,如下所示:
int semctl(int semid,int semnum,int cmd, ...);
函数中,参数semid为信号量的标示符(即通过semget函数的到的值);参数semnum标示一个特定的信号;参数cmd指明控制
操作的类型;最后的“...”说明函数的参数是可选的,它依赖于第三个参数cmd,它通过共用体变量semun选择要操作的参数。
union semun
{
int val; //仅用于SETVAL操作类型,设置某个信号量的值等于val
struct semid_ds *buf; //用于IPC_STAT和IPC_SET操作,存取semid_ds结构
unsigned short *array; //用于SETALL和GETALL操作
struct seminfo *__buf; //为控制IPC_INFO提供的缓存
};
参数cmd通过宏来指示操作类型,通常取以下几个宏:
- GETVAL:把semval的当前值作为函数返回值返回。既然信号量决不会时负数(semval被声明为一个unsigned short整数),
那么成功的返回值总是非负数。
- SETVAL:把semval值设置为val。如果操作成功,那么相应信号量在所有进程中的信号量调整值将被设置为0。
- IPC_RMID:把由semid指定的信号量集从系统中删除掉。
信号量的操作:
信号量的值与相应资源的使用情况有关,当它的值大于0时,表示当前可用资源的数量,当它的值小于0时,其绝对值表
示等待使用该资源的进程个数。信号量的值仅能由PV操作来改变。使用semget打开一个信号量集后,对其中一个或多个信号
量的操作就使用semop函数来执行。该函数原型为:
int semop(int semid,struct sembuf *sops,unsigned nsops);
函数的参数semid为信号量的标示符,参数sops指向进行操作的结构体数组首地址,参数nsops指出将要进行操作的信号量
的个数。semop函数调用成功返回0,否则返回-1。
semop的第二个参数sops指向的结构体数组中,每个sembuf结构体对应一个特定的信号操作。该结构体为:
struct sembuf
{
unsigned short sem_num; //信号量在信号集中的索引
short sem_op; //操作类型
short sem_flg; //操作标志
};
sem_op的取值和意义:
- sem_op>0:信号量加上sem_op的值,表示进程释放控制的资源。
- sem_op=0:如果没有设置IPC_NOWAIT,则调用进程进入睡眠状态,直到信号量值为0;否则进程不会睡眠,直接返回
EAGAIN。
- sem_op<0:信号量加上sem_op的值。若没有设置IPC_NOWAIT,则调用进程阻塞,直到资源可用;否则进程直接返回
EAGAIN。
下面是对信号量进行操作的一个例子:
// myipc.h
#pragma once #include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/msg.h> union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
}; key_t Ftok(const char *pathname,int proj_id)
{
key_t key= ftok(pathname,proj_id);
if(key== -)
{
perror("ftok.");
exit();
}
return key;
}
#include "myipc.h" int main()
{
key_t sem_key= Ftok("mysem",0xff);
int sem_id= semget(sem_key,,IPC_CREAT);
if(sem_id== -)
{
perror("semget.");
exit();
}
else
{
printf("sem key = 0x%x,sem id = %d\n",sem_key,sem_id);
}
int ret;
union semun init;
init.val= ;
semctl(sem_id,,SETVAL,init);
struct sembuf info;
info.sem_num= ;
info.sem_op= ;
info.sem_flg= ;
semop(sem_id,&info,);
ret= semctl(sem_id,,GETVAL);
printf("sem value = %d\n",ret);
ret= semctl(sem_id,,IPC_RMID);
if(ret== -)
{
printf("Remove sem error.\n");
}
else
printf("Remove sem ok.\n");
return ;
}

IPC进程间通信---信号量的更多相关文章
- 【转载】Linux的进程间通信-信号量
原文:Linux的进程间通信-信号量 Linux的进程间通信-信号量 版权声明: 本文章内容在非商业使用前提下可无需授权任意转载.发布. 转载.发布请务必注明作者和其微博.微信公众号地址,以便读者询问 ...
- Android开发之IPC进程间通信-AIDL介绍及实例解析
一.IPC进程间通信 IPC是进程间通信方法的统称,Linux IPC包括以下方法,Android的进程间通信主要采用是哪些方法呢? 1. 管道(Pipe)及有名管道(named pipe):管道可用 ...
- System V IPC 之信号量
本文继<System V IPC 之共享内存>之后接着介绍 System V IPC 的信号量编程.在开始正式的内容前让我们先概要的了解一下 Linux 中信号量的分类. 信号量的分类 在 ...
- 【IPC进程间通信之四】数据复制消息WM_COPYDATA
IPC进程间通信+数据复制消息WM_COPYDATA IPC(Inter-Process Communication,进程间通信). 数据复制消息WM_C ...
- IPC 进程间通信方式——信号量
信号量 本质上是共享资源的数目,用来控制对共享资源的访问. 用于进程间的互斥和同步 每种共享资源对应一个信号量,为了便于大量共享资源的操作引入了信号量集,可对多对信号量一次性操作.对信号量集中所有的操 ...
- UNIX:高级环境编程 - 第十五章 IPC:进程间通信
IPC(InterProcess Communication)进程间通信.为啥没有进程间通信,这是因为进程间都是同步的关系,不需要通信. 1.管道 1.1管道特点: (1)半双工的(即数据只能在一个方 ...
- Linux - 进程间通信 - 信号量
一.概念 简单来讲,信号量是一个用来描述临界资源的资源个数的计数器. 信号量的本质是一种数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的通信资源(文件.外部设备等)来实现进程间通信, 他本身 ...
- Linux进程间通信—信号量
二.信号量(semophore) 信号量是一种计数器,可以控制进程间多个线程或者多个进程对资源的同步访问,它常实现为一种锁机制.实质上,信号量是一个被保护的变量,并且只能通过初始化和两个标准的原子操作 ...
- IPC 进程间通信
linux下进程间通信的几种主要手段简介: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它 ...
随机推荐
- js之闭包
函数作为返回值 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回. 我们来实现一个对Array的求和.通常情况下,求和的函数是这样定义的: function sum(arr) { ret ...
- 对 Vue 的理解(一)
一.什么是 Vue ? 首先,Vue 是一个 MVVM 框架,M -- 模型,就是用来定义驱动的数据,V -- 视图,是经过数据改变后的 html,VM -- 框架视图,就是用来实现双向绑定的中间桥梁 ...
- ASTreeView Demo:Add, Edit & Delete nodes
http://www.jinweijie.com/ http://www.astreeview.com/astreeviewdemo/astreeviewdemo1.aspx 選擇節點: <sc ...
- js变量定义提升、this指针指向、运算符优先级、原型、继承、全局变量污染、对象属性及原型属性优先级
原文出自:http://www.cnblogs.com/xxcanghai/p/5189353.html作者:小小沧海 题目如下: function Foo() { getName = functio ...
- 使用cookie实现只出现一次的广告代码效果
我们上网经常会遇到第一次需要登录而之后不用再登录的网站的情况,其实是运用了Cookie 存储 web 页面的用户信息,Cookie 以名/值对形式存储,当浏览器从服务器上请求 web 页面时, 属于该 ...
- python数据分析工具安装集合
用python做数据分析离不开几个好的轮子(或称为科学棧/第三方包等),比如matplotlib,numpy, scipy, pandas, scikit-learn, gensim等,这些包的功能强 ...
- 【起航计划ObjC 001】印第安老斑鸠ObjC的幻想 ---- Ubuntu下安装并使用Obj-C
如何在最新版本的 Ubuntu下(14.10)来安装.编译Objective-C? Ubuntu已经有了对Objective-C的编译器(gobjc)的安装,因此安装gobjc的步骤可省,如果你用的U ...
- 使用gulp解决外部编辑器修改Eclipse文件延迟刷新
本人前端用惯了Hbuilder,修改了eclipse项目中的文件后,由于是外部编辑器修改过的,eclipse不会自动部署更新,一般按F5刷新项目,或者在 preferences > genera ...
- Django初步(一):安装和简单演示
参考:Windows下安装Django:http://www.th7.cn/Program/Python/201305/136301.shtml
- sqlalchemy & python & datatables & javascript 中文拼音排序
近期有中文拼单排序需要,查询资料,mysql数据库有convert函数支持 select cname from channel order by convert(cname using gbk); # ...