操作系统复习
转载:https://www.nowcoder.com/discuss/325668?type=2
什么是操作系统
操作系统(英语:operating system,缩写作 OS)是管理计算机硬件与软件资源的计算机程序,同时也是计算机系统的内核与基石。操作系统需要处理如管理与配置内存、决定系统资源供需的优先次序、控制输入与输出设备、操作网络与管理文件系统等基本事务。操作系统也提供一个让用户与系统交互的操作界面。
请描述进程的三种基本状态
就绪状态:当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可立即执行,这时的进程状态称为就绪状态。
执行状态:当进程已获得处理机,其程序正在处理机上执行,此时的进程状态称为执行状态。
阻塞状态:正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。例如,等待I/O完成、申请缓冲区不能满足、等待信件(信号)等。
进程状态间的切换
(1) 就绪→执行
处于就绪状态的进程,当进程调度程序为之分配了处理机后,该进程便由就绪状态转变成执行状态。
(2) 执行→就绪
处于执行状态的进程在其执行过程中,因分配给它的一个时间片已用完而不得不让出处理机,于是进程从执行状态转变成就绪状态。
(3) 执行→阻塞
正在执行的进程因等待某种事件发生而无法继续执行时,便从执行状态变成阻塞状态。
(4) 阻塞→就绪
处于阻塞状态的进程,若其等待的事件已经发生,于是进程由阻塞状态转变为就绪状态。
线程的几种状态
线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。
第一是创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态;
第二是就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。
第三是运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
第四是阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend等方法都可以导致线程阻塞。
第五是死亡状态。如果一个线程的run方法执行结束,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪状态。
什么是线程?
- 线程是进程的子任务,是CPU调度和分派的基本单位,用于保证程序的实时性,实现进程内部的并发。(线程自身是不能拥有系统资源的,但是它可以拥有自己的堆、栈、局部变量以及程序计算器。)
- 优点:可以提高系统的并行性,数据共享比较方便,切换比较快。
- 缺点:没有内存隔离,一个线程的崩溃会导致整个进程的崩溃。编程复杂以及调试困难。
什么是进程?
- 进程是对运行时程序的封装,是系统进行资源调度和分配的基本单位,实现了操作系统的并发;
- 优点:内存隔离,单个进程的崩溃不会导致这个系统的崩溃。而且进程方便测试以及编程简单
- 缺点:创建销毁比较麻烦,进程间数据的共享麻烦,并且消耗的资源比较多。
一个进程里包含什么?
一个进程由三部分组成:程序、数据及进程控制块(PCB)。进程控制块是记录进程有关信息的一块主存,是进程存在的程序唯一标识。
进程和线程区别?
调度: 线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
并发性: 不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行
拥有资源: 进程是拥有资源的一个独立单位,线程不拥有系统资源,但是可以访问隶属于进程的资源
系统开销: 创建或撤销进程时,系统都要为之分配或回收系统资源,如内存空间,I/O设备等,OS所付出的开销显著大于在创建或撤销线程时的开销,进程切换的开销也远大于线程切换的开销
进程和线程的关系?
- 一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程(通常说的主线程)
- 资源分配给进程,同一进程的所有线程共享该进程的所有资源
- 线程在执行过程中,需要协作同步,不同进程的线程间要利用消息通信的方法实现同步
- 处理机分配给线程,即真正在处理机上运行的是线程
- 线程是指进程内的一个执行单元,也是进程内的可调度实体
什么时候适合用多线程什么时候适合用多进程?
1、需要频繁创建销毁的优先使用线程;因为创建和销毁一个进程代价是很大的。
2、线程的切换速度快,所以在需要大量计算,切换频繁时用线程,还有耗时的操作使用线程可提高应用程序的响应;
3、因为对CPU系统的效率使用上线程更占优,所以可能要发展到多机分布的用进程,多核分布用线程;
4、需要更稳定安全时,适合选择进程;需要速度时,选择线程更好。
作业、管程各自定义
作业:用户在一次解题或一个事务处理过程中要求计算机系统所做工作的集合,它包括用户程序、所需要的数据及控制命令等。
管程:管程实际上是定义了一个数据结构和在该数据结构上的能为并发进程所执行的一组操作,这组操作能同步进程和改变管程中的数据。
linux进程有5种状态
- 运行(正在运行或在运行队列中等待)
- 中断(休眠中, 受阻, 在等待某个条件的形成或接受到信号)
- 不可中断(收到信号不唤醒和不可运行, 进程必须等待直到有中断发生)
- 僵死(进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放)
- 停止(进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行)
什么是进程间通信?通信的目的?
进程通信:
进程用户空间是相互独立的,一般而言是不能相互访问的。但很多情况下进程间需要互相通信,来完成系统的某项功能。进程通过与内核及其它进程之间的互相通信来协调它们的行为。
目的:
- 数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间。
- 共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到。通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
- 资源共享:多个进程之间共享同样的资源。为了作到这一点,需要内核提供锁和同步机制。
- 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。
进程间通信方式-IPC?哪种方式效率最高?
1.管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
2.有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
3.信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
4.信号(sinal)
信号是一种比较复杂的通信方式,用于通知接收进程某些事件已经发生,要注意信号处理中调用的函数是否为信号安全。
5.消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
6.共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
7.套接字( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
最快的方式是共享内存:采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝
X64和X86的区别
死锁的产生和解除
死锁定义:
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态,这些在互相等待的进程称为死锁进程。
产生死锁的必要条件:
互斥条件:一个资源一次只能被一个进程使用
请求与保持条件:一个进程因请求资源而阻塞时,对已获得资源保持不放
不可剥夺条件:进程获得的资源,在未完全使用完之前,不能强行剥夺
循环等待条件:若干进程之间形成一种头尾相接的环形等待资源关系
死锁避免:
系统对进程发出每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源,如果分配后系统可能发生死锁,则不予分配,否则予以分配。这是一种保证系统不进入死锁状态的动态策略。
死锁预防:
只要打破四个必要条件之一就能有效预防死锁的发生:
● 打破互斥条件: 改造独占性资源为虚拟资源,大部分资源已无法改造。
● 打破不可抢占条件: 当一进程占有一独占性资源后又申请一独占性资源而无法满足,则退出原占有的资源。
● 打破占有且申请条件: 采用资源预先分配策略,即进程运行前申请全部资源,满足则运行,不然就等待,这样就不会占有且申请。
● 打破循环等待条件: 实现资源有序分配策略,对所有设备实现分类编号,所有进程只能采用按序号递增的形式申请资源。
死锁避免和死锁预防的区别:
死锁预防是设法至少破坏产生死锁的四个必要条件之一,严格的防止死锁的出现;而死锁避免则不那么严格的限制产生死锁的必要条件的存在,因为即使死锁的必要条件存在,也不一定发生死锁。死锁避免是在系统运行过程中注意避免死锁的最终发生。
避免死锁的算法
银行家算法等等。
互斥体和临界区的区别
1、临界区只能用于对象在同一进程里线程间的互斥访问;互斥体可以用于对象进程间或线程间的互斥访问。
2、临界区是非内核对象,只在用户态进行锁操作,速度快;互斥体是内核对象,在核心态进行锁操作,速度慢。
3、临界区和互斥体在Windows平台都下可用;Linux下只有互斥体可用
Windows链接器加载动态库(DLL)的搜索路径顺序
- 当前进程的可执行模块所在的目录
- 当前目录
- Windows系统目录。如C:\Windows\System32,GetSystemDirectory函数检索此目录的路径
- Windows目录。 如C:\Windows,GetWindowsDirectory函数检索此目录的路径
- PATH环境变量中列出的目录
什么是内存抖动
内存抖动一般是内存分配算法不好,内存太小或者程序的算法不佳引起的页面频繁地从内存调入/调出的行为。
多线程、多进程在实际服务器中的应用
当多个客户访问服务器时,服务器应该如何响应处理这些客户的信息,是分多个线程还是多个进程去处理。
1、服务端分配多个线程/进程来处理客户端连接,一个客户端对应一个线程/进程
2、服务端的一个进程/线程对应多个连接.
线程(进程)同步的方式有哪些?
互斥量:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。
信号量:它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量。
事件:通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作。
什么是缓冲区溢出?有什么危害?其原因是什么?
缓冲区溢出是指当计算机向缓冲区填充数据时超出了缓冲区本身的容量,溢出的数据覆盖在合法数据上。
危害有以下两点:
程序崩溃,导致拒绝服务
跳转并且执行一段恶意代码
造成缓冲区溢出的主要原因是程序中没有仔细检查用户输入。
说一说进程同步有哪几种机制。
原子操作、信号量机制、分布式系统、自旋锁管程、会合
操作系统中进程调度策略有哪几种?
先进先出算法(FIFO):
按照进程进入就绪队列的先后次序来选择。即每当进入进程调度,总是把就绪队列的队首进程投入运行。
时间片轮转算法(RR):
分时系统的一种调度算法。轮转的基本思想是,将CPU的处理时间划分成一个个的时间片,就绪队列中的进程轮流运行一个时间片。当时间片结束时,就强迫进程让出CPU,该进程进入就绪队列,等待下一次调度,同时,进程调度又去选择就绪队列中的一个进程,分配给它一个时间片,以投入运行。
最高优先级算法(HPF):
进程调度每次将处理机分配给具有最高优先级的就绪进程。最高优先级算法可与不同的CPU方式结合形成可抢占式最高优先级算法和不可抢占式最高优先级算法。
多级队列反馈法:
几种调度算法的结合形式多级队列方式。
分页和分段有什么区别?
段是信息的逻辑单位,它是根据用户的需要划分的,因此段对用户是可见的 ;
页是信息的物理单位,是为了管理主存的方便而划分的,对用户是透明的。
段的大小不固定,有它所完成的功能决定;
页大大小固定,由系统决定;
段向用户提供二维地址空间;
页向用户提供的是一维地址空间段是信息的逻辑单位,便于存储保护和信息的共享,页的保护和共享受到限制。
用户态和内核态的区别
当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。
当进程在执行用户自己的代码时,则称其处于用户运行态(用户态)。即此时处理器在特权级最低的(3级)用户代码中运行。
用户态进入内核态的方式,如何进入内核态
a. 系统调用
这是用户态进程主动要求切换到内核态的一种方式,用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作,比如fork()实际上就是执行了一个创建新进程的系统调用。而系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现,例如Linux的int 80h中断。
b. 异常
当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。
c. 外围设备的中断
当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。
这3种方式是系统在运行时由用户态转到内核态的最主要方式,其中系统调用可以认为是用户进程主动发起的,异常和外围设备中断则是被动的。
那你知道什么叫僵尸进程?怎么处理僵尸进程?
定义:
完成了生命周期但却依然留在进程表中的进程,我们称之为 “僵尸进程”。
如何产生:
当你运行一个程序时,它会产生一个父进程以及很多子进程。 所有这些子进程都会消耗内核分配给它们的内存和 CPU 资源。
这些子进程完成执行后会发送一个 Exit 信号然后死掉。这个 Exit 信号需要被父进程所读取。父进程需要随后调用 wait 命令来读取子进程的退出状态,并将子进程从进程表中移除。
若父进程正确第读取了子进程的 Exit 信号,则子进程会从进程表中删掉。
但若父进程未能读取到子进程的 Exit 信号,则这个子进程虽然完成执行处于死亡的状态,但也不会从进程表中删掉。
处理:
打开终端并输入下面命令:
ps aux | grep Z
kill -s SIGCHLD pid
将这里的 pid 替换成父进程的进程 id,这样父进程就会删除所有以及完成并死掉的子进程了。
确保删除子僵尸的唯一方法就是杀掉它们的父进程。
ps -aux什么意思
ps -aux 显示所有的进程(静态)
a 显示所有用户的进程
u 显示用户
x 显示无控制终端的进程