高频知识汇总 您所在的位置:网站首页 数据库面试真题汇总 高频知识汇总

高频知识汇总

2023-12-10 12:50| 来源: 网络整理| 查看: 265

我之前也已经在牛客写了好几篇互联网相关的求职经验、高频知识点汇总的文章了,简要介绍一下,有需要的同学可以点进去先收藏,之后用到时可以看一看。如果有帮助的话,希望大家给个赞,给个收藏!有疑问的也可以在评论区留言讨论,能帮的上大家的都会尽力回复的!

总章,按时间段记录了我整个互联网求职的过程我是如何从零基础拿到第一份实习的(各个时间段的实操经验分享) 刷题经验,里面包含按类划分的高频题号,并且每类题下都有我汇总收藏的优质博客:高频知识总结 | 算法题如何刷?我的高效刷题方法 面经总结,包含我的实习和秋招的面试真题:高频知识总结 | 我的实习和秋招互联网高频面试题分享 我的银行科技岗求职经历分享,从前期准备到笔面考试内容都有:我和牛客的故事—银行科技岗经验分享(干货满满+经验帖汇总) 前言

这篇【操作系统】是我在学习时自己整理的,大部分都是按我个人的理解来写的答案。

当时我在学习八股文时有一个痛点,就是在复习时也是搜罗了很多很多的总结资料,但有些资料不能说他不好,但放的知识太多,太全面了,比如文件管理一般面试中碰到的概率很小很小,所以跟这部分内容相关的我就只了解了磁盘读写的速度、缓存读写速度、内存读写速度等的各种差异和对比,别的就没再多了解了。

所以这篇文章已经经过我的筛选,把最重要、最常问的知识点给整了出来,你至少需要先把这些全都掌握再去看别的进阶、更全面的知识!

并且我还在必要的知识点下还留了各种补充链接,可以直接点进去看!非常适合一个知识点接着一个知识点的来攻克!所以刷到这里,先点点关注和收藏,之后我看时间还会把我总结的计算机网、数据库的知识都排一下版发出来。

废话不多说,直接开始铺干货。

1. 操作系统概述 1.1 系统调用 / 用户态和内核态

根据进程访问资源的特点,我们可以把进程在系统上的运行分为两个级别:

用户态(user mode) : 用户态运行的进程可以直接读取用户程序的数据。 系统态(kernel mode):可以简单的理解系统态运行的进程或程序几乎可以访问计算机的任何资源,不受限制。 1.2 说了用户态和系统态之后,那么什么是系统调用呢? 我们运行的程序基本都是运行在用户态,如果我们调用操作系统提供的系统态级别的子功能咋办呢?那就需要系统调用了! 也就是说在我们运行的用户程序中,凡是与系统态级别的资源有关的操作(如文件管理、进程控制、内存管理等),都必须通过系统调用方式向操作系统提出服务请求,并由操作系统代为完成。

这些系统调用按功能大致可分为如下几类:

设备管理。完成设备的请求或释放,以及设备启动等功能。 文件管理。完成文件的读、写、创建及删除等功能。 进程控制。完成进程的创建、撤销、阻塞及唤醒等功能。 进程通信。完成进程之间的消息传递或信号传递等功能。 内存管理。完成内存的分配、回收以及获取作业占用内存区大小及地址等功能。 1.3 那么如何从用户态切换到内核态呢?(仅需知道是这哪三种就可以了,其实一般只会问到举几个系统调用的例子) 系统调用这是用户态进程主动要求切换到内核态的一种方式,用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作,比如 read 操作,比如前例中 fork() 实际上就是执行了一个创建新进程的系统调用。而系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现,例如Linux的int 80h中断。 异常当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。 外围设备的中断当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。

这3种方式是系统在运行时由用户态转到内核态的最主要方式,其中系统调用可以认为是用户进程主动发起的,异常和外围设备中断则是被动的。

1.4 其他必会知识

并行与并发并发:在操作系统中,某一时间段,几个程序在同一个CPU上运行,但在任意一个时间点上,只有一个程序在CPU上运行。并行:两个程序在某一时刻同时运行,强调同时发生。

阻塞与非阻塞阻塞是指调用线程或者进程被操作系统挂起。非阻塞是指调用线程或者进程不会被操作系统挂起。

同步与异步同步与异步同步是阻塞模式,异步是非阻塞模式。同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,知道收到返回信息才继续执行下去;异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回式系统会通知进程进行处理,这样可以提高执行的效率。

2. 进程管理 2.1 线程、进程、协程的区别

答:

进程是资源分配的最基本的单位,运行一个程序会创建一个或多个进程,进程就是运行起来的可执行程序。 线程是程序执行的最基本的单位,是轻量级的进程,每个进程里都有一个主线程,且只能有一个,和进程是相互依存的关系,生命周期和进程一样。 协程是用户态的轻量级线程,是线程内部的基本单位。无需线程上下文切换的开销、无需原子操作锁定及同步的开销、方便切换控制流,简化编程模型。

进程和线程的区别的话

首先从资源来说,进程是资源分配的基本单位,但是线程不拥有资源,线程可以访问隶属进程的资源。 然后从调度来说,线程是独立调度的基本单位,在同一进程中线程切换的话不会引起进程的切换,从一个进程中的线程切换到另一个进程中的线程时,会引起进程的切换。 从系统开销来讲,由于创建或撤销进程,系统都要分配回收资源,所付出的开销远大于创建或撤销线程时的开销。类似的,在进行进程切换的时候,涉及当前执行进程 CPU 环境的保存及新调度进程 CPU 环境设置,而线程切换只需保存和设置少量寄存器的内容,开销很小。 通信方面来说,线程间可以通过直接读写同一进程的数据进行通信,但是进程通信需要借助一些复杂的方法。 2.2 PCB是什么?(我字节同一个岗的连着两面被问到PCB) PCB主要包含下面几部分的内容: 进程的描述信息,比如进程的名称,标识符, 处理机的状态信息,当程序中断是保留此时的信息,以便 CPU 返回时能从断点执行 进程调度信息,比如阻塞原因,状态,优先级等等 进程控制和资源占用,同步通信机制,链接指针(指向队列中下一个进程的 PCB 地址) PCB 的作用 PCB是进程实体的一部分,是操作系统中最重要的数据结构 由于它的存在,使得多道程序环境下,不能独立运行的程序成为一个能独立运行的基本单位,使得程序可以并发执行 系统通过 PCB 来感知进程的存在。(换句话说,PCB 是进程存在的唯一标识) 进程的组成可以用下图来表示,PCB 就是他唯一标识符。图片说明 2.3 进程和线程创建和撤销的过程中发生了什么事情?(问的不多,我被问到过一次)

进程允许创建和控制另一个进程,前者称为父进程,后者称为子进程,子进程又可以创建孙进程,如此下去进而形成一个进程的家族树,这样子进程就可以从父进程那里继承所有的资源,当子进程撤销时,便将从父进程处获得的所有资源归还,此外,撤销父进程,则必须撤销所有的子进程。(撤销的过程实际上就是对这棵家族树进行后序遍历的过程)在应用中创建一个子进程的过程如下:

申请空白的PCB 初始化进程描述信息 为进程分配资源以及地址空间 将其插入就绪队列中

当进程完成后,系统会回收占用的资源,撤销进程,而引发进程撤销的情况有:进程正常结束或者异常结束,外界的干预(比如我们在任务管理器中强制停止某个进程的运行)。

查找需要撤销的进程的 PCB 如果进程处于运行状态,终止进程并进行调度 终止子孙进程 - 归还资源 将它从所在的队列中移除 2.4 进程的五种状态

面试在答的时候这么答:有创建状态、就绪状态、运行状态、阻塞状态、结束状态。

其中只有就绪状态和运行状态能互相转化,当进程为就绪态时,等待 CPU 分配时间片,得到时间片后就进入 运行状态 运行状态在使用完 CPU 时间片后,又重回就绪态。 阻塞状态是进程在运行状态时,需要等待某个资源比如打印机资源,而进入一个挂起的状态,等资源拿到后会回到就绪状态,等待 CPU 时间片。 2.5 进程调度算法(面试高频知识点)

这个看cyc大佬总结的,按批处理系统和交互式系统去记忆比较容易记住。点这里:cycBook

2.6 进程同步的方式

临界区首先对临界资源的访问那段代码被称为临界区,为了互斥的访问临界区,每个进程在进入临界区时,都需要先进行检查,也就是查看锁。

同步与互斥同步:多个进程因为合作产生的直接制约关系,使得进程有一定的先后顺序。互斥:多个进程在同一时刻只有一个进程能进入临界区。

信号量信号量是一个整型变量,可以对其执行 P 和 V 操作。P:如果信号量大于零,就对其进行减 1 操作;如果信号量等于 0,进程进入 waiting 状态,等待信号量大于零。V:对信号量执行加 1 操作,并唤醒正在 waiting 的进程如果信号量只能取 0 或者 1,那么就变成了互斥量,其实也可以理解成加锁解锁操作,0 表示已经加锁,1 表示解锁。

管程使用信号量机制实现的生产者消费者问题需要客户端代码做很多控制,而管程把控制的代码独立出来,不仅不容易出错,也使得客户端代码调用更容易。管程有一个重要特性:在一个时刻只能有一个进程使用管程。进程在无法继续执行的时候不能一直占用管程,否则其它进程永远不能使用管程。管程引入了 条件变量 以及相关的操作:wait() 和 signal() 来实现同步操作。对 条件变量 执行 wait() 操作会导致调用进程阻塞,把管程让出来给另一个进程持有。signal() 操作用于唤醒被阻塞的进程。

2.7 进程间通信的方式(重要!)

建议把BiliBili王道考研的这一节课给看了进程通信和进程同步很容易混淆,其实可以把进程通信当成一种手段,进程同步是一种目的,为了实现进程同步,可传输一些进程同步所需要的信息。

管道

匿名管道:举个例子:linux 里的竖线,就是管道的意思,比如 ps -aux|grep mysql 这句话的意思是把前一个进程查询的结果作为 grep mysql 的输入,如果两个进程要进行通信的话,就可以用这种管道来进行通信。这种通信的方式是半双工通信的,只能单向交替传输并且只能在具有亲属关系的进程之间通信使用。可以看成是一种特殊的文件,但是这种文件只能存在于内存之中。 命名管道:可以用 mkfifo 命令创建一个命名管道,可以用一个进程向管道里写数据,然后可以让另一个进程把里面的数据读出来。命名管道的优点是去除了只能在父子进程中使用的限制,并且命名管道有路径名和它相关联,是以一种特殊设备文件形式存在于文件系统中的。图片说明

消息队列

消息队列的通信模式是这样的:a 进程要给 b 进程发消息,只需要把消息挂在消息队列(可以是中介邮局,也可以是进程自己的信箱)里就行了,b 进程需要的时候再去取消息队列里的消息。 消息队列可以独立于读写进程存在,就算进程终止时,消息队列的内容也不会被删除。 读进程可以根据消息类型有选择的接收消息,而不像 FIFO 那样只能默认接收。图片说明如果进程发送的数据较大,并且两个进程通信非常频繁的话,消息队列模型就不太合适了,因为如果发送的数据很大的话,意味着发送消息(拷贝)这个过程就需要很多时间来读写内存。

共享内存

共享内存的方式就可以解决拷贝耗时很长的问题了。 共享内存是最快的一种进程通信的方式,因为进程是直接对内存进行存取的。因为可以多个进程对共享内存同时操作,所以对共享空间的访问必须要求进程对共享内存的访问是互斥的。所以我们经常把信号量和共享内存一起使用来实现进程通信。 (这里补个知识!!!系统加载一个进程的时候,分配给进程的内存并不是实际的物理内存,而是虚拟内存空间。那么我们可以让两个进程各自拿出一块儿虚拟地址空间来,映射到同一个物理内存中。这样两个进程虽然有独立的虚拟内存空间,但有一部分是映射到相同的物理内存,这样就完成共享机制了。)

信号量

共享内存最大的问题就是多进程竞争内存的问题,就像平时所说的线程安全的问题,那么就需要靠信号量来保证进程间的操作的同步与互斥。 信号量其实就是个计数器,例如信号量的初始值是 1,然后 a 进程访问临界资源的时候,把信号量设置为 0,然后进程 b 也要访问临界资源的时候,发现信号量是 0,就知道已有进程在访问临界资源了,这时进程 b 就访问不了了,所以说信号量也是进程间的一种通信方式。 套接字套接字可以实现两个不同的机器之间的进程通信,比如 socket 使用。 2.8 生产者消费者模型(要会写伪代码)

生产者和消费者模型,期间就需要线程之间进行通信来实现互斥和同步。

需求是这样的:

生产者每生成一个产品,就消耗一个缓冲区,只有当缓冲区不满的时候才能放入; 消费者每消费一个产品,就消耗一个产品,只有当缓冲区不空的时候才能消费。

做法:

因为缓冲区是临界资源,所以需要定义一个互斥信号量,为 mutex 来实现两者对临界资源的互斥访问。 为了同步生产者和消费者的操作,需要记录缓冲区的剩余大小 empty 和 产品的个数 full。当缓冲区大小不为 0 时,生产者才能放入产品;当产品个数不为 0 时,消费者才能拿走产品。 注意!不可对临界区先加锁,设想这样一个情况:当 empty = 0 时,生产者此时先对临界区加锁,然后发现缓冲区的数量为 0,则开始进入阻塞等待消费者消费的状态,而此时一个消费者开始进入消耗一个产品,但发现临界区被加锁,所以生产者在等待消费者消费产品,而消费者在等待生产者释放临界区锁,进入了一个死锁状态。

伪代码如下

mutex = 1; empty = N; full = 0; void Producer() { P(empty); // 生产者生产一个产品,消耗一个缓冲区 P(mutex); .... // 临界区 V(mutex); V(full); // 产品数量加1 } void Consumer() { P(full); // 消费者消耗一个产品,释放一个缓冲区 P(mutex); // 临界区上锁 .... V(mutex); // 临界区锁释放 V(empty); // 增加一个缓冲区 } void P(S){ S--; if(S < 0) block(); // 如果小于0,代表资源没了 } void V(S){ S++; if(S


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有