1.什么是进程?什么是线程?进程和线程的区别?
进程:资源分配和管理的基本单位
线程:程序执行的最小单位。
区别:
地址空间: 同一进程的所有线程共享本进程的地址空间,而不同的进程之间的地址空间是独立的。
资源拥有: 同一进程的所有线程共享本进程的资源,如内存,CPU,IO等。进程之间的资源是独立的,无法共享。
执行过程:每一个进程就是一个可执行的应用程序,每一个独立的进程都有一个程序执行的入口,顺序执行序列。但是线程不能够独立执行,必须依存在应用程序中,由程序的多线程控制机制进行控制。
健壮性: 因为同一进程的所以线程共享此线程的资源,因此当一个线程发生崩溃时,此进程也会发生崩溃。 但是各个进程之间的资源是独立的,因此当一个进程崩溃时,不会影响其他进程。因此进程比线程健壮。
2.并行和并发的区别?
如图:
并行:指在同一时刻,有多条指令在多个处理器上同时执行
并发:指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮流执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个进程快速交替的执行。
相同点:
并发和并行的目标都是最大化CPU的使用率,将cpu的性能充分压榨出来。
不同点:
(1)并行在多处理器系统中存在,而并发可以在单处理器和多处理器系统中都存在
(2)并行要求程序能够同时执行多个操作,而并发只是要求程序“看着像是”同时执行多个操作,其实是交替执行。
3.什么是协程?
协程:是一个可以在某个地方挂起的特殊函数,并且可以重新在挂起处继续运行
一个进程可以包含多个线程,一个线程也可以包含多个协程,无论有多少个CPU(核),一个线程内的多个协程的运行是串行的,所以协程适合I/O 阻塞型
协程是由程序控制的,并且能保留上一次调用的状态
4.进程和线程的切换流程?
拓展:
虚拟内存是操作系统为每个进程提供的一种抽象,每个进程都有属于自己的、私有的、地址连续的虚拟内存,最终进程的数据及代码要放到物理内存上,有某种机制能记住虚拟地址空间中的某个数据被放到了哪个物理内存地址上,这就是所谓的地址空间映射------页表。
每个进程都有自己的虚拟地址空间,进程内的所有线程共享进程的虚拟地址空间。
进程和线程切换的区别:
程切换涉及虚拟地址空间的切换而线程不会
进程都有自己的虚拟地址空间,把虚拟地址转换为物理地址需要查找页表,页表查找是一个很慢的过程,通常使用Cache来缓存常用的地址映射,这样可以加速页表查找,由于每个进程都有自己的虚拟地址空间,那么显然每个进程都有自己的页表,那么当进程切换后页表也要进行切换,页表切换后cache就失效了,cache失效导致命中率降低,那么虚拟地址转换为物理地址就会变慢,表现出来的就是程序运行会变慢,而线程切换则不会导致cache失效,因为线程无需切换地址空间,因此我们通常说线程切换要比较进程切换快
进程切换分两步:
1.切换页表来使用新的地址空间
2.切换内核栈和硬件上下文等
线程切换没1步骤
5.为什么虚拟地址空间切换比较耗时?
进程都有自己的虚拟地址空间,把虚拟地址转换为物理地址需要查找页表,页表查找是一个很慢的过程,通常使用Cache来缓存常用的地址映射,这样可以加速页表查找,由于每个进程都有自己的虚拟地址空间,那么显然每个进程都有自己的页表,那么当进程切换后页表也要进行切换,页表切换后cache就失效了,cache失效导致命中率降低,那么虚拟地址转换为物理地址就会变慢,表现出来的就是程序运行会变慢
6.进程间通信方式
1.管道:
优点:简单,我们很容易得知管道里的数据已经被另一个进程读取了
缺点:通信方式效率低,不适合进程间频繁地交换数据
匿名管道:通信范围是存在父子关系的进程。因为管道没有实体,也就是没有管道文件,只能通过 fork 来复制父进程 fd 文件描述符,来达到通信的目的,通信的数据是无格式的流并且大小受限,通信的方式是单向的
命名管道:可以在不相关的进程间也能相互通信。因为命名管道,提前创建了一个类型为管道的设备文件,在进程里只要使用这个设备文件,就可以相互通信
不管是匿名管道还是命名管道,进程写入的数据都是缓存在内核中,另一个进程读取数据时候自然也是从内核中获取,同时通信数据都遵循先进先出原则,
2.消息队列
消息队列是保存在内核中的消息链表,生命周期随内核,如果没有释放消息队列或者没有关闭操作系统,消息队列会一直存在
1.消息队列不适合比较大数据的传输:
因为在内核中每个消息体都有一个最大长度的限制,同时所有队列所包含的全部消息体的总长度也是有上限
2.消息队列通信过程中,存在用户态与内核态之间的数据拷贝开销:
因为进程写入数据到内核中的消息队列时,会发生从用户态拷贝数据到内核态的过程,同理另一进程读取内核中的消息数据时,会发生从内核态拷贝数据到用户态的过程
3.共享内存
共享内存的机制,就是拿出一块虚拟地址空间来,映射到相同的物理内存中。这样这个进程写入的东西,另外一个进程马上就能看到了,都不需要拷贝来拷贝去,传来传去,大大提高了进程间通信的速度。
4.信号量
信号量是一个整型的计数器,主要用于实现进程间的互斥与同步
控制信号量的方式有两种原子操作:
一个是 P 操作,这个操作会把信号量减去 1,相减后如果信号量 < 0,则表明资源已被占用,进程需阻塞等待;相减后如果信号量 >= 0,则表明还有资源可使用,进程可正常继续执行。
另一个是 V 操作,这个操作会把信号量加上 1,相加后如果信号量 <= 0,则表明当前有阻塞中的进程,于是会将该进程唤醒运行;相加后如果信号量 > 0,则表明当前没有阻塞中的进程;
P 操作是用在进入共享资源之前,V 操作是用在离开共享资源之后,这两个操作是必须成对出现的
信号初始化为 1,就代表着是互斥信号量,它可以保证共享内存在任何时刻只有一个进程在访问,这就很好的保护了共享内存
信号初始化为 0,就代表着是同步信号量,它可以保证进程 A 应在进程 B 之前执行。
5.信号
信号是进程间通信机制中唯一的异步通信机制,因为可以在任何时候发送信号给某一进程
6.Socket
Socket 通信不仅可以跨网络与不同主机的进程间通信,还可以在同主机上进程间通信
可根据创建 Socket 的类型不同,分为三种常见的通信方式,一个是基于 TCP 协议的通信方式,一个是基于 UDP 协议的通信方式,一个是本地进程间通信方式。
7.线程的同步方式?
线程同步:即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态
同步方式:
1.临界区:在任意时刻只允许一个线程对共享资源进行访问,如果有多个线程试图访问公共资源,那么在有一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以抢占
2.事件:事件机制,则允许一个线程在处理完一个任务后,主动唤醒另外一个线程执行任务
3.互斥量:互斥对象和临界区对象非常相似,只是其允许在进程间使用,而临界区只限制与同一进程的各个线程之间使用
4.信号量;当需要一个计数器来限制可以使用某共享资源的线程数目时,可以使用“信号量”对象,信号保存了对当前访问某一个指定资源的线程的计数值,该计数值是当前还可以使用该资源的线程数目。如果这个计数达到了零,则所有对这个信号所控制的资源的访问尝试都被放入到一个队列中等待,直到超时或计数值不为零为止。
8.什么是临界区?
临界资源是指一次仅允许一个进程访问的资源
临界区是指每个进程中访问临界资源的那段程序代码
如何解决冲突?
1.如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入。
2.进入临界区的进程要在有限时间内退出,以便其它进程能及时进入自己的临界区。
3.如果进程不能进入自己的临界区,则应让出CPU,避免进程出现“忙等”现象。
9.线程的分类
用户线程:在用户空间实现的线程,不是由内核管理的线程,是由用户态的线程库来完成线程的管理
内核线程:在内核中实现的线程,是由内核管理的线程;
轻量级进程:在内核中来支持用户线程;
10.进程的状态
进程的状态有五种:创建态、就绪态、运行态、阻塞态和终止
进程的状态转换过程、进程的状态转换条件、进程的状态转换时机