一 信号量的基本概念

  信号量:它是一个特殊变量,只允许对它进行等待和发送信号这两种操作。
  假设有一个信号量变量sv
  P(sv):用于等待,如果sv的值大于零,就给它减去1,如果它的值等于零,就挂起该进程的执行。
  V(sv):用于发送信号,如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而被挂起,就给它加1

二 信号量的相关函数

#include <sys/sem.h>
//semctl函数的作用是用来直接控制信号量信息
int semctl(int sem_id,            //由semget返回的信号量标识符
       int sem_num,           //是信号量编号,当需要用到成组的信号量时,就要用到这个参数,它一般取值为0,表示这是第一个也是唯一的信号量
       int command,           //是将要采取的动作
       ...                //它将会是一个union semun结构
      );
//semget函数的作用是创建一个新信号量或取得一个已有信号量的键。
int semget(key_t key,            //key是整数值,不相关的进程可以通过它访问同一个信号量
       int num_sems,          //指定需要的信号量数目,几乎总是取值为1
       int sem_flags          //是一组标志,与open函数的标志非常相似
      );                 //在成功时返回一个正数(非零)值,它就是其他信号量函数将用到的信号量标识符,如果失败,则返回-1
//semop函数用于改变信号量的值int semop(int sem_id,           //由semget返回的信号量标识符
      struct sembuf *sem_ops,   //指向一个sembuf结构数组的指针
      size_t num_sem_ops        //信号操作结构的数量,恒大于或等于1
     );

  semun包含于semun.h头文件中

union semun{
int val;          //SETVAL所设置的信号量集中的一个信号量的值
struct semid_ds *buf;  //IPC_STAT,IPC_SET存储的数据
unsigned short *array;  //GETALL, SETALL返回值的数组
}

  semop函数中的sembuf结构体

struct sembuf{
short sem_num;  //信号量编号,除非需要使用一组信号量,否则它的取值一般为0
short sem_op;   //是信号量在一次操作中需要改变的数值,通常只会用到两个值,一个是-1,也就是P操作,它等待信号量变为己用;一个是+1,也就是V操作,它发送信号表示信号量现在已可用
short sem_flg;  //通常设置为SEM_UNDO,它将使得操作系统跟踪当前进程对这个信号量的修改情况
}

  semctl中第三个参数command取值如下:

    ·IPC_STAT:读取一个信号量集的数据结构semid_ds,并将其存储在semun中的buf参数中。
    ·IPC_SET:设置信号量集的数据结构semid_ds中的元素ipc_perm,其值取自semun中的buf参数。
    ·IPC_RMID:将信号量集从内存中删除。
    ·GETALL:用于读取信号量集中的所有信号量的值。
    ·GETNCNT:返回正在等待资源的进程数目。
    ·GETPID:返回最后一个执行semop操作的进程的PID。
    ·GETVAL:返回信号量集中的一个单个的信号量的值。
    ·GETZCNT:返回这在等待完全空闲的资源的进程数目。
    ·SETALL:设置信号量集中的所有的信号量的值。
    ·SETVAL:设置信号量集中的一个单独的信号量的值。

三 例子

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h> #include <sys/sem.h>
#include "semun.h" static int set_semvalue(void);
static void del_semvalue(void);
static int semaphore_p(void);
static int semaphore_v(void); static int sem_id; int main(int argc,char *argv[]){
int i;
int pause_time;
char op_char=''; srand((unsigned int)getpid());
sem_id=semget((key_t),,|IPC_CREAT);
if(argc>){
if(!set_semvalue()){
fprintf(stderr,"Failed to initialize semaphore\n");
exit(EXIT_FAILURE);
}
op_char='X';
sleep();
} //进入和离开临界区域10次,在每次循环的开始,首先调用semaphore函数,它在程序进入临界区域时设置信号量以等待进入
for(i=;i<;i++){
if(!semaphore_p()){
exit(EXIT_FAILURE);
}
printf("%c",op_char);
fflush(stdout);
pause_time=rand()%;
sleep(pause_time);
printf("%c",op_char);
fflush(stdout); //临界区域之后,调用semaphore_v来将信号量设置为可用,然后等待一段随机时间,再进入下一次循环。在整个循环语句执行完毕后,调用del_semvalue函数来清理代码
if(!semaphore_v()){
exit(EXIT_FAILURE);
}
pause_time=rand()%;
sleep(pause_time);
}
printf("\n%d - finished\n",getpid());
if(argc>){
sleep();
del_semvalue();
}
exit(EXIT_SUCCESS);
} //函数set_semvalue通过将semct1调用的command参数设置为SETVAL来初始化信号量
static int set_semvalue(void){
union semun sem_union;
sem_union.val=;
if(semctl(sem_id,,SETVAL,sem_union)==-){
return ;
}
return ;
} static void del_semvalue(void){
union semun sem_union;
if(semctl(sem_id,,IPC_RMID,sem_union)==-){
fprintf(stderr,"Failed to delete semaphore");
}
} //semaphore_p对信号量做减1操作(等待)
static int semaphore_p(void){
struct sembuf sem_b;
sem_b.sem_num=;
sem_b.sem_op=-;
sem_b.sem_flg=SEM_UNDO;
if(semop(sem_id,&sem_b,)==-){
fprintf(stderr,"semaphore_p failed\n");
return ;
}
return ;
} //semaphore_v将sembuf结构中的sem_op设置为1,释放操作
static int semaphore_v(void){
struct sembuf sem_b;
sem_b.sem_num=;
sem_b.sem_op=;
sem_b.sem_flg=SEM_UNDO;
if(semop(sem_id,&sem_b,)==-){
fprintf(stderr,"semaphore_v failed\n");
return ;
}
return ;
}

Linux学习笔记26——信号量的更多相关文章

  1. Linux 学习笔记

    Linux学习笔记 请切换web视图查看,表格比较大,方法:视图>>web板式视图 博客园不能粘贴图片吗 http://wenku.baidu.com/view/bda1c3067fd53 ...

  2. linux学习笔记2-linux的常用命令

    第一篇博客:linux学习笔记1-ubuntu的安装与基本设置 之中,已经介绍了如何安装linux操作系统,以及一些基本的设置修改. 本篇博客主要介绍linux中的一些常用的终端命令 ======== ...

  3. linux学习笔记2 - linux常用命令

    转载请标注原链接:http://www.cnblogs.com/xczyd/p/5543731.html 第一篇博客:linux学习笔记1-ubuntu的安装与基本设置 之中,已经介绍了如何安装lin ...

  4. Linux 学习笔记之超详细基础linux命令 Part 13

    Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122 ---------------------------------接Part 12---------------- ...

  5. Linux 学习笔记之超详细基础linux命令 Part 7

    Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122 ---------------------------------接Part 6----------------- ...

  6. Linux 学习笔记之超详细基础linux命令 Part 1

    Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122   说明:主要是在REHL Server 6操作系统下进行的测试 --字符界面虚拟终端与图形界面之间的切 方法:[ ...

  7. Intel® Media SDK Media Samples Linux 学习笔记(转)

    最近折腾intel media sdk,主要硬件平台是在HD4600的核显上进行测试,intel media sdk是intel提供的一种基于核显的硬件编解码的解决方案,之前已经有使用ffmpeg进行 ...

  8. Linux学习笔记(一)2015.4.13

    研究生由单片机转Linux学习 首先安装VMware虚拟机,用的是VMware 10.0 在VMware 10.0上安装视频上推荐的Red Hat Linux 5 安装后正式进入Linux学习 笔记1 ...

  9. 20160127 linux 学习笔记

    Linux学习笔记第一天 Linux基本介绍 Linux的起源和发展: 简单说linux是一种操作系统,可以安装在包括服务器.个人电脑,乃至PDA.手机.打印机等各类设备中. 起源: Linux起源于 ...

随机推荐

  1. C#实现从数据库读取数据到Excel

    用第三方组件:NPOI来实现 先去官网:http://npoi.codeplex.com/下载需要引入dll(可以选择.net2.0或者.net4.0的dll),然后在网站中添加引用.使用 NPOI ...

  2. C#中方法的参数修饰符

    做项目久了,有的时候真的需要静下心来认真的总结一下自己所用到的技术,而不是每天依葫芦画瓢,每天忙忙碌碌,到头来不知道自己忙了个啥,学了什么,自己到底掌握了多少知识.所以我想回顾一下C#的基础知识,把重 ...

  3. [Mime] MimeEntity--MimeEntity Mime实体帮助类 (转载)

    点击下载 MimeEntity.rar 这个类是关于Mime实体的类看下面代码吧 /// <summary> /// 类说明:Assistant /// 编 码 人:苏飞 /// 联系方式 ...

  4. Android混淆那些事儿

    博客: 安卓之家 微博: 追风917 CSDN: 蒋朋的家 简书: 追风917 博客园:追风917 # Android混淆 Android混淆是Android开发者经常使用的一种用于代码防止被反编译的 ...

  5. 关于AVD不能导入文件的解决方案

    安卓虚拟机导入文件时报以下异常: [2013-01-23 16:09:18 - ddms] transfer error: Read-only file system [2013-01-23 16:0 ...

  6. mvc 用户控件 ascx 获取 View 页面的值

    <%Html.RenderAction("AscxSideNav", "UI", new {itemName=ViewData["ItemNam ...

  7. (转)Android开发:性能最佳实践-管理应用内存

    翻自:http://developer.android.com/training/articles/memory.html 在任何软件开发环境中,RAM都是宝贵的资源,但在移动操作系统中更加珍贵.尽管 ...

  8. Windows phone 之自定义控件(补充)

    <UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x= ...

  9. 关于php的一些开源程序

    最好用的当属thinksns,目前更新到4.3.4, 社交型网站. 此网站提供大量源码,有时间可以去看看:http://down.admin5.com/

  10. 练习SignalR使用

    前言 随着Ajax越来越普遍的使用,前端页面跟后台服务也越来越密切的进行交互,实现前后端进行实时的消息传递尤为重要,一文件上传为例,现在普遍使用ajax上传然后通过flash进行文件进度的显示,这是目 ...