Linux IPC实践(12) --System V信号量(2)
实践1:信号量实现进程互斥
父子进程执行流程如下:
|
父进程 |
子进程 |
|
P |
P |
|
O(print) |
X(print) |
|
sleep |
sleep |
|
O(print) |
X(print) |
|
V |
V |
|
sleep |
sleep |
从图中可以看出, O或X总是成对出现的, 要么两个O, 要么两个X;
/**P,V原语实现父子进程互斥使用终端**/
// 程序代码
int main(int argc,char *argv[])
{
int semid = sem_create(IPC_PRIVATE);
sem_setval(semid, 1);
int count = 10;
pid_t pid = fork();
if (pid == -1)
err_exit("fork error");
else if (pid > 0) //子进程
{
srand(getpid());
while (count --)
{
sem_P(semid);
//临界区开始
cout << 'X';
fflush(stdout); //一定要加上ffflush, 因为中断是行缓冲的
sleep(rand()%3);
cout << 'X';
fflush(stdout);
//临界区结束
sem_V(semid);
sleep(rand()%3);
}
}
else //父进程
{
srand(getpid());
while (count --)
{
sem_P(semid);
//临界区开始
cout << 'O';
fflush(stdout);
sleep(rand()%3);
cout << 'O';
fflush(stdout);
//临界区结束
sem_V(semid);
sleep(rand()%3);
}
wait(NULL);
sem_delete(semid);
}
return 0;
}
实践2: 信号量集解决哲学家进餐问题
假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。吃东西的时候,他们就停止思考,思考的时候也停止吃东西。每两个哲学家之间有一只餐叉。因为用一只餐叉很难吃饭,所以假设哲学家必须用两只餐叉吃东西, 而且他们只能使用自己左右手边的那两只餐叉。
/**
解决的方法采用的是: 只有左右两个刀叉都能够使用时,才拿起两个刀叉
实现了有死锁和无死锁的两种形式的wait_2fork(见下)
**/
int semid;
//没有死锁的wait
void wait_2fork(unsigned short no)
{
unsigned short left = no;
unsigned short right = (no+1)%5;
struct sembuf sops[2] = {{left, -1, 0}, {right, -1, 0}};
//同时获取左右两把刀叉
if (semop(semid, sops, 2) == -1)
err_exit("wait_2fork error");
}
/*
//有死锁的wait
void wait_2fork(unsigned short no)
{
unsigned short left = no;
unsigned short right = (no+1)%5;
struct sembuf sops = {left, -1, 0};
//获取左边的刀叉
if (semop(semid, &sops, 1) == -1)
err_exit("wait_2fork error");
sleep(4); //沉睡几秒, 加速死锁的产生
sops.sem_num = right;
//获取右边的刀叉
if (semop(semid, &sops, 1) == -1)
err_exit("wait_2fork error");
}
*/
//释放两把刀叉
void signal_2fork(unsigned short no)
{
unsigned short left = no;
unsigned short right = (no+1)%5;
struct sembuf sops[2] = {{left, 1, 0}, {right, 1, 0}};
if (semop(semid, sops, 2) == -1)
err_exit("signal_2fork error");
}
//哲学家
void philosopher(unsigned short no)
{
srand(time(NULL));
while (true)
{
cout << no << " is thinking" << endl;
sleep(rand()%5+1);
cout << no << " is hunger" << endl;
wait_2fork(no); //获取两把刀叉
//进餐
cout << "++ " << no << " is eating" << endl;
sleep(rand()%5+1);
signal_2fork(no);//释放两把刀叉
}
}
int main()
{
// 创建一个信号量集: 里面包含5个信号量
semid = semget(IPC_PRIVATE, 5, IPC_CREAT|0666);
if (semid == -1)
err_exit("semget error");
//将每个信号量都设初值为1
union semun su;
su.val = 1;
for (int i = 0; i < 5; ++i)
if (semctl(semid, i, SETVAL, su) == -1)
err_exit("semctl SETVAL error");
//创建四个子进程, 将每个进程的编号设定为no
pid_t pid;
unsigned short no = 0;
for (unsigned short i = 0; i < 4; ++i)
{
pid = fork();
if (pid == -1)
err_exit("fork error");
else if (pid == 0)
{
no = i+1;
break;
}
}
// 最后五个进程(4个子进程+1个父进程)都会汇集到此处,
// 每个进程代表着一个哲学家,编号no: 0~4
philosopher(no);
return 0;
}
Linux IPC实践(12) --System V信号量(2)的更多相关文章
- Linux IPC实践(11) --System V信号量(1)
信号量API #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget ...
- Linux IPC实践(9) --System V共享内存
共享内存API #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int ...
- Linux IPC实践(6) --System V消息队列(3)
消息队列综合案例 消息队列实现回射客户/服务器 server进程接收时, 指定msgtyp为0, 从队首不断接收消息 server进程发送时, 将mtype指定为接收到的client进程的pid ...
- Linux IPC实践(13) --System V IPC综合实践
实践:实现一个先进先出的共享内存shmfifo 使用消息队列即可实现消息的先进先出(FIFO), 但是使用共享内存实现消息的先进先出则更加快速; 我们首先完成C语言版本的shmfifo(基于过程调用) ...
- Linux IPC实践(4) --System V消息队列(1)
消息队列概述 消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法(仅局限于本机); 每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值. 消息队列也有管道一样的不足: ...
- Linux IPC实践(5) --System V消息队列(2)
消息发送/接收API msgsnd函数 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 参数 msgid: 由ms ...
- linux网络编程之system v信号量(一)
今天起,学习信号量相关的知识,下面开始: 关于信号量,在前面已经介绍过了,这里回顾一下: 通过上面的描述,很容易就能想到信号量的一上数据结构: 下面再来回顾一下P.V原语: 所谓的原语就是指这段代码是 ...
- linux网络编程之system v信号量(二)
今天迎来元旦假期的最后一天了,过得好快~昨天跟小伙伴们在军都滑雪陪儿爽,虽说上了两回中级道都摔得异常的惨烈,但是在初级道上学习"s"转弯还是有一些小心得,可以在要往高手迈进的前提, ...
- Linux中的System V信号量
在进程同步,并发运行时,保证按序地访问共享资源是十分重要的.因此引入了临界区的概念,一次只能有一个线程进入临界区完成他的指令.而信号量(semaphore)的作用,类似于一个交通信号灯,它负责进程协作 ...
随机推荐
- WPF ListBox 获取listBoxItem
1.已知item的DataContext,获取ListBoxItem 1)ItemContainerGenerator.ContainerFromItem var selectedItem = Doc ...
- 360搜索引擎so自动收录php改写方案——适合phpcms等cms
360搜索引擎自动收录功能,官方提供了代码,带式,十分坑爹,没有提供批量提交入口,只是提供了一段js代码,关键是 一个js去下载另外一个js,document.write到文档,然后再 重复2遍如此工 ...
- 【已解决】IIS搭建 asp.net core 项目后 其他电脑访问不到资源文件
IIS搭建asp.net core 项目后,访问不到里面的资源文件(图片等),解决方法如下: 1.检查asp.net core发布文件中的资源文件是不是都放到了wwwroot名称的目录中. 2.检查a ...
- Do a web framework ourselves
step 1: from wsgiref.simple_server import make_server def application(environ, start_response): star ...
- Android Design Support Library使用详解——Snackbar
Google在2015 I/O大会上,给我们带来了更加详细的Material Design规范,同时也引入了Android Design Support Library,为我们提供了基于Materia ...
- OpenCV RGB2LAB执行效率测试
代码 #include <iostream> #include <vector> #include <opencv2/opencv.hpp> #define ERR ...
- Android隐式启动Activity可能存在的坑
转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 本篇文章,对隐式启动Activity再做分析. 有些人可能会说了, ...
- 初识Spring Boot框架(二)之DIY一个Spring Boot的自动配置
在上篇博客初识Spring Boot框架中我们初步见识了SpringBoot的方便之处,很多小伙伴可能也会好奇这个Spring Boot是怎么实现自动配置的,那么今天我就带小伙伴我们自己来实现一个简单 ...
- Shell脚本了解
一.什么是Shell Shell 是一个用C语言编写的程序,它是用户使用Linux的桥梁.Shell既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序,这个应用程序提供了一个界面, ...
- 2017京东校招面试回忆(已成功拿到offer)
一面 24日 晚上5:30-6:40 1 先说自己熟悉的领域 2 list的实现有什么? arraylist1.6 1.7区别 底层 linkedlist 底层是怎么实现的 单向还是双向 ...