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):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它 ...
随机推荐
- MyBatis 中 sqlmapconfig核心标签typeAliases配置说明
标签说明 在 MyBatis 的 sql 映射配置文件中,需要使用 paramterType.resultType 来设置 sql 语句的输入输出参数,一般参数都是基本的数据类型或封装类型,但都需要声 ...
- 【设计模式】template method(模板方法)-- 类行为型模式5.10
1.意图 子类在不改变父类的算法结构的情况下,可以重定义算法的某些特定步骤 2.动机 模板方法用一些抽象的操作定义一个算法,子类重定义这些操作以提供具体的行为:步骤的顺序定了,但实现可以调整: 3.适 ...
- PAT 1051 Pop Sequence
#include <cstdio> #include <cstdlib> #include <vector> using namespace std; bool p ...
- JavaScirpt(JS)——BOM浏览器对象模型
一.BOM概念 BOM(Browser Object Model)即浏览器对象模型.可以对浏览器窗口进行访问和操作.使用 BOM,开发者可以移动窗口.改变状态栏中的文本以及执行其他与页面内容不直接相关 ...
- jQuery二——属性操作、文档操作、位置属性
一.jquery的属性操作 jquery对象有它自己的属性和方法. 其中jquery的属性操作模块分为四个部分:html属性操作,dom属性操作,类样式操作和值操作. 1.html属性操作 是对htm ...
- 9th week -the history of program 1950~2020
We already know that programming language is a formal language designed to communicate instructions ...
- JavaScript简易动画
<p id="s">fly</p> <script> function move(){ var id=document.getElementBy ...
- 在crontab中执行脚本重要事项
crontab不能成功执行shell脚本的可能原因 crond进程不存在,该进程是crontab的守护进程,它必须存在才能让crontab正常使用: 系统时间不对: 环境变量的问题:crontab执行 ...
- 设计模式之简单工厂模式(Simple Factory)
原文地址:http://www.cnblogs.com/BeyondAnyTime/archive/2012/07/06/2579100.html 今天呢,要学习的设计模式是“简单工厂模式”,这是一个 ...
- 《浪潮之巅》(第2版):精彩的IT商战史
2011年看过第一版.以为看新版会跳过大部分看过的内容,结果发现还是从头到尾看了一遍,2011年看过的内容已经记不太确切了:) 另外IT的历史太精彩了,许多故事都知道,再看还是挺有意思.当然作者的文字 ...