最近学习了操做系统的并发;如下是关于进程间实现并发,通讯的两个方法。html
例子:linux
求100000个浮点数的和。要求:git
(1)随机生成100000个浮点数(父进程)。github
(2)而后建立4个后代进程,分别求25000个浮点数的和。数组
(3)父进程对4个后代进程的结果求和。并发
(4)每一个子进程在屏幕上以格式“(ID_k) Child_k sum: XXX”打印信息,函数
其中k的取值为1~4,表明子进程的编号,ID_k表示第k个子进程的ID,XXX是该子进程计算的结果。post
(5)父进程在屏幕上以格式 “(ID)Parent direct sum:YYY, sum from children: ZZZ”打印信息,学习
其中ID表示父进程的ID,YYY为直接由100000个随机数求和的值,ZZZ为把4个子进程的结果相加的值。spa
1:利用管道进行进程间的通讯
用到下列函数
pipe() from unistd.h
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()建立的共享内存
函数具体用法,可见连接,讲述的很详细了;
具体思路:
一:实现进程间的通讯,无非就是各进程间数据的交流,传输;
一、shm_open()函数是建立或打开一个已存在(惟一的name)的共享内存,返回文件描述符,能够看做是建立或打开了一个文件,说法不一样而已
二、ftruncate()函数用于指定文件(fd)有多大
三、关键步骤就是mmap(),它将指定的文件(fd)或其余对象映射到内存, 获得能够直接操做的指针对象,不需调用write, read等
四、而后就是在使用完成后须要解除映射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:如在子进程建立以前,父进程已建立了共享内存或信号量,则子进程无需在进行打开操做,可直接使用