System V IPC(2)-信号量
一.概述
System V信号量与System V消息队列不同。它不是用来在进程间传递数据。它主要是来同步进程的动作。
1.一个信号量是一个由内核维护的整数。其值被限制为大于或等于0。
2.可以在信号量上加上或减去一个数量。
3.当一个减操作把信号量减到小于0时,内核会阻塞调用进程。直到另一操作把信号恢复,阻塞才会解除。
4.常用的信号量是二进制信号量。即操作0和1来控制临界区。
二.函数接口
1.创建或打开一个信号量
#include <sys/sem.h> int semget(key_t key, int nsems, int semflg);
key和semflg跟消息队列一样,这里不再介绍,上面已给出消息队列的文章连接。
nsems:指定信号量数目,一般都是1。
2.控制信号量
#include <sys/sem.h> int semctl(int semid, int semnum, int cmd, ...);
semid:semget()返回的信号量标识符。
semnum:信号量编号,如果是成组的信号量,就要用到它,否则是0。
cmd:控制信号量的命令。SETVAL初始化一个值,IPC_RMID删除信号量。
第四个参数是一个union semun结构。如果有的Linux版本头文件没有这个结构,需要自己定义:
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) */
};
3.改变信号量的值
#include <sys/sem.h> int semop(int semid, struct sembuf *sops, size_t nsops);
sops:指向一个sembuf结构,该结构成员如下:
unsigned short sem_num:信号量编号,如果不是一组信号,一般都为0。
short sem_op:对信号量加减操作,如:-1,+1,1。
short sem_flg:通常设置为SEM_UNDO。如果进程终止时没有释放该信号量,内核会释放它。
三.简单例子
我们封装一个简单的二进制信号量,写2个小程序,一个只打印基数,一个只打印偶数,通过二进制信号量来控制它们按顺序打印1-10。
1.封装二进制信号量
/**
* @file binary_sem.h
*/
#ifndef _BINARY_SEM_H_
#define _BINARY_SEM_H_
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) */
};
/* 设置信号量 */
int sem_set(int sem_id);
/* 增大信号量 */
int sem_up(int sem_id);
/* 减小信号量 */
int sem_down(int sem_id);
/* 删除信号量 */
int sem_delete(int sem_id);
#endif
/**
* @file binary_sem.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/sem.h>
#include "binary_sem.h"
static union semun sem_union;
static struct sembuf sem_buf;
/* 设置信号量 */
int sem_set(int sem_id)
{
sem_union.val = ;
, SETVAL, sem_union) == -)
;
;
}
/* 改变信号量为1 */
int sem_up(int sem_id)
{
sem_buf.sem_num = ;
sem_buf.sem_flg = SEM_UNDO;
sem_buf.sem_op = ;
) == -)
;
;
}
/* 信号量减1 */
int sem_down(int sem_id)
{
sem_buf.sem_num = ;
sem_buf.sem_flg = SEM_UNDO;
sem_buf.sem_op = -;
) == -)
;
;
}
/* 删除信号量 */
int sem_delete(int sem_id)
{
, IPC_RMID, sem_union) == -)
;
;
}
2.打印基数的程序
/**
* @file sem1.c
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/sem.h>
#include <unistd.h>
#include "binary_sem.h"
#define SEM_KEY 7788
void err_exit(const char *err_msg)
{
printf("error: %s\n", err_msg);
exit();
}
int main(int argc, const char *argv[])
{
int sem_id, i;
/* 创建信号 */
, | IPC_CREAT)) == -)
err_exit("semget()");
/* 初始化信号为1 */
)
err_exit("sem_set()");
; i < ; i += )
{
/* 信号减一 */
)
err_exit("sem_down()");
sleep();
printf(], i);
/* 信号加一 */
)
err_exit("sem_up()");
sleep();
}
;
}
对信号量加减操作之间的代码就是临界区。程序第39行的sleep()是为了有足够的时间来允许第二个程序,46行的sleep()是尽量让其他程序来获取信号量。
3.只打印偶数的程序
/**
* @file sem2.c
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
#include "binary_sem.h"
#define SEM_KEY 7788
void err_exit(const char *err_msg)
{
printf("error: %s\n", err_msg);
exit();
}
int main(int argc, const char *argv[])
{
int sem_id, i;
/* 创建信号 */
, | IPC_CREAT)) == -)
err_exit("semget()");
; i <= ; i += )
{
/* 信号减一 */
)
err_exit("sem_down()");
printf(], i);
/* 信号加一 */
)
err_exit("sem_up()");
sleep();
}
;
}
四.实验
1.为了测试方便,上面2个程序的key统一用一个值为7788的宏来指定。
2.两个程序执行的流程:sem1初始化一个为1的信号量,进入循环后对信号执行减一,并进入临界区。休眠3秒的时间我执行第二个程序sem2,sem2进入循环后也执行减一操作,但此时信号已被sem1减为0,此时内核会阻塞sem1的操作,因为再减就小于0了。回到sem1,3秒过后,打印基数,并把信号重置为1,离开临界区,休眠1秒。此时内核发现信号是1,可以执行减操作,内核会对sem2放行,sem2进入临界区打印偶数。刚刚休眠1秒的sem1再次进入临界区,发现信号量被sem2减到了0,此时被内核阻塞,直到sem2重置信号量。如此反复!!!

最后:其实System V信号量的语义和API都比较复杂,有机会再探讨比它简单的POSIX信号量。
System V IPC(2)-信号量的更多相关文章
- System V IPC 之信号量
本文继<System V IPC 之共享内存>之后接着介绍 System V IPC 的信号量编程.在开始正式的内容前让我们先概要的了解一下 Linux 中信号量的分类. 信号量的分类 在 ...
- Linux 系统编程 学习:05-进程间通信2:System V IPC(2)
Linux 系统编程 学习:05-进程间通信2:System V IPC(2) 背景 上一讲 进程间通信:System V IPC(1)中,我们介绍了System IPC中有关消息队列.共享内存的概念 ...
- 线程同步、信号量、system v IPC
一.线程同步 条件变量 什么是条件变量? 线程A等待某个条件成立,条件成立,线程A才继续向下执行.线程B的执行使条件成立,条件成立以后唤醒线程A,以继续执行.这个条件就是条件变量. pthread_c ...
- 第3章 System V IPC
3.1 概述 System V IPC 包含:System V消息队列.System V信号量.System V共享内存. 3.2 key_t 键和 ftok函数 这三种类型的System V IPC ...
- 《Unix网络编程》卷2 读书笔记 第3章- System V IPC
1. 概述 三种类型的System V IPC:System V 消息队列.System V 信号量.System V 共享内存区 System V IPC在访问它们的函数和内核为它们维护的信息上共享 ...
- 从并发处理谈PHP进程间通信(二)System V IPC
.container { margin-right: auto; margin-left: auto; padding-left: 15px; padding-right: 15px } .conta ...
- System V IPC 之共享内存
IPC 是进程间通信(Interprocess Communication)的缩写,通常指允许用户态进程执行系列操作的一组机制: 通过信号量与其他进程进行同步 向其他进程发送消息或者从其他进程接收消息 ...
- System V IPC 之消息队列
消息队列和共享内存.信号量一样,同属 System V IPC 通信机制.消息队列是一系列连续排列的消息,保存在内核中,通过消息队列的引用标识符来访问.使用消息队列的好处是对每个消息指定了特定消息类型 ...
- 四十九、进程间通信——System V IPC 之消息队列
49.1 System V IPC 介绍 49.1.1 System V IPC 概述 UNIX 系统存在信号.管道和命名管道等基本进程间通讯机制 System V 引入了三种高级进程间通信机制 消息 ...
随机推荐
- 形象化的spring 依赖注入原理
转. IoC就是Inversion of Control,控制反转.在Java开发中,IoC意味着将你设计好的类交给系统去控制,而不是在你的类内部控制.这称为控制反转. 下面我们以几个例子来说明什 ...
- mybatis公用代码抽取到单独的mapper.xml文件
同任何的代码库一样,在mapper中,通常也会有一些公共的sql代码段会被很多业务mapper.xml引用到,比如最常用的可能是分页和数据权限过滤了,尤其是在oracle中的分页语法.为了减少骨架性代 ...
- Servlet—简单的管理系统
网站的框架 网站的框架采用MV模式,即Model(模型).View(视图).框架将界面层和模型层进行分离,结构更清晰,更加方便管理代码. 其中上图框架中的修改和删除功能完成而添加查询模块没有编写 实现 ...
- 【笔记】InnoDB内存分配
原文:http://www.mysqlperformanceblog.com/2006/05/30/innodb-memory-usage/ 有很多问题是有关InnoDB如何分配内存的.这里我试图解释 ...
- pywebsocket的搭建
Python可以搭建pywebsocket(Web服务器,python websocket),搭建pywebsocket必须要已经安装了python,点我查看python的下载与安装.在这篇Blog中 ...
- 【经验之谈】前端面试知识点总结(CSS相关)——附答案
目录 二.CSS部分 1.解释一下CSS的盒子模型? 2.请你说说CSS选择器的类型有哪些,并举几个例子说明其用法? 3.请你说说CSS有什么特殊性?(优先级.计算特殊值) 4.要动态改变层中内容可以 ...
- Jquery属性获取——attr()与prop()
今天在项目中使用<select></select>下拉菜单时,使用juery操作,使页面加载完菜单默认选中的值为2,我一开始的操作如下: <!--html部分--> ...
- Could not load file or assembly 'Microsoft.SqlServer.Management.Sdk.Sfc, Version=11.0.0.0 系统找不到指定的文件。
环境: web服务器: ip:192.168.1.32 ,安装有 Visual Studio Premium 2013 操作系统: Microsoft Server 2008 r2+sp1 数据库服 ...
- 使用 SQL的 for xml path来进行字符串拼接 (group by)
参考: http://www.cnblogs.com/repository/archive/2011/01/18/1938418.html select convert(varchar(10),c.[ ...
- Android studio .9图片造成的错误总结
前言,今天早晨遇到一个很奇葩的问题,导致我花费了很长的时间来解决.从eclipse 项目里复制过来4张.9图片,粘贴到android studio 项目里, 一运行发现报错,开始是 找不到这几张.9图 ...