前一篇文章概述了Linux 系统中信号量互斥编程,这篇文章正好是前一篇的姊妹篇----信号量同步。说它们是姊妹篇是因为它们都是利用了内核的信号量机制实现了进程间的通信。因为两者所解决的问题不同,因此它们使用的场景就会有所区别。

信号量互斥主要解决的问题是:进程间需要同时访问某种资源,但是它们对资源的操作会互相影响对方的操作结果,因此需要一种机制实现让进程在访问资源时能禁止其他进程访问相同的资源。而信号量同步则解决了另一个经典问题:生产者和消费者之间的协同工作问题。

首先描述一下生产者和消费者问题:进程A 负责生产产品(创建并写入文件),进程B 负责消费产品(复制文件),理想的流程是当进程A 创建并写好数据到文件以后,进程B就取走文件。但是两个进程运行时机的不确定往往让这个流程出现混乱,即进程A的生产工作还未完成(如只创建了文件但是没写入数据),进程B 就复制了文件,导致进程B 得到的是一个不完整的文件。事实上问题出现的原因就是两个进程间没有一种同步的机制。

信号量的提出就解决了这个问题。信号量的实现在前一篇文章中有详细介绍,这里只是指出运用信号量同步进程与互斥之间的不同,然后给出一个实例说明。

下面是笔者实现代码的思维导图:

与互斥不同的是,在给信号量赋初值时并不是赋值为1,而是赋值为0,并且在生产者中并没有获取信号量,而在消费者中也没有释放信号量。这样做是为了使两者的运行次序不会影响最后的结果。

可以分析:如果生产者程序先运行,它会依次创建并写入文件,假设此时消费者程序运行,但是此时信号量初值为0,因此消费者程序被挂起。当生产者程序执行完,释放信号量以后,消费者程序继续运行,最后得到正确的文件。

如果消费者程序先运行,它测试到信号量初值是0 ,因此直接被挂起,直到生产者程序运行完才继续运行,可知这样也能够得到正确的文件。

需要注意的是,在上图中的1.7 释放信号量里面,包含一个将初值置为0 的操作,这样是为了在下一次再运行这两个程序时,如果先运行消费者,初值仍然是0。

下面是笔者的测试代码:

生产者代码:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h> int main(int argc, char **argv)
{
int fd = ;
key_t key;
int semid;
struct sembuf ops;
//创建信号量集合
key = ftok("/home/application/semapthore",);
semid=semget(key,,IPC_CREAT); //将初值置为0
semctl(semid,,SETVAL,); //创建文件
fd = open("./product.txt",O_RDWR|O_CREAT,); //休息
sleep(); //写入数据
write(fd,"Product is finished!",); //关闭文件
close(fd); //释放信号量
ops.sem_num=;
ops.sem_op=;
ops.sem_flg = SEM_UNDO;
semop(semid,&ops,);
semctl(semid,,SETVAL,);
return ;
}

消费者代码;

#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h> int main(int argc,char **argv)
{ key_t key;
int semid;
struct sembuf ops;
//打开信号量集合
key = ftok("/home/application/semapthore",);
semid=semget(key,,IPC_CREAT);
//获取信号量
ops.sem_num = ;
ops.sem_op = -;
ops.sem_flg = SEM_UNDO;
semop(semid,&ops,); //消费文件
system("cp ./product.txt ./comsum/"); return ;
}

Linux 信号量同步编程的更多相关文章

  1. Linux信号量同步共享内存实验.

    Linux信号量同步共享内存实验. Linux信号量同步共享内存实验. 简述 程序流程 信号量和共享内存的系统函数 信号量系统函数及接口 共享内存系统函数及接口 写程序 读程序 简述 本文主要内容是自 ...

  2. Linux 信号量互斥编程

    所谓信号量,其实就是一个数字.内核给这个数字赋予一定的含义,让它等于不同的值时所表示的意义不同.这样就可以用它来标示某种资源是否正被使用.信号的分类其实挺多的,主要还是二值和计数器.这里讨论二值 现在 ...

  3. 转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)

    Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)   介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可 ...

  4. linux信号量之进程间同步

    概念 linux信号量: 允许多个线程同时进入临界区,可以用于进程间的同步. 和互斥锁(mutex)的区别: 互斥锁只允许一个线程进入临界区. 所在头文件: semaphore.h 主要函数 初始化函 ...

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

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

  6. Linux线程的信号量同步

    信号量和互斥锁(mutex)的区别:互斥锁只允许一个线程进入临界区,而信号量允许多个线程同时进入临界区. 不多做解释,要使用信号量同步,需要包含头文件semaphore.h. 主要用到的函数: int ...

  7. 【linux草鞋应用编程系列】_3_ 进程间通信

    一.进程间通信        linux下面提供了多种进程间通信的方法, 管道.信号.信号量.消息队列.共享内存.套接字等.下面我们分别 介绍管道.信号量.消息队列.共享内存.        信号和套 ...

  8. Linux内核同步机制

    http://blog.csdn.net/bullbat/article/details/7376424 Linux内核同步控制方法有很多,信号量.锁.原子量.RCU等等,不同的实现方法应用于不同的环 ...

  9. Linux下的编程实战【转】

    一篇比较不错的文章, 降到了 makefile make , gcc编译器,GDB调试器, Linux文件系统,Linux文件API,.C语言库函数(C库函数的文件操作实际上是独立于具体的操作系统平台 ...

随机推荐

  1. OpenCV学习(一)

    环境:OpenCV 2.4.4 VS2010 第一个Demo,显示一张图片 #include "opencv2/highgui/highgui.hpp" int main( int ...

  2. Linux I2C设备驱动编写(三)-实例分析AM3359

    TI-AM3359 I2C适配器实例分析 I2C Spec简述 特性: 兼容飞利浦I2C 2.1版本规格 支持标准模式(100K bits/s)和快速模式(400K bits/s) 多路接收.发送模式 ...

  3. DES加密,Tk写的简单的GUI

    # -*- coding: UTF-8 -*- from Tkinter import * from tkMessageBox import * ip = [ 58,50,42,34,26,18,10 ...

  4. Jquery- 错误消息"Date"未定义,"String"未定义

    在jquery的高版本(1.7-1.9)提示“String”未定义,稍低版本提示“Date”未定义错误 解决办法: 1.找到你发生错误的代码(即执行那条代码时发生的错误) 2.使用setTimeout ...

  5. mysql 加载文本数据

    可以配置导入哪几列,每个字段用什么隔开,每行用什么隔开,也可以单独设置某个字段的值. 详细看代码: LOAD DATA INFILE 'D:/aa.txt' INTO TABLE aa FIELDS ...

  6. 征服 Redis + Jedis + Spring (三)—— 列表操作【转】

    一开始以为Spring下操作哈希表,列表,真就是那么土.恍惚间发现“stringRedisTemplate.opsForList()”的强大,抓紧时间恶补下. 相关链接: 征服 Redis 征服 Re ...

  7. 通过strace 监控 fdatasync

    通过strace 监控 Redis AOF文件的系统调用 Redis中主要的AOF设置 「appendonly yes」 开启每次更新操作后进行日志记录 「appendfilename appendo ...

  8. 基于AFNetworking3.0网络封装

    概述 对于开发人员来说,学习网络层知识是必备的,任何一款App的开发,都需要到网络请求接口.很多朋友都还在使用原生的NSURLConnection一行一行地写,代码到处是,这样维护起来更困难了. 对于 ...

  9. vc++ 最小化到托盘的详细实现

    在VC++中,想实现将MFC最小化到系统托盘,需要调用NOTIFYICONDATA类,并注册相应的消息,以下详细讲解如何实现: 1.声明一个NOTIFYICONDATA类,也就是NOTIFYICOND ...

  10. Windows Server 2008 R2 域控制器部署指南

    一.域控制器安装步骤: 1.装 Windows Server 2008 R2并配置计算机名称和IP地址(见 附录一) 2.点击“开始”,在“搜索程序和文件”中输入Dcpromo.exe后按回车键: 3 ...