面试之线程与进程

进程间通信与线程间通信

一、概念

进程:系统进行资源分配和调度的一个独立单位。

线程:进程的一个实体,是CPU调度和分派的基本单位。可与同属一个进程的其他线程共享进程所拥有的全部资源。

二、进程间通信方式

1.管道(PIPE)

通常指无名管道,是一种最基本的IPC机制,作用于有血缘关系的进程之间,完成数据传递。

1)管道的原理: 管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现。

① 其本质是一个伪文件(实为内核缓冲区)
② 由两个文件描述符引用,一个表示读端,一个表示写端。
③ 规定数据从管道的写端流入管道,从读端流出。

2)管道的局限性:

① 数据自己读不能自己写。
② 数据一旦被读走,便不在管道中存在,不可反复读取。
③ 由于管道采用半双工通信方式。因此,数据只能在一个方向上流动。
④ 只能在有公共祖先的进程间使用管道。

2.FIFO

也称为命名管道,它是一种文件类型,提供了一个路径名与之关联,以 FIFO 的文件形式存在于文件系统中。因此,通过 FIFO 不相关的进程也能交换数据。

1)FIFO的特性:

①FIFO 在文件系统中作为一个特殊的文件而存在,但 FIFO 中的内容却存放在内存中。
②当使用 FIFO 的进程退出后,FIFO 文件将继续保存在文件系统中以便以后使用。
③FIFO 有名字,不相关的进程可以通过打开命名管道进行通信。

2)FIFO的局限性:

客户端可以发请求到服务器,但前提是要知道一个公共的FIFO通道,对于实现服务器回传应答到客户端的问题,可以通过为每一个客户端创建一个专用的FIFO,来实现回传应答。但也有不足,服务器会同时应答成千上万个客户端,创建如此多的FIFO是否会使系统负载过大,相应的如何判断客户端是否因意外而崩溃成为难题,或者客户端不读取应答直接退出,所以服务器必须处理SIGPIPE信号,并做相应处理。

3.信号量

它不以传送数据为主要目的,主要是用来保护共享资源(信号量也属于临界资源),使得资源在一个时刻只有一个进程独享。因此,主要作为进程间以及同一个进程内不同线程之间的同步手段。

信号量的工作机制:

它常作为一种锁机制,防止某进程在访问资源时其它进程也访问该资源。可以直接理解成计数器(当然其实加锁的时候肯定不能这么简单,不只只是信号量了),信号量会有初值(>0),每当有进程申请使用信号量,通过一个P操作来对信号量进行-1操作,当计数器减到0的时候就说明没有资源了,其他进程要想访问就必须等待(具体怎么等还有说法,比如忙等待或者睡眠),当该进程执行完这段工作(我们称之为临界区)之后,就会执行V操作来对信号量进行+1操作。

4信号

信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

1)信号的原理:

A给B发送信号,B收到信号之前执行自己的代码,收到信号后,不管执行到程序的什么位置,都要暂停运行,去处理信号,处理完毕再继续执行。

与硬件中断类似——异步模式。但信号是软件层面上实现的中断,早期常被称为“软中断”。

2)信号的产生:

①硬件产生,从键盘敲入组合键发送一个信号,常用的Ctrl+C就可以给前台进程发送;
②进程发送(或者说是由软件产生),比如我们可以在shell进程下输入kill命令给一个进程发送信 号(命令:kill -信号标号 PID);
③异常,当异常的发生的时候肯定是会发送信号的。

3)信号的处理方式:

①执行默认动作;
②忽略(丢弃).即对信号不做任何处理;
③捕捉.定义信号处理函数,当信号发生时,执行相应的处理函数。

5.队列

消息队列是消息的链表,存放在内核中并由消息队列标识符标识.

1)队列的原理:

队列是UNIX下不同进程之间可实现共享资源的一种机制,UNIX允许不同进程将格式化的数据流以消息队列形式发送给任意进程.对消息队列具有操作权限的进程都可以使用msget完成对消息队列的操作控制.通过使用消息类型,进程可以按任何顺序读信息,或为消息安排优先级顺序.

2)队列的特性:

①发送带类型数据块。
②是全双工的,可双向通信。
③生命周期随内核,必须显式删除。

6.共享内存

共享内存是最快的IPC(进程间通信)方式,它是针对其它进程间通信方式运行效率低而专门设计的.它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步与通信.

1)共享内存的原理:
映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问.

2)优点:
我们可以看到使用共享内存进行进程之间的通信是非常方便的,而且函数的接口也比较简单,数据的共享还使进程间的数据不用传送,而是直接访问内存,加快了程序的效率。

3)缺点:
共享内存没有提供同步机制,这使得我们在使用共享内存进行进程之间的通信时,往往需要借助其他手段来保证进程之间的同步工作。

7.socket

socket,即套接字是一种通信机制,凭借这种机制,客户/服务器(即要进行通信的进程)系统的开发工作既可以在本地单机上进行,也可以跨网络进行。也就是说它可以让不在同一台计算机但通过网络连接计算机上的进程进行通信。也因为这样,套接字明确地将客户端和服务器区分开来。

基于流套接字的客户/服务器的工作流程:

使用socket进行进程通信的进程采用的客户/服务器系统是如何工作的呢?

1)服务器端

首先服务器应用程序用系统调用socket来创建一个套接字,它是系统分配给该服务器进程的类似文件描述符的资源,它不能与其他的进程共享。

接下来,服务器进程会给套接字起个名字,我们使用系统调用bind来给套接字命名。然后服务器进程就开始等待客户连接到这个套接字。

然后,系统调用listen来创建一个队列并将其用于存放来自客户的进入连接。

最后,服务器通过系统调用accept来接受客户的连接。它会创建一个与原有的命名套接不同的新套接字,这个套接字只用于与这个特定客户端进行通信,而命名套接字(即原先的套接字)则被保留下来继续处理来自其他客户的连接。

2)客户端

基于socket的客户端比服务器端简单,同样,客户应用程序首先调用socket来创建一个未命名的套接字,然后将服务器的命名套接字作为一个地址来调用connect与服务器建立连接。

一旦连接建立,我们就可以像使用底层的文件描述符那样用套接字来实现双向数据的通信。

三、进程间通信方式比较

进程间的通信根据通信内容可以划分为两种:即控制信息(消息)的传送与大批数据(数据)传送。有时也把进程间控制信息的交换称为低级通信,而把进程间大批量数据的交换称为高级通信。

通信方式通信内容特点
管道数据具有亲缘关系进程间通信,单向流动,只能承载无格式字节流以及缓冲区大小受限
FIFO数据允许无亲缘关系进程间的通信,单向流动,只能承载无格式字节流以及缓冲区大小受限
信号量同步多线程之间的同步
信号消息不涉及数据交换
队列消息消息队列中信息的复制需要额外消耗CPU的时间.不适宜于信息量大或操作频繁的场合
共享内存数据和消息针对消息缓冲的缺点改而利用内存缓冲区直接交换信息,无须复制,快捷、信息量大是其优点,缺点是不方便网络通信
socket数据和消息位于不同机器的IPC方式

四、线程间通信方式

线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。

1.全局变量

进程中的线程间内存共享,这是比较常用的通信方式和交互方式。
注:定义全局变量时最好使用volatile来定义,以防编译器对此变量进行优化。

2.Message消息机制

常用的Message通信的接口主要有两个:PostMessage和PostThreadMessage,
PostMessage为线程向主窗口发送消息。而PostThreadMessage是任意两个线程之间的通信接口。

3.CEvent对象

CEvent为MFC中的一个对象,可以通过对CEvent的触发状态进行改变,从而实现线程间的通信和同步。

五、总结

由于多线程共享地址空间和数据空间,所以多个线程间的通信是一个线程的数据可以直接提供给其他线程使用,而不必通过操作系统(也就是内核的调度)。

进程间的通信则不同,它的数据空间的独立性决定了它的通信相对比较复杂,需要通过操作系统。以前进程间的通信只能是单机版的,现在操作系统都继承了基于套接字(socket)的进程间的通信机制。这样进程间的通信就不局限于单台计算机了,实现了网络通信。

  • 8
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值