进程间的通讯与同步

本文详细介绍了进程间通信的几种方式,包括管道(有名管道和无名管道)、信号量、共享内存和消息队列,并对比了它们的特点。接着讨论了进程、线程的同步机制,如信号量、互斥锁、读写锁和条件变量,以及同步和异步、阻塞和非阻塞的概念。文章还提到了竞争、饥饿和死锁的问题。

一、进程之间的通信机制

首先进程的通讯方式有这么几种:管道、信号、共享内存、消息队列、套接字。

管道:分为有名管道和无名管道。

有名管道:用于任意进程之间的通讯 。    其接口 mkfifo/mkfifo()。有名管道是有名有形的,Linux中为其设立了一个专门的特殊的文件系统 --管道文件,它存在于文件系统中,任何进程可以在任何时候通过有名管道的路径和文件名来访问管道。但是在磁盘上其只是一个节点,而文件的数据还是存在内存缓冲页面中,和无名管道一样。

无名管道:用于父子进程之间的通讯。      其接口 pipe()。无名管道不属于任何文件系统,只存在于内存中,它是无名无形的,可以把它看作是一种特殊的文件,通过使用普通文件的read()、write()函数对管道进行操作。

******

多线程是可以对管道同时进行写操作的,但是会出现多个进程交替写入管道的现象。形成这样的原因在于管道本身的实现机制。通过双指针实现的,是不会出现数据覆盖的现象。但是仍是需要同步的,否则会出现数据混乱。

        

若头指针等于尾指针,则可判管道为满。为满写操作会阻塞。(可设置为非阻塞,接口会返回-1)

若尾指针等于头指针,则可判管道为空。为空读操作会阻塞。

******

管道的通讯方式:半双工。

操作管道:读端和写端必须都存在,如果写端关闭,读完之后会返回0。如果读端关闭,写操作会触发异常SIGPIPE。

信号量:简单来理解,其就是一个特殊的变量,通过对其进行原子的加减操作来控制多进程对于临界资源的访问。

这里又牵扯到一个概念,临界资源是什么?

临界资源:同一时刻只允许一个进程(线程)访问的资源。

临界区:访问临界资源的代码段。

对于信号量而言,它还有一个定义。

若取值为  0或者1   称其为二进制信号量。

若取值为    >1          称其为计数信号量。

在Linux下信号量是这么被定义的可以对比着理解一下,信号量是一种睡眠锁。如果有一个任务正在试图获得一个已经被占用的信号量时,信号量会将其推进一个等待队列,然后让其睡眠。这时的处理器能重获自由,去干别的事,等到该信号量被释放之后,处于等待队列的那个进程就被唤醒,然后执行。

共享内存:共享内存顾名思义,就是多个进程共享的内存块。共享内存的实现是通过讲多个进程的部份虚拟地址空间映射到同一块物理内存上就达到了共享的目的。

                                         

但是,使用共享内存的时候切记需要同步,否则会造成读写冲突或是脏读。

消息队列:是一种存在于内存上的数据结构,由内核维护的。也就是存在在内存上用来存放进进程之间通信信息的队列,这个数据结构是可以脱离进程而存在的,也就是说,发送方进程在往消息队列里存放数据块后就可以直接走人了,而接受方也不像管道一样必须等待着发送方发数据,想拿的时候拿就可以了。

            

消息队列与管道的对比:

1.管道是跟随进程的,消息队列是跟随内核的,也就是说进程结束之后,管道就死了,但是消息队列还会存在(除非显示调用函数销毁)

2.管道是文件,文件节点是存放在存放在磁盘上的,因此访问速度慢,消息队列是数据结构,存放在内存,访问速度快。

3.管道是数据流式存取(数据流式存取就会导致类似于“粘包”的问题),消息队列是数据块式存取。

4.管道的开销机制大。每个管道都要浪费一个文件描述符。

二、进程、线程之间的同步机制

首先,在谈及进程与线程的同步之前,得先明确一个概念就是,什么是同步(对临界资源访问的控制),还有另一个同步(数据的通讯方式),异步,阻塞,非阻塞这些词的意义得搞清楚。

先来说说同步异步的这个同步是啥意思。

同步(数据的通讯方式):在发出一个调用之后,等待结果产生再返回。

异步:在发出一个调用之后,不等待,立即返回,等到结果产生之后通知调用方返回。

阻塞:在发出一个调用之后,在结果出来之前,程序挂起,结果产生之后返回。

非阻塞:在发出一个调用之后,立即返回,无论结果如何。

同步(对临界资源访问的控制):通俗来讲在多线程或多进程下保证程序不会出错。对于竞争资源保证在某一时刻只有单个进程或线程访问。

同步机制:信号量、互斥锁、读写锁、条件变量。

互斥锁:简单来理解就是,一个进程在拿到锁之后,相当于就是拿到了进入访问临界资源的钥匙,而其他进程想要进入临界区就得等这个线程释放锁,并或得之后才可以访问。

读写锁:这么理解,读和读是可以的,读和写是互斥的,写和写是互斥的。换言之,某个进程获得了读锁在对临界资源进行读操作,这是其他进程是可以获取读锁对临界资源进行读操作的。但是想要获取写锁是会被阻塞的。而某个进程获得了写锁,那么其他进程获取读锁和写锁都会被阻塞。书上的说法是独占和共享,我理解的是独占就是写锁,共享就是读锁。

条件变量:可以这么理解就是一个条件,条件满足进程可执行,条件不满足进程阻塞。相当于一个栅栏,栅栏里有一群二哈趴在上面等着拆家呢(进程被条件变量阻塞),当主人允许开栅栏的时候(即条件满足的时候),狗就跑出来拆家了(即进程恢复运行)。

*******************************

竞争和饥饿:在多个进程运行的时候自然会出现竞争的状态(竞争cpu,竞争锁),那么这就会导致另一种进程状态饥饿,假设当进程1在释放资源后被进程2争取到,而进程2在释放之后又被进程1所拿到,循环下去之外的进程就处于无资源可拿的状态,称为饥饿状态。

竞争和死锁:举个简单的例子,进程1和2都需要两个资源,进程1竞争到了其中一个,进程2竞争到了其中的另一个,两个进程都因为没拿到另一份资源而阻塞着无法释放,导致死锁。

********************************

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值