春节过去了,真的过去一年了。在公司待了快一年了。2016希望自己变得越来越好。

ps:上面那句话是年前写的,中间隔了那么久,自己也变懒了。

一、信号量

1,信号量本质是一个计数器,控制访问共享资源的最大并行进程总数。(和信号有很大的区别)

2,信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有。
   信号量的值为正的时候,说明它空闲。所测试的线程可以锁定而使用它。若为0,说明它被占用,测试的线程要进入睡眠队列中,等待被唤醒。

3,信号量分类:Linux提供两种信号量:
(1) 内核信号量,由内核控制路径使用
(2) 用户态进程使用的信号量,这种信号量又分为POSIX信号量和SYSTEMV信号量。
   POSIX信号量又分为有名信号量和无名信号量。
    有名信号量,其值保存在文件中, 所以它可以用于线程也可以用于进程间的同步。无名信号量,其值保存在内存中。

干货来源:  http://blog.csdn.net/qinxiongxu/article/details/7830537

4,最简单的信号量是只能取0和1的变量,这也是信号量最常见的一种形式,叫做二进制信号量。

  而可以取多个正整数的信号量被称为通用信号量。这里主要讨论二进制信号量。

5,使用方法

  使用时给其一个初始值,假如该资源允许同时两个进程使用,初始值就设置为2,有一个进程使用该资源计数-1(原子操作),有一个进程放弃使用该资源计数+1(原子操作)。如果计数为0,不允许新的进程来访问资源,新的进程阻塞等待,直到计数重新大于0解除阻塞。
  如果有多个资源需要控制访问,就需要多个信号量,把多个信号量存入数组中,这个数组就叫信号量集。

二,编程实现

参考: http://blog.csdn.net/ljianhui/article/details/10243617    其实就是用这篇博客的。

这里用的是二进制信号量,初始值是1,最多允许1个进程获取信号量。

这个例子采用两个相同的程序往终端输出字符,根据命令行参数加以区分。

#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<sys/sem.h> union semun
{
int val;
struct semid_ds *buf;
unsigned short *arry;
}; static int sem_id = ;
static int set_semvalue();
static void del_semvalue();
static int semaphore_p();
static int semaphore_v(); int main(int argc, char **argv)
{
char message = 'x';
int i = ;
// 创建信号量
sem_id = semget((key_t), , |IPC_CREAT); if(argc > )
{
// 程序第一次调用,初始化信号量
if(!set_semvalue())
{
fprintf(stderr, "Failed Init semaphore\n");
exit(EXIT_FAILURE);
} // 设置输出到屏幕中的信息
message = argv[][];
sleep();
} for(i = ; i < ; i++)
{
if(!semaphore_p()) // 进入临界区
{
exit(EXIT_FAILURE);
} printf("%c", message);
fflush(stdout); // 清理缓冲区
sleep(rand() % ); // 休眠随机时间
printf("%c", message);
fflush(stdout); if(!semaphore_v()) // 离开临界区
{
exit(EXIT_FAILURE);
}
sleep(rand() % ); // 休眠随机时间
} sleep();
printf("\n %d - finished\n", getpid()); if(argc > )
{
sleep();
del_semvalue();
} exit(EXIT_SUCCESS);
} // 初始化信号量
static int set_semvalue()
{
union semun sem_union;
sem_union.val = ;
if(- == semctl(sem_id, , SETVAL, sem_union))
{
return ;
}
return ;
} // 删除信号量
static void del_semvalue()
{
union semun sem_union;
if(- == semctl(sem_id, , IPC_RMID, sem_union))
{
fprintf(stderr, "Failed delete semphore\n");
}
} // 对信号量-1操作,即等待P(sv)
static int semaphore_p()
{
struct sembuf sem_b;
sem_b.sem_num = ;
sem_b.sem_op = -; // P()
sem_b.sem_flg = SEM_UNDO; if(- == semop(sem_id, &sem_b, ))
{
fprintf(stderr, "Failed semaphore_p()\n");
return ;
} return ;
} // 释放操作, +1, 发送信号V(sv)
static int semaphore_v()
{
struct sembuf sem_b;
sem_b.sem_num = ;
sem_b.sem_op = ; // P()
sem_b.sem_flg = SEM_UNDO; if(- == semop(sem_id, &sem_b, ))
{
fprintf(stderr, "Failed semaphore_v()\n");
return ;
} return ;
}

运行结果:

分析:第一次运行 一个程序打印 X,另一个打印 1。

第二次运行 一个打印1  , 一个打印2。

因为每个程序都在其进入临界区后和离开临界区前打印一个字符,所以每个字符都应该成对出现。

一个进程在打印时,会先执行P操作,若没有打印完,也就是没有执行V操作。另一个进程要执行打印,也要进行P操作,这时候由于信号量的值为0,获取信号量失败,进程只能挂起自己。等另一个程序释放(V操作)才能打印。

任何时刻只有一个进程得到了信号量,只有一个进程在执行打印

总结:

信号量是一个特殊的变量,程序对其访问都是原子操作,且只允许对它进行等待(即P(信号变量))和发送(即V(信号变量))信息操作。

我们通常通过信号来解决多个进程对同一资源的访问竞争的问题,使在任一时刻只能有一个执行线程访问代码的临界区域,

也可以说它是协调进程间的对同一资源的访问权,也就是用于同步进程的。

Linux进程间通信之信号量的更多相关文章

  1. Linux进程间通信——使用信号量

    这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信——使用信号.下面 ...

  2. Linux进程间通信--使用信号量【转】

    本文转载自:http://blog.csdn.net/ljianhui/article/details/10243617 这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号 ...

  3. Linux进程间通信——使用信号量(转)

    这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信——使用信号.下面 ...

  4. Linux进程间通信:管道,信号量,消息队列,信号,共享内存,套接字

    Linux下的进程通信手段基本上是从UNIX平台上的进程通信手段继承而来的.而对UNIX发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间 ...

  5. Linux进程间通信——使用信号量【转】

    本文转载自:http://blog.csdn.net/ljianhui/article/details/10243617 这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号 ...

  6. Linux -- 进程间通信之信号量

    基本概念简述 多个线程同时访问一个共享数据,很可能造成恶劣的后果:为了保证数据访问资源的正确性和安全性,需要对线程进行"同步" (Linux下所有的执行实体都称为任务(task), ...

  7. Linux进程间通信(六):共享内存 shmget()、shmat()、shmdt()、shmctl()

    下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式 ...

  8. Linux进程间通信——使用共享内存

    一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存. ...

  9. Linux多线程--使用信号量同步线程【转】

    本文转载自:http://blog.csdn.net/ljianhui/article/details/10813469 信号量.同步这些名词在进程间通信时就已经说过,在这里它们的意思是相同的,只不过 ...

随机推荐

  1. R语言数据的输入

    键盘输入 调用edit函数,比如我们要让用户输入一个长度为5的向量并赋值给变量a,那么可以: a<-vector() a<-edit(a) 另外也可以用函数fix来直接编辑变量,而不需要再 ...

  2. 10个开源的PHP网站内容管理系统

    1. DEDE -这是一款国内开源的cms,作者是一个个人,能做出如此功能的cms,是相当不错的.2007版功能十分强大,希望能改善之前数据量一大,更新静态页就很慢的缺点.因为开源,有较多的玩家和拥护 ...

  3. SQL Server求解最近多少销售记录的销售额占比总销售额的指定比例

    看园中SQL Server大V潇潇隐者的博文,发现一边文就是描述了如标题描述的问题.   具体的问题描述我通过潇潇隐者的博文的截图来阐释: 注意:如果以上截取有所侵权,也请作者告知,再次感谢.   当 ...

  4. x01.Game.CubeRun: 风一样的女子

    1.题解 小孩学英语比较有意思,Monkey three => 猴三,风一样的女子 => 风 Girl.诸如此类不是重点,重点是一花一世界,一草一天堂.花花草草,纷纷扰扰.大千世界,当别具 ...

  5. Centos6.6下安装MySQL5.6

    1.先查看本机上已经安装的MySQL rpm –qa | grep -i mysql 如果存在信息说明已经安装MySQL 需要完全卸载以前的MySQL yum remove mysql mysql-s ...

  6. NopCommerce 关于Customer的会员类别及会员价处理 的尝试途径

    示例效果: 当Customer是某个会员级别或内部员工时, 购物结算时享受一定的折扣: 相关设定如下: Step1.新增会员类别    Admin - Customers - Customer rol ...

  7. 记一次惨痛的线上bug

    讲述背景,刚入职新公司2个月的时候,接手一个红包系统.资历尚浅,对业务也不是很熟悉.公司开发新的平台,需要使用红包功能来进行推广,按照产品的需求,进行开发...然而,问题就出在这里,红包接口比较陈旧, ...

  8. openjudge2989糖果[DP 01背包可行性]

    openjudge2989糖果 总时间限制:  1000ms 内存限制:  65536kB 描述 由于在维护世界和平的事务中做出巨大贡献,Dzx被赠予糖果公司2010年5月23日当天无限量糖果免费优惠 ...

  9. 关于OAUTH2.0的极品好文

    Web Server Flow: web ServerFlow是把oauth1.0的三个步骤缩略为两个步骤 首先这个是适合有server的第三方使用的. 1客户端http请求authorize 2服务 ...

  10. SQL 2008 windows登录失败,错误18456, 更正

    可能的原因:密码有效性验证失败.该密码太短,不符合 Windows 策略要求. 本地设置可能被域设置覆盖.而域设置中指定了安全策略,密码必须有一定的复杂性.重新更改sa密码. 第一步.以windows ...