最近学习了操作系统的并发;以下是关于进程间实现并发,通信的两个方法。

例子:

求100000个浮点数的和。要求:

(1)随机生成100000个浮点数(父进程)。

(2)然后创建4个后代进程,分别求25000个浮点数的和。

(3)父进程对4个后代进程的结果求和。

(4)每个子进程在屏幕上以格式“(ID_k) Child_k sum: XXX”打印信息,

其中k的取值为1~4,代表子进程的编号,ID_k表示第k个子进程的ID,XXX是该子进程计算的结果。

(5)父进程在屏幕上以格式 “(ID)Parent direct sum:YYY, sum from children: ZZZ”打印信息,

其中ID表示父进程的ID,YYY为直接由100000个随机数求和的值,ZZZ为把4个子进程的结果相加的值。

1:利用管道进行进程间的通信

用到下列函数

pipe() from unistd.h

sleep()

write(), read()

fork(); //创建子进程

管道只能用于具有亲缘关系的进程,可以将其看作一个文件,但有别于普通的文件, 管道一次只可以被一个进程访问,能实现互斥;

pipe(int fd[] ), 其参数为长度为2的int数组,分别代表读端fd[0], 写端fd[1], 在创建管道后,f d[0],fd[1]成为文件描述符;

写入(write)管道一端fd[1]的数据,在管道的另一端fd[0]可以被进程读取(read);

代码在这里

2:利用共享内存实现通信, 信号量实现互斥

共享内存使用了以下函数:

int shm_open(const char *name, int oflag, mode_t mode);  //创建或打开共享内存, 返回文件描述符

int ftruncate(int fd, off_t FILE_SIZE);  //调整共享内存空间大小

void*mmap ( void * addr , size_t len , int prot , int flags , int fd , off_t offset ) //将文件映射到进程的地址空间,返回指向地址空间的指针

int munmap(void *start, size_t length); //解除地址映射

int shm_unlink(const char *name); //删除shm_open()创建的共享内存

函数具体用法,可见链接,讲述的很详细了;

具体思路:

一:实现进程间的通信,无非就是各进程间数据的交流,传输;

1、shm_open()函数是创建或打开一个已存在(唯一的name)的共享内存,返回文件描述符,可以看作是创建或打开了一个文件,说法不同而已

2、ftruncate()函数用于指定文件(fd)有多大

3、关键步骤就是mmap(),它将指定的文件(fd)或其他对象映射到内存, 得到可以直接操作的指针对象,不需调用write, read等

4、然后就是在使用完成后需要解除映射munmap(), 和删除创建的共享内存(name)shm_unlink(),; 对于做打开共享内存操作的进程,也需要执行这些操作(1,2,3,4)

二:然后使用信号量实现互斥:

互斥的意思为:当一个进程在临界区访问共享资源时,其他进程不能进入该临界区访问任何共享资源

临界区代表进程将访问共享资源的一段代码

当我们在向共享区写入数据时,显然不想多个进程同时访问,因为会造成不必要的麻烦,就需要信号量来实现这种互斥的机制

sem_t *sem_open(const char *name,int oflag, mode_t mode,unsigned int value)  //创建或打开一个存在的(name)信号量

int sem_wait(sem_t *sem) // 使信号量(value)减1,若信号量小于0,则阻塞执行semwait()的进程

临界区代码一般存在于这两个调用之间,比如:当前进程向共享区写数据,如受到sem_wait阻塞,表示资源已经用尽或其他进程正在访问,需等待

int sem_post(sem_t *sem) // 当前进程离开临界区时,使信号量(value)加1,

int sem_unlink(count char *name) //删除信号量

函数具体用法,可见链接,讲述的很详细了;

代码在这里

需要注意的是:

1:在使用共享内存和信号量时要注意,有些调用是使用的共享内存和信号量的name, 但有些是使用的创建或打开他们的返回值(fd和sem_t*)

2:如在子进程创建之前,父进程已创建了共享内存或信号量,则子进程无需在进行打开操作,可直接使用

C实现进程间通信(管道; 共享内存,信号量)的更多相关文章

  1. Linux环境进程间通信(五): 共享内存(下)

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

  2. Linux环境进程间通信(五): 共享内存(上)

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

  3. Linux进程IPC浅析[进程间通信SystemV共享内存]

    Linux进程IPC浅析[进程间通信SystemV共享内存] 共享内存概念,概述 共享内存的相关函数 共享内存概念,概述: 共享内存区域是被多个进程共享的一部分物理内存 多个进程都可把该共享内存映射到 ...

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

    Linux进程间通信-使用共享内存 转自: https://blog.csdn.net/ljianhui/article/details/10253345 下面将讲解进程间通信的另一种方式,使用共享内 ...

  5. 浅析Linux下进程间通信:共享内存

    浅析Linux下进程间通信:共享内存 共享内存允许两个或多个进程共享一给定的存储区.因为数据不需要在客户进程和服务器进程之间复制,所以它是最快的一种IPC.使用共享内存要注意的是,多个进程之间对一给定 ...

  6. 进程间通信机制(管道、信号、共享内存/信号量/消息队列)、线程间通信机制(互斥锁、条件变量、posix匿名信号量)

    注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料如<linux内核完全剖析>.<linux c 编程一站式学习>等,只是为了更好 ...

  7. Linux进程间通信 共享内存+信号量+简单样例

    每个进程都有着自己独立的地址空间,比方程序之前申请了一块内存.当调用fork函数之后.父进程和子进程所使用的是不同的内存. 因此进程间的通信,不像线程间通信那么简单.可是共享内存编程接口能够让一个进程 ...

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

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

  9. Linux进程间通信——使用共享内存(转)

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

  10. Linux进程间通信(四) - 共享内存

    共享内存的优势 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝.对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只 ...

随机推荐

  1. C. Fountains

    \(整体思路没错,但是我貌似太麻烦了.......\) \(分情况讨论\) \(Ⅰ.coin和diamond各选一个物品,这个简单\) \(Ⅱ.在coin中选两个或者在diamond选两个\) \(开 ...

  2. 区间dp C - Two Rabbits

    C - Two Rabbits 这个题目的意思是,n块石头围一圈.一只兔子顺时针,一只兔子逆时针(限制在一圈的范围内). 这个题目我觉得还比较难,不太好想,不过后来lj大佬给了我一点点提示,因为是需要 ...

  3. 面试官:你说你懂动态代理,那你知道为什么JDK中的代理类都要继承Proxy吗?

    之前我已经写过了关于动态代理的两篇文章,本来以为这块应该没啥问题,没想到今天又被难住了- 太难了!!! 之前文章的链接: 动态代理学习(一)自己动手模拟JDK动态代理. 动态代理学习(二)JDK动态代 ...

  4. node能做的性能优化

    开发中,我们就离不开性能优化,那么在使用node开发的时候,我们可以使用那些代码来优化性能呢 一.释放内存 当node运行检测到错误的时候,释放掉内存 http.get(str,(res)=>{ ...

  5. EEGLAB-批量处理.dat数据及保存脑电地形图

    步骤 1.先在图形界面操作一遍准备做的操作. 2.在命令行窗口输入 EEG.history 获取刚刚操作都用到哪些语句. 3.稍加修改即可以写一个批量化函数来读取生成数据. 4.在 EEGLAB\ee ...

  6. QtCreator MSVC 搭建 Debugger

    QtCreatorForWindows搭建Debugger QtCreator for windows选择mingw或者msvc: qt-opensource-windows-x86-msvc2015 ...

  7. Git使用教程之新手也能看懂(一)

    首先我写这篇文章的初衷是因为 有一段时间没用Git了,现在突然用起来,很多命令都忘记了,导致去上网查了各种资料和文档(其中廖雪峰老师的文章给我的帮助很大,非常感谢!),花费了大量的时间,等于是又重新学 ...

  8. python语法学习第十天--魔法方法

    魔法方法二!!! 属性访问:在对属性任何操作时,都会调用   有关属性 __getattr__(self, name) 定义当用户试图获取一个不存在的属性时的行为 __getattribute__(s ...

  9. Universalimageloader 原图片大小获取

    Universalimageloader1.9.5上还没有对外提供获取图片的原大小功能,如果需要获取图片的源大小,可参考stackoverflow上的解决办法 stackoverflow地址 主要实现 ...

  10. Mockito如何mock一条链式调用

    在写单元测试的时候,不免可能需要mock一些对象出来,并且mock一些方法调用去返回一个自己想要的对象.一般的使用是这样的: FinalPumpkin pumpkin = mock(FinalPump ...