1、操作系统
操作系统是应用程序和硬件之间的媒介,是管理计算机硬件和软件资源的计算机程序。计算机运行的许多应用程序都需要对内存和 CPU 进行交互,操作系统可以保证交互准确进行。
2、操作系统主要有哪些功能
处理器(CPU)管理:CPU 的管理和分配,主要指的是进程管理。
内存管理:内存的分配和管理,主要利用了虚拟内存的方式。
外存管理:外存(磁盘等)的分配和管理,将外存以文件的形式提供出去。
I/O 管理:对输入/输出设备的统一管理。
3、内核
内核可以说是一个计算机程序,它是操作系统的核心,可以控制操作系统中所有的内容、如 CPU、内存、硬盘等硬件。
4、用户态和内核态
大多数操作系统会把内存空间分成了两个区域:内核空间和用户空间。内核空间只有内核程序可以访问,而用户空间专门是给应用程序使用的内存空间,权限较小。当程序使用用户空间时,程序在用户态执行。当程序使用内核空间时,程序在内核态执行。
5、用户态和内核态切换
应用程序进⼊内核空间,就需要通过系统调用来进入内核态:应用程序使用系统调用时,会产生一个中断,CPU 中断当前用户程序,去执行中断处理程序,也就是执行内核程序。处理完后会触发中断,把 CPU 执行权限交给用户程序,回到用户态继续工作。
6、并发和并行
并发是指一个处理器同时处理多个任务。在一段时间内有多个任务都会被处理,但在某一时刻只有一个任务在执行。例如有两个进程 A 和 B,A 运行一个时间片之后,切换到 B,B 运行一个时间片之后又切换到 A。因为切换速度足够快,所以宏观上表现为在一段时间内能同时运行多个程序。
并行是指多个处理器或者是多核的处理器同时处理多个不同的任务。在同一时刻,不同的程序被放到不同的处理器上运行,多个进程同时进行。
7、进程和线程
进程是一个内存中正在运行的一个程序,每个进程都拥有独立的地址空间,一个应用程序可以有多个进程。进程也是程序的一次执行过程,是系统运行程序的基本单位,系统运行一个程序即是一个进程从创建、运行到终止的过程。
线程是进程中的一个执行单元,是 CPU 调度的基本单位,一个进程可以拥有多个线程,属于同一个进程的不同线程之间共享同一地址空间。
进程和线程的区别与联系:
a. 不同进程的数据很难共享,而同一进程下的不同线程共享数据较容易。
b. 进程消耗的计算机资源更多,线程的上下文切换开销更小,所需时间更少。
c. 进程间不会相互影响,一个线程挂掉将导致整个进程挂掉。
d. 进程使用的内存地址可以上锁,即某一线程使用共享内存时,其他线程必须等它结束才能用。
e. 进程适合对安全稳定有要求的情况,线程适合对于速度有要求的情况。
8、进程上下文切换与线程上下文切换
进程的上下文切换是一种将 CPU 资源从一个进程分配给另一个进程的机制。在切换的过程中,操作系统需要先存储当前进程的状态,再读入下一个进程的状态,然后执行此进程。
线程的上下文切换需要看线程是否属于同一个进程。若不属于同一个进程,则切换的过程跟进程的上下文切换一样。若属于同一个进程,由于共享内存空间,切换时内存空间的资源保持不动,仅需切换线程的私有数据等不共享的数据即可。
9、进程有哪些状态
就绪状态 ready:进程已经准备好,只要分配到 CPU 就能够立即运行
执行状态 running:进程被 CPU 调度,其程序正在执行的状态。
阻塞状态 block:正在执行的进程由于发生某事件暂时无法继续执行的状态。
创建状态:进程被创建时的状态。
终止状态:进程从系统中消失时的状态。
10、进程间通信
一个进程无法访问另一个进程的变量和数据结构,如果想让一个进程访问另一个进程的资源,需要使用进程间通信。进程间通信的方式有管道、消息队列、共享内存、套接字等。
管道:管道是半双工的,即数据只能在一个方向上流动,只能用于具有亲缘关系的进程之间的通信如父子进程。
消息队列:消息队列就是一个保存在内核中消息的列表。用户进程可以向消息队列添加消息,也可以向消息队列读取消息。
共享内存:多个进程共享一个存储区,一个进程写入的信息,可以被共享这个内存的其他进程读取,从而实现了进程间的通信。
11、套接字通信
套接字(Socket)可以让不在同一台主机上的两个进程,通过网络进行通信,一般可以用在客户端和服务器之间的通信。通过 Socket 接口可以区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。套接字的连接分为三步:服务器监听,客户端请求,连接确认。
服务器监听:服务端套接字处于等待连接的状态,实时监听网络状态,等待客户端的连接请求。
客户端请求:客户端套接字根据服务端套接字的地址和端口号,向服务端套接字提出连接请求。
连接确认:服务端套接字监听到连接请求时,会响应这个请求,建立一个新的线程,客户端确认后建立连接。此时,服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
12、进程间常用的调度方法
进程调度决定了哪些进程在优先使用 CPU。常用调度算法有:先来先服务算法、时间片轮转算法、短任务优先算法、优先级调度算法等。
a. 先来先服务算法(FCFS):按照进程到达的先后顺
序进行服务。算法实现简单,缺点则是短的工作有可能变得很慢,因为其前面有很长的工作在执行。
b. 时间片轮转算法:按照进程到达的先后顺序将所有进程排成一个队列,按照队列的顺序,每个进程分配一个时间片轮流执行。时间片轮转算法是对先来先服务算法的一种改进,其主要目的是改善短程序的响应时间。
c. 短任务优先算法(SJF):根据进程的预计执行时间来进行调度,执行时间最短的进程。可以保证每个任务的周转时间都是最小的,平均周转时间也就是最小的。
d. 优先级调度算法:优先级调度算法给每个进程赋予一个优先级,每次需要进程切换时,找一个优先级最高的进程进行调度。该算法的优点在于可以赋予重要的进程以高优先级以确保重要任务能够得到 CPU 时间。
13、僵尸进程与孤儿进程
僵尸进程:已完成且处于终止状态,但在进程表中却仍然存在的进程。
孤儿进程:父进程退出,子进程还在运行,那么这些子进程将成为孤儿进程。
14、进程饥饿(竞争锁)
饥饿是指系统不能保证某个进程的等待时间上界,从而使该进程长时间等待,当等待时间给进程推进和响应带来明显影响时,便称为进程饥饿。当饥饿到一定程度的进程所赋予的任务即使完成也不再具有实际意义时称该进程被饿死。
15、死锁
死锁是指两个或多个进程在互相请求对方占有的资源时,由于资源被对方占用而造成的相互等待现象。例如:用户 A 访问表 A(锁住了表 A)后访问表 B,用户 B 访问表 B(锁住了表 B)后访问表 A,这时用户 A 由于用户 B 已经锁住表 B,它必须等待用户 B 释放表 B 才能继续,同样用户 B 要等用户 A 释放表A 才能继续,这就死锁就产生了。
16、活锁
活锁指线程无法取得需要的资源而一直重试的现象。与死锁不同,活锁中的线程不会被阻塞,它们会一直尝试获取资源,但是却一直失败,最终导致程序无法正常执行。活锁可以用两个人过一条很窄的小桥来比喻:为了让对方先过,两个人都往旁边让,但两个人总是让到同一边。这样,虽然两个人的状态一直在变化,但却都无法往前推进。
17、死锁产生的条件
死锁产生需要同时满足四个条件:互斥、占有等待、不可抢占、循环等待。
a. 互斥条件:同一时刻只能有一个进程占用资源,如果其他进程想要访问该资源必须等待。
b. 占有等待条件:进程已经持有了至少一个资源,并且正在等待其他资源,但等待的资源被其它进程占有,导致当前进程被阻塞,但阻塞的同时并不释放自己已经获取的资源。
c. 不可抢占条件:指资源在使用完之前不能被其它进程抢占,只有使用完后由自己释放。
d. 循环等待条件:存在一个循环等待队列,其中每个进程都在等待下一个进程所持有的资源。
18、如何避免死锁
破坏死锁产生的条件来避免死锁。
a. 破坏占有等待条件:资源一次性分配,一个进程一次请求其所需要的所有资源,只要有一个资源得不到分配,也不给这个进程分配其他的资源。
b. 破坏不可抢占条件:当进程进一步申请其他资源时,如果申请不到,主动释放已占有的资源。
c. 破坏循环等待条件:按序申请资源,系统给每类资源赋予一个序号,每个进程按序号依次请求资源,释放则相反。