这是我参与8月更文挑战的第12天,活动详情查看:8月更文挑战
引言:最近准备面试,在此记录下一些关于操作系统的知识
进程和线程的区别
进程是操作系统资源分配的基本单位。每个进程有自己独立的一块内存空间,一个进程可以有多个线程。
线程是进程中的一个执行任务,负责当前进程中程序的执行。一个进程中至少有一个线程,一个进程可以运行多个线程,多个线程可以共享数据。与进程不一样,多个线程共享进程的堆和方法区资源,每个线程有自己的程序计数器,虚拟机栈以及本地方法栈。所以系统在产生一个线程,或是在各个线程之间切换工作时,负担要比进程小的多。
根本区别:进程是操作系统资源分配的基本单位,线程是cpu资源调度的基本单位。
资源开销:进程有独立的代码和数据空间(程序上下文),程序直接的切换会有较大的开销;同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
内存分配:线程共享同一进程的地址空间和资源,而进程之间的资源和地址是独立的。
影响关系:一个进程崩溃后,在保护模式下不会对其他进程产生影响,而一个线程崩溃后会之间导致整个进程奔溃。所以多进程要比多线程健壮得多。
协程是一种比线程更加轻量级的存在。一个线程也可以拥有多个协程。其执行过程更类似于子例程,或者说不带返回值的函数调用。
协程避免了无意义的调度,因为线程切换会占用大量的系统时间,由此可以提高性能,但程序员必须自己承担调度的责任。同时,协程页失去了标准线程使用多CPU的能力。
python中的多线程
python中点多线程不是严格意义上的多线程,因为python中GIL存在,GIL的引入提高了python单线程程序的高性能,此外python gc垃圾回收机制(引用计数)也用到了GIL锁这样可以防止多个线程访问的时候,导致内存泄漏,只使用GIL一把锁可以防止死锁,对引入锁而导致的性能下降影响不大。但是这也导致只能单线程使用。
可以通过:
- 需要多线程的代码用c进行编写,然后python调用即可。
- 编译器使用jpython,cpython中有GIL锁,但是jpython没有。不过可能会有不兼容的问题。
进程有哪些状态
- 就绪状态:进程已获得除处理器以外的所需资源,等待分配处理器资源。
- 运行状态:占用处理机资源运行,处在此状态的进程数小于等于cpu数。
- 阻塞状态:进程等待某种条件,在条件满足之前无法执行。
并发和并行
并发是一段时间内,多个任务都会被处理;但是某一刻,只有一个任务在执行。。
并行就是同一时刻,有多个任务在执行。这个需要在多核处理器上完成。
进程和线程的切换流程
进程切换分俩步:
1.切换页表使用新的地址空间,一旦切换上下文,处理器中所有已缓存的内存地址都作废。
2.切换内核栈和硬件上下文
对于linux来说,线程和进程最大的区别就在于地址空间,对于线程切换,第一步是不需要的,第二步是进程和线程切换。
因为每个进程都有自己的虚拟地址空间,而线程共用同一个虚拟地址空间所以线程切换的时候不涉及虚拟地址空间的转换。
虚拟地址空间切换为什么比较耗时
进程都有自己的虚拟地址空间,把虚拟地址空间转换成物理地址需要查找页表,页表查找比较慢,所以一般是使用Cache来缓存常用的地址映射。
由于每个进程有自己的虚拟空间,每个进程都有自己的页表,所以进程在切换的时候会导致缓存清空,这就导致再次访问的时候无法击中缓存,虚拟地址转换成物理地址速度变慢而线程因为同属于一个进程 (不会清空缓存)所以不会导致缓存失效。
进程间通信方式有哪些
- 管道:管道这种通讯方式有两种限制,一是半双工的通信,数据只能单向流动,二是只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
- 管道分为两类:匿名管道和命名管道,匿名管道只能单向通信而命名管道以磁盘方式存在,可以实现本机任意两个进程通信。
- 信号:信号可以在任何时候发给某一进程,而无需知道该进程的状态。
- 消息队列:消息队列是消息的链表,有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
- Socket:与其他通信机制不同,它可用于不同机器之间通信。
- 共享内存:共享内存就是映射一段能被其他进程访问的内存,这个内存由一个进程创建,但是多个进程都可以访问。共享内存是最快的IPC方式,是针对其他进程通信方式运行效率低而专门设计的。往往与其他通信机制配合使用。
优缺点
- 管道:速度慢,容量有限;
- Socket:任何进程都能通信,但速度慢;
- 消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题;
- 信号量:不能传递复杂信息,只能用来同步;
- 共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题
死锁
定义:在多个并发进程中,如果每个进程持有某种资源而又等待其他进程释放他们保持的资源,没有改变之前都不能向前推进,称这一组进程产生了死锁。
简而言之就是俩个进程无限期的阻塞互相等待的过程
死锁产生的四个必要条件:
互斥条件:一个资源一次只能被一个进程使用。
请求与保持:一个进程因为请求资源而阻塞时候,对其已有资源不释放。
不可剥夺条件:进程获得的资源,在没有使用之前其他进程不能抢夺。
循环等待条件:许多个进程之间形成一种头尾相连的环形等待状态。