实践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");//将每个信号量都设初值为1union semun su;su.val = 1;for (int i = 0; i < 5; ++i)if (semctl(semid, i, SETVAL, su) == -1)err_exit("semctl SETVAL error");//创建四个子进程, 将每个进程的编号设定为nopid_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~4philosopher(no);return 0;
}

Linux IPC实践(12) --System V信号量(2)相关推荐

  1. Linux IPC实践(11) --System V信号量(1)

    信号量API #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget ...

  2. Linux IPC实践(9) --System V共享内存

    共享内存API #include <sys/ipc.h> #include <sys/shm.h>int shmget(key_t key, size_t size, int ...

  3. Linux IPC实践(6) --System V消息队列(3)

    消息队列综合案例 消息队列实现回射客户/服务器 server进程接收时, 指定msgtyp为0, 从队首不断接收消息 server进程发送时, 将mtype指定为接收到的client进程的pid cl ...

  4. Linux IPC实践(13) --System V IPC综合实践

    实践:实现一个先进先出的共享内存shmfifo 使用消息队列即可实现消息的先进先出(FIFO), 但是使用共享内存实现消息的先进先出则更加快速; 我们首先完成C语言版本的shmfifo(基于过程调用) ...

  5. Linux IPC实践(4) --System V消息队列(1)

    消息队列概述 消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法(仅局限于本机); 每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值. 消息队列也有管道一样的不足:  ...

  6. Linux IPC实践(5) --System V消息队列(2)

    消息发送/接收API msgsnd函数 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 参数 msgid: 由ms ...

  7. linux进程间通信:system V 信号量 生产者和消费者模型编程案例

    生产者和消费者模型: 有若干个缓冲区,生产者不断向里填数据,消费者不断从中取数据 两者不冲突的前提: 缓冲区有若干个,且是固定大小,生产者和消费者各有若干个 生产者向缓冲区中填数据前需要判断缓冲区是否 ...

  8. linux 内核信号量与用户态信号量(system v,信号量在Linux多线程机制中的应用

    [摘 要]本文以信号量原理为基础,重点阐述信号量在Linux多线程同步机制中的实现特色. [关键词]信号量:Linux:多线程:同步 1 信号量 1965年E. W. Dijkstra首次提出信号量的 ...

  9. Linux进程间通信三 System V 信号量简介与示例

    1. System V信号量简介 SystemV信号量主要用于解决生产者和消费者问题,一个信号量能够控制多个资源,说它是信号量集也不为过. 2. API接口介绍 2.1 创建或打开信号量集 #incl ...

最新文章

  1. 关于Webview带参访问服务器
  2. 如何判断一个对象是否是数组。
  3. python3 内置函数详解
  4. Missing binding node_modules/node-sass/vendor/darwin-x64-72/binding.node
  5. hdfs为什么要用block以及block大小的设置
  6. 2019中国手机品牌用户社交洞察报告:低价看配置 高价重颜值
  7. 小米互联通信服务_时隔六年,小米NFC碰碰贴复活,碰一下自动亮灯、联网、投屏...
  8. 【故障诊断分析】基于matlab概率神经网络柴油机故障诊断【含Matlab源码 1754期】
  9. 安卓实现tcp连接(安卓作为客户端,电脑作为服务端)
  10. 黑马java架构师课_【黑马精品】Java架构师实战训练营
  11. [译] Vue 最黑暗的一天
  12. python高级编程书籍推荐_Python书籍推荐
  13. oracle多个参数查询,Oracle 多参数查询语句
  14. 如何用css写出一个三角形
  15. 蚁群算法(ACO)最短路径规划(MATLAB)
  16. 医院应如何有效实施迅速合理的安全疏散系统
  17. java domino 单点登录_Domino单点登录LTPAtoken生成原理
  18. DSm安装mysql_黑群辉DSM6.17安装图文教程 - 诗风个人博客
  19. javascript——小方块运动
  20. PHP获取本周的起止时间

热门文章

  1. 计组之存储系统:1、存储系统的概念与基本组成(层次、分类、性能指标、基本结构、寻址)
  2. Python 参数传入sys.argv和getopt.getopt()的用法
  3. Centos7 修改防火墙,开放端口、转发端口
  4. 《明日方舟》Python版公开招募工具
  5. foreach的 多种用法
  6. K线理论--单根K线形态
  7. DP-访问者模式(Visitor Pattern)
  8. 大数据如何促进经济增长?中国优势及应对 | 互联网经济学
  9. 网易云音乐评论催泪刷屏?我用Python抓取了1008328条热评告诉你为什么!
  10. Modbus协议模型