软件开发相关面经8——操作系统篇

进程与线程的区别和联系(重点)

1.进程是对运行时程序的封装,是**系统进行资源分配和调度的基本单元,而线程是进程的子任务,是CPU分配和调度的基本单元。**
2. 一个进程可以有多个线程,但是一个线程只能属于一个进程。
3. 进程的创建需要系统分配内存和CPU,文件句柄等资源,销毁时也要进行相应的回收,所以进程的管理开销很大;但是线程的管理开销则很小。
4. 进程之间不会相互影响;而一个线程崩溃会导致进程崩溃,从而影响同个进程里面的其他线程。

联系: 进程与线程之间的关系:线程是存在进程的内部,一个进程中可以有多个线程,一个线程只能存在一个进程中


Linux理论上最多可以创建多少个进程?一个进程可以创建多少线程,和什么有关

答:Linux中有一个命令可以帮助我们查看系统中的进程上限

ulimit -u

我这是1024,但是这属于软限制,是可以改变的。即我可以通过改变这个参数的值来修改对于进程数量的软限制,比如说用下面的命令将软限制改到5120。

 ulimit -u 5120

我们用pid_t来表示一个进程的pid,因此能表示的进程的范围一定不会超过pid_t类型的大小

cat /proc/sys/kernel/pid_max
32768

pid_t实际上就是一个short类型变量,当然这里能表示的范围只是进程id最多表示到这么多,这只是一个理论值,实际上,由于内存等系统资源的限制,根本不会同时有这么多的进程存在。

至于线程。进程最多可以创建的线程数是根据分配给调用栈的大小,以及操作系统(32位和64位不同)共同决定的。Linux32位下是300多个。


冯诺依曼结构有哪几个模块?分别对应现代计算机的哪几个部分?

存储器:内存
控制器:南桥北桥
运算器:CPU
输入设备:键盘
输出设备:显示器、网卡

进程调度方法详细介绍

先来先服务 (FCFS first come first serve):按照作业到达任务队列的顺序调度 FCFS是非抢占式的,易于实现,效率不高,性能不好,有利于长作业(CPU繁忙性)而不利于短作业(I/O繁忙性)
短作业优先 (SHF short job first):每次从队列里选择预计时间最短的作业运行。SJF是非抢占式的,优先照顾短作业,具有很好的性能,降低平均等待时间,提高吞吐量。但是不利于长作业,长作业可能一直处于等待状态,出现饥饿现象;完全未考虑作业的优先紧迫程度,不能用于实时系统
最短剩余时间优先 该算法首先按照作业的服务时间挑选最短的作业运行,在该作业运行期间,一旦有新作业到达系统,并且该新作业的服务时间比当前运行作业的剩余服务时间短,则发生抢占;否则,当前作业继续运行。该算法确保一旦新的短作业或短进程进入系统,能够很快得到处理。
==高响应比优先调度算法(Highest Reponse Ratio First, HRRF)==是非抢占式的,主要用于作业调度。基本思想:每次进行作业调度时,先计算后备作业队列中每个作业的响应比,挑选最高的作业投入系统运行。响应比 = (等待时间 + 服务时间) / 服务时间 = 等待时间 / 服务时间 + 1。因为每次都需要计算响应比,所以比较耗费系统资源。
时间片轮转 用于分时系统的进程调度。基本思想:系统将CPU处理时间划分为若干个时间片(q),进程按照到达先后顺序排列。每次调度选择队首的进程,执行完1个时间片q后,计时器发出时钟中断请求,该进程移至队尾。以后每次调度都是如此。该算法能在给定的时间内响应所有用户的而请求,达到分时系统的目的。
时间片大小的确定
1.系统对响应时间的要求
2.就绪队列中进程的数目
3.系统的处理能力
多级反馈队列(Multilevel Feedback Queue)
多级反馈队列调度算法是一种CPU处理机调度算法
参考:https://blog.csdn.net/leex_brave/article/details/51638300

进程的执行过程是什么样的,执行一个进程需要做哪些工作?

创建进程首先要将程序和数据装入内存。将用户源程序变为可在内存中执行的程序,通常需要以下几个步骤:
编译:由编译程序将用户源代码编译成若干个目标模块
链接:由链接程序将编译后形成的一组目标模块,以及所需库函数链接在一起,形成一个完整的装入模块
装入由装入程序将装入模块装入内存运行
在这里插入图片描述

将进程装入内存时,通常使用分页技术,将内存分成固定大小的页,进程分为固定大小的块,加载时将进程的块装入页中,并使用页表记录。减少外部碎片。 通常操作系统还会使用虚拟内存的技术将磁盘作为内存的扩充。

操作系统的内存管理(操作系统对内存的划分和动态分配)说一下

操作系统的内存管理包括物理内存管理虚拟内存管理
内存管理包括内存管理概念、交换与覆盖、连续分配管理方式和非连续分配管理方式(分页管理方式、分段管理方式、段页式管理方式)。
虚拟内存管理包括虚拟内存概念、请求分页管理方式、页面置换算法、页面分配策略、工作集和抖动。

内存管理功能
内存的分配与回收:当作业或进程创建后系统会为他们分配内存空间,当结束后内存空间也会被回收。
地址转换:将程序中的逻辑地址转换成内存中的物理地址
内存空间的扩充:利用虚拟存储技术或自动覆盖技术,从逻辑上扩充内存
存储保护:保证个个作业在自己的内存空间内运行,互不干扰
参考:https://www.cnblogs.com/peterYong/p/6556619.html

覆盖

追根溯源——早期计算机系统内存容量小,虽然内存中只有一道用户程序,内存存储空间仍有可能放不下。覆盖的基本思想是:程序运行时并非任何时候都要访问程序及数据的各个部分,因此可以把用户空间分成一个固定区和若干个覆盖区。经常活跃的部分放在固定区,其余部分按调用关系分段。在覆盖区和外存(即磁盘)中屡次调入调出。

特点是打破了必须将一个进程的全部信息装入主存后才能运行的限制。

交换

交换的基本思想是: 把处于等待状态(比如说等待IO, 网络等阻塞的线程)的程序从内存移出,腾出内存空间,这个过程叫换出。把准备好竞争CPU的程序从辅存移动到内存,这个过程叫换入。

需要注意几个问题:

交换需要备份存储,通常是快速磁盘

为了有效使用CPU,每个进程的执行时间需要比交换时间长。

如果换出进程,必须确保该进程是处于完全空闲状态

普通的交换使用不多,但交换策略的某些变种在许多系统(比如UNIX系统)仍发挥作用。

两者区别: 交换技术主要是在不同进程(或作业之间),而覆盖则用于同一个进程中。对于主存无法存放用户程序的矛盾,现代操作系统是通过虚拟内存技术来解决的,覆盖技术已成为历史,而交换技术在现代操作系统仍有较强的生命力。
交换技术是以进程为单位,若进程所需内存大于系统内存 ,则此进程无法进行。而虚拟存储是以页或段为单位,是把进程再分为页或段对内存进行分化,若进程所需内存大于系统内存,进程也可以运行,因为该进程的一部分可换到外存上。
总的来说覆盖是进程内部的,而 交换 和虚拟 可进行 进程间互换,而虚拟可以继续把进程在内存划分成页或段。

参考:https://blog.csdn.net/qq_33826977/article/details/79776543
https://zhuanlan.zhihu.com/p/141602175

抖动(颠簸)现象
刚刚换出的页面马上又要换入内存,刚刚换入的页面马上又要换出外存,这种频繁的页面调度行为称为抖动,或颠簸
产生抖动的主要原因是进程频繁访问的页面数目高于可用的物理块数(分配给进程的物理块不够)

**虚拟内存**是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。

死锁产生的必要条件(怎么检测死锁,解决死锁问题)

什么是死锁?
所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。 因此我们举个例子来描述,如果此时有一个线程A,按照先锁a再获得锁b的的顺序获得锁,而在此同时又有另外一个线程B,按照先锁b再锁a的顺序获得锁。如下图所示:
在这里插入图片描述
死锁产生的4个必要条件?
(1) 互斥:一个资源每次只能被一个进程使用。
(2) 占有并请求:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不可剥夺:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待:若干进程之间形成一种头尾相接的循环等待资源关系。

产生死锁的原因主要是:
(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适。
(3) 资源分配不当等。

死锁的恢复

  1. 重新启动:是最简单、最常用的死锁消除方法,但代价很大,因为在此之前所有进程已经完成的计算工作都将付之东流,不仅包括死锁的全部进程,也包括未参与死锁的全部进程。
  2. 终止进程(process termination):终止参与死锁的进程并回收它们所占资源。
    (1) 一次性全部终止;(2) 逐步终止(优先级,代价函数)
  3. 剥夺资源(resource preemption):剥夺死锁进程所占有的全部或者部分资源。
    (1) 逐步剥夺:一次剥夺死锁进程所占有的一个或一组资源,如果死锁尚未解除再继续剥夺,直至死锁解除为止。
    (2) 一次剥夺:一次性地剥夺死锁进程所占有的全部资源。
  4. 进程回退(rollback):让参与死锁的进程回退到以前没有发生死锁的某个点处,并由此点开始继续执行,希望进程交叉执行时不再发生死锁。但是系统开销很大
    (1) 要实现“回退”,必须“记住”以前某一点处的现场,而现场随着进程推进而动态变化,需要花费大量时间和空间。
    (2) 一个回退的进程应当“挽回”它在回退点之间所造成的影响,如修改某一文件,给其它进程发送消息等,这些在实现时是难以做到的

饥饿

是由于资源分配策略不公引起的,当进程或线程无法访问它所需要的资源而不能继续执行时,就会发生饥饿现象。

进程之间的通信方法有哪几种 (重点)

进程之间的通信方式主要有六种,包括管道信号量消息队列信号共享内存套接字
管道
管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;
匿名管道只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);
单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在于内存中。
其中:
匿名管道(pipe):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常指父子进程关系。
命名管道(FIFO):有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
缺点:信号传递的信息少、只能承载无格式字节流以及缓冲区大小受限
消息队列(message queue)
消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递的信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
共享内存(share memory):效率高
共享内存就是映射一段能被其它进程所访问的内存,这段内存由一个进程创建,但多个进程都可以访问。共享内存是最快的IPC方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量配合使用,来实现进程间的同步和通信。

信号量(semaphore)
信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
套接字(socket)
是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。
信号(signal)
是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
参考:https://blog.csdn.net/ailunlee/article/details/98042567


线程中的通信方式

锁机制:包括互斥锁、条件变量、读写锁
互斥锁提供了以排他方式防止数据结构被并发修改的方法。
读写锁允许多个线程同时读共享数据,而对写操作是互斥的。
条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。
信号量机制(Semaphore):包括无名线程信号量和命名线程信号量
信号机制(Signal):类似进程间的信号处理
线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。

说到线程之间通信方式:

1.是通过共享变量,线程之间通过该变量进行协作通信; 
2.通过队列(本质上也是线程间共享同一块内存)来实现消费者和生产者的模式来进行通信;

1.通过线程之间共享变量的方式

这个就有必要说下 wait(),notify(),以及notifyAll() 这三个方法

这三个方法都是属于Object的方法;所以所有类都可以继承这三方法;
wait()方法使得当前线程必须要等待,等到另外一个线程调用notify()或者notifyAll()方法。
notify()方法会唤醒一个等待当前对象的锁的线程。而notifyAll()顾名思义;就是唤醒所有在等待中的方法;
wait()和notify()方法要求在调用时线程已经获得了对象的锁,因此对这两个方法的调用需要放在synchronized方法或synchronized块中。

参考:https://blog.csdn.net/liyue98/article/details/80112246

什么时候用多进程,什么时候用多线程

频繁修改的:需要频繁创建和销毁的优先使用多线程
计算量大:需要大量计算的优先使用多线程 因为需要消耗大量CPU资源且切换频繁,所以多线程好一点
相关性强:任务间相关性比较强的用多线程,相关性比较弱的用多进程。因为线程之间的数据共享和同步比较简单。
多分布:可能要扩展到多机分布的用多进程,多核分布的用多线程。
参考:https://blog.csdn.net/yu876876/article/details/82810178

孤儿进程和僵尸进程分别是什么,怎么形成的?

孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵尸进程。

如果进程不调用wait / waitpid的话, 那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害,应当避免。孤儿进程并不会有什么危害

说一下PCB/说一下进程地址空间

PCB就是进程控制块,是操作系统中的一种数据结构,用于表示进程状态,操作系统通过PCB对进程进行管理。
PCB中包含有:进程标识符,处理器状态,进程调度信息,进程控制信息
https://blog.csdn.net/qq_38499859/article/details/80057427

进程地址空间内有:

代码段text:存放程序的二进制代码
初始化的数据Data:已经初始化的变量和数据
未初始化的数据BSS:还没有初始化的数据
栈
堆

多线程是如何同步的(尤其是如果项目中用到了多线程,很大可能会结合讨论)

临界区
信号量
事件
互斥量

同一个进程内的线程会共享什么资源?

该进程的地址空间
全局变量
堆空间
线程的栈空间是自己独有的

一般情况下在Linux/windows平台下栈空间的大小

在Linux下栈空间通常是8M,Windows下是1M

虚拟地址

在运行一个进程的时候,它所需要的内存空间可能大于系统的物理内存容量。通常一个进程会有4G的空间,但是物理内存并没有这么大,所以这些空间都是虚拟内存,它的地址都是逻辑地址,每次在访问的时候都需要映射成物理地址。当进程访问某个逻辑地址的时候,会去查看页表,如果页表中没有相应的物理地址,说明内存中没有这页的数据,发生缺页异常,这时候进程需要把数据从磁盘拷贝到物理内存中。如果物理内存已经满了,就需要覆盖已有的页,如果这个页曾经被修改过,那么还要把它写回磁盘

服务器高并发的解决方案

  1. 应用数据与静态资源分离
    将静态资源(图片,视频,js,css等)单独保存到专门的静态资源服务器中,在客户端访问的时候
    从静态资源服务器中返回静态资源,从主服务器中返回应用数据。
  2. 客户端缓存
    因为效率最高,消耗资源最小的就是纯静态的html页面,所以可以把网站上的页面尽可能用静态的来实现,在页面过期或者有数据更新之后再将页面重新缓存。或者先生成静态页面,然后用ajax异步请求获取动态数据。
  3. 集群和分布式
    (集群是所有的服务器都有相同的功能,请求哪台都可以,主要起分流作用)
    (分布式是将不同的业务放到不同的服务器中,处理一个请求可能需要使用到多台服务器,起到加快请求处理的速度。)
    可以使用服务器集群和分布式架构,使得原本属于一个服务器的计算压力分散到多个服务器上。同时加快请求处理的速度。
  4. 反向代理
    在访问服务器的时候,服务器通过别的服务器获取资源或结果返回给客户端。

协程了解吗(高频)

协程和微线程是一个东西。
协程就是子程序在执行时中断并转去执行别的子程序,在适当的时候又返回来执行。
这种子程序间的跳转不是函数调用,也不是多线程执行,所以省去了线程切换的开销,效率很高,并且不需要多线程间的锁机制,不会发生变量写冲突。

那协程的底层是怎么实现的,怎么使用协程?

协程进行中断跳转时将函数的上下文存放在其他位置中,而不是存放在函数堆栈里,当处理完其他事情跳转回来的时候,取回上下文继续执行原来的函数。

进程的状态以及转换图

三态模型
三态模型包括三种状态:

  1. 执行:进程分到CPU时间片,可以执行
  2. 就绪:进程已经就绪,只要分配到CPU时间片,随时可以执行
  3. 阻塞:有IO事件或者等待其他资源

五态模型

  1. 新建态:进程刚刚创建。
  2. 就绪态:
  3. 运行态:
  4. 等待态:出现等待事件
  5. 终止态:进程结束

七态模型

  1. 新建态
  2. 就绪挂起态
  3. 就绪态
  4. 运行态
  5. 等待态
  6. 挂起等待态
  7. 终止态
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值