【后台研发岗】面试精华总结(地表最全)。操作系统+Linux专题(持续更新)

文章目录



进程是什么?有哪几种状态?

进程是运行中的程序,程序只是静态的指令的集合。
进程包括指令数据段以及PCB(进程控制块)。是操作系统分配资源的最小单位

进程有三种状态:阻塞态就绪态执行态

以read函数进程读取管道中内容为例:

  1. 当管道中没有数据时,进程read等待管道另一端写数据,此时进程为阻塞态。
  2. 写端向管道中写数据,进程read发现数据可读,等待CPU分配时间片,此时进程由阻塞态转为就绪态。
  3. 当CPU分配给read进程时间片,进行读取数据,进程由就绪态变为执行态。


僵尸进程,孤儿进程,守护进程是什么?

  • 孤儿进程

父进程提前退出,子进程仍然在运行,称子进程为孤儿进程孤儿进程对系统没有危害,产生孤儿进程后,有init进程来接管该孤儿进程(通过ps命令可以查看init进程的pid为1)。

  • 僵尸进程

子进程提前退出,父进程仍然在运行,称子进程为僵尸进程僵尸进程对系统有害,僵尸进程并不会释放拥有的进程号资源。如果出现了大量的僵尸进程占用资源,将会无法创建新的进程(通过ps命令可以查看僵尸进程的状态位z(zombie))。

解决僵尸进程的办法有两个:

  1. 是杀死父进程,僵尸进程将会转变为孤儿进程,此时init进程会来接管这些孤儿进程,资源得到回收。
  2. 父进程调用 wait 函数回收子进程资源;
  • 守护进程

一种特殊的孤儿进程,不论终端是否关闭,都会一直运行到系统关闭。

在Linux中我们可以使用top , ps 等指令查看进程的状态。



线程是什么?有哪几种线程?

线程是一种轻量级的进程是操作系统调度的最小单位

线程有两种类型:用户级线程内核级线程

  1. 内核级线程:内核态使用的线程。
  2. 用户级线程:用户态使用的线程。


进程与线程的区别?(多进程与多线程的区别?)

用一个形象的例子可以说明进程与线程之间的关系,将进程比作火车线程比作火车车厢

  1. 数据的共享与同步
    多进程的数据是分开的,共享较为困难,需要通过IPC,同步较为简单;多线程的数据是共享的,共享简单,但是同步困难。这一点各有优势。(好比不同的火车共享数据困难,同步简单;车厢之间共享数据简单,同步困难)。

  2. CPU与内存消耗
    多进程CPU利用率低,内存消耗大,切换复杂;多线程CPU利用率高,内存消耗小,切换简单。多线程占优。

  3. 创建销毁,切换
    多进程创建,销毁,切换速度慢;多线程较快。多线程占优。

  4. 编程调试
    多进程的编程,调试都简单;多线程的编程,调试都较复杂。多进程占优。

  5. 可靠性
    多进程之间不会相互影响;多线程之间会相互影响,一个线程挂掉导致整个进程挂掉。多进程占优。

  6. 分布式
    多进程适用于多核,多机分布,需要扩展到多台机器;多线程适用于多核。多线程占优。

总的来说,多线程更加节省CPU,内存以及时间,但是编程,调试都更加复杂,可靠性也不稳定;多进程则相反。选用哪一种方法需要根据具体情况而定。

在这里插入图片描述

那么相比于进程,哪些东西又是线程私有的?请见下一个问题。



哪些是线程私有的?

  1. 线程id:每一个线程都有自己的线程id,可以通过pthread_self()查看。

  2. 寄存器的值:线程需要不断进行切换,需要使用寄存器存放旧线程的状态。

  3. 函数堆栈:线程需要拥有属于自己的函数堆栈,使得函数调用可以正常进行。

  4. errno:错误返回码

  5. 线程优先级



集群,分布式的区别?

  • 集群

同一个业务,部署在多个服务器上面(不同的服务器运行同样的代码,干同一件事)。

  • 分布式

一个业务拆分成多个子业务,部署在不同的服务器上面(不同的服务器运行不同的代码,为了同一个目的)。



多核是什么意思?

多核也就是多内核,是指在一个处理器(CPU)中集成多个完整的计算引擎。



并发与并行的区别

  • 并发

单核CPU根据时间片的划分,依次处理多任务。

  • 并行

多核CPU同时处理多个任务。


举个例子:吃饭的时候接到电话,接了电话后继续吃饭,这是并发;一般吃饭一边接电话,这是并行。



大内核与微内核

  • 大内核

将操作系统的主要功能模块作为一个紧密联系的整体运行在内核态,优点是效率高,缺点是代码量过大难以维护。

  • 微内核

随着操作系统内核越来越复杂难以维护,于是提出了微内核的概念;微内核是将最基本的功能留在内核态,而其他功能放在用户态,大大降低了内核的复杂性,从而增加了可维护性,但是由于用户态与内核态之间的频繁切换,效率大大降低。



分时系统与实时系统

  • 分时系统

CPU划分多个时间片并发执行任务,相应时间较快,效率高。

  • 实时系统

规定截止时间内处理完并作出相应,有较高的安全性与可靠性,例如飞机订票,股票交易等。



32位的系统一个进程最多有多少内存空间?

32位系统意味着4G的寻址空间,在Linux中将其分为两个部分,0 ~ 3G为用户空间,3 ~ 4
G为内核空间。

补充:关于用户空间和内核空间的区别见下一个问题。



用户态与内核态的区别?(用户空间和内核空间的区别?)

内核态和用户态是操作系统运行的两种级别。在32位寻址的Linux系统中有4G的虚拟地址空间,0 ~ 3G分为用户空间,3 ~ 4G分为内核空间。

  • 内核态

内核空间存放的是内核代码和数据,权限较高,可以访问所有的内存空间和对象,CPU不会被抢占。如 系统调用 和 操作硬件 都处在内核态。

  • 用户态

用户空间存放的是用户程序的代码和数据,权限较低,能访问的内存空间和对象受限,CPU可被抢占。 大部分用户使用的应用程序都是在用户态。



库函数与系统调用的区别

  1. 本质

库函数是可以自己编写的函数,发生在用户地址空间;而系统调用属于内核提供的API,发生在内核空间。 如fread属于库函数,如read,write,open属于系统调用。

  1. 开销方面

库函数的开销较小;系统调用需要经过用户态,内核态,用户态的转换,所以开销较大。

  1. 移植性方面

库函数较容易移植,而系统调用由于不同操作系统之间的差异较大,移植较困难。



上下文切换

上下文切换是指CPU挂起一个进程/线程,去执行另一个进程/线程

上下文切换只能发生在内核态,是多任务操作系统的一个特点。不过由于上下文的高速切换,在用户眼中仿佛任务是同时处理的一样。



多线程锁的种类?(linux多线程锁?)

  1. 互斥锁(pthread_mutex_t)

最为常用的锁,任意时刻只能有一个线程能访问加锁资源。

  1. 递归锁(pthread_mutex_recursive)

相比于互斥锁无法对同一个资源多次加锁或解锁,递归锁可以对同一个资源进行多次加锁和解锁。

  1. 自旋锁(pthread_spinlock_t)

相比于互斥锁在阻塞状态会让出cpu去忙其他事务,自旋锁在阻塞状态下并不会让出cpu而是一直占用cpu直到得到锁,这样减小了cpu上下文切换的时间,多用于内核中消耗时间较少临界区。

  1. 读写锁(pthread_rdlock_t)

该锁区分读和写操作,加写锁时其他线程只能进行读操作,加读锁的时候多个线程可以对该临界资源加读锁。



Linux系统中有哪些同步机制?(重点)

  1. signal信号同步

  2. 信号量

  3. 锁的机制(详见上一个问题)

  4. 原子操作



什么是半双工管道?全双工管道?

  • 单工管道:只有一端可以使用,用作读或者写。

  • 半双工管道:两端都可以使用,但只能一端读一端写,数据单向流动。

  • 全双工管道:两端都可以使用,且每一端均可读写,数据双向流动。



进程间(IPC:Interprocess communication)通信方式有哪些?

  1. 管道
    管道分为无名管道有名管道两种,速度较慢,且容量有限。
    无名管道(pipe):通过 pipe()函数 创建,存在于内存之中,且只能在亲属进程之间使用。
    有名管道(FIFO):通过 mkfifo命令 创建,即使不是亲属进程也可以通信。

pipe和FIFO用来实现进程间相互发送非常小的,频率高的消息;这两种方式适用于两个进程间的通信。

  1. 消息队列
    由消息组成的链表,存放在内存中。此方法不太常用。

  2. 信号量
    主要作为锁机制,可以作为同步机制,不能用于传递复杂的消息。

  3. 共享内存
    映射一段能够被其他进程所访问的内存。是最快的IPC方式,共享内存用来实现进程间共享非常庞大的,频率高的消息;此方法适用于多进程之间的通信。常常和信号量等方式配合使用。

  4. socket套接字
    Socket套接字也是一种进程间通信机制,与其他通信机制不同的是,它可以用于不同主机的进程间通信。

  5. signal信号
    用于通知接收进程某个事件已经发生,主要用于同步。



如何选择进程间的通信方式?

  • Pipe和FIFO用来实现进程间相互发送非常小的,频率高的消息;这两种方式适用于两个进程间的通信

  • 共享内存用来实现进程间共享非常庞大的,频率高的消息;此方法适用于多进程之间的通信

  • 其余主要使用socket



线程池中多线程的线程数该如何设置?

可以分为以下两种情况进行分析:

  1. CPU密集型(需要进行大量计算的类型)

线程数 = CPU核数 + 1

  1. IO密集型(需要进行大量IO操作的类型)

线程数 = CPU核数 * 2



操作系统的进程调度算法有哪些?

  1. 先来先服务(FCFS)
    算法原理是哪一个进程先到达,就先服务哪一个进程。
    属于非抢占式算法,有利于长作业,不利于短作业,总体效率不好。

  2. 短作业优先(SJF)
    算法原理是优先处理短作业。
    属于非抢占式算法,有利于短作业,不利于长作业,总体效率不好。

  3. 高响应比优先
    优先处理高响应比的作业,响应比=(等待时间+服务时间)/ 服务时间
    属于非抢占式算法,该算法介于FCFS和SJF两种算法之间。

  4. 优先级队列
    为每一项作业设置好优先级,先处理优先级高的作业。
    有抢占式也有非抢占式。

  5. 时间片轮转(RR)
    将CPU的处理时间划分为若干个时间片,分别去处理各个作业。
    该算法常常用于分时系统,并且简单有效。

  6. 多级反馈队列
    是比较好的一种任务调度算法,这也是linux系统使用的进程调度算法。
    本质上是 优先级队列算法+ RR 算法。 设置多个优先级队列,所有队列都采取FCFS的原则,并且队列优先级越大,分配的时间片越大。当有新的进程加入时,加入第一个优先级队列。具体可参考多级反馈队列调度算法



linux的任务调度机制是什么?

Linux采用 多级反馈队列算法 调度进程(见上一个问题第6点)。



死锁是什么?

死锁是指多个线程因竞争资源而造成的相互等待。

死锁形成的条件(必须同时满足下面的四个条件):

  1. 互斥条件
    线程对于资源的占有必须是互斥的。

  2. 不可剥夺条件
    不能强行剥夺线程对资源的占有权。

  3. 请求且保持条件
    线程在请求其他的资源时,会保持自己拥有的资源。

  4. 循环等待条件
    一个线程在等待另一个线程释放资源,从而形成一个循环等待链。



如何解决死锁问题?

  1. 鸵鸟策略
    直接忽视死锁,解决死锁的代价很高,并且发生死锁的概率很低时,可以直接忽视死锁。

在Linux,Windos系统中解决死锁的办法仅仅是忽略它。

  1. 死锁预防
    设定限制条件,从而让形成死锁的四个条件不再成立。如当资源不再互斥,打破互斥形成死锁的条件。

  2. 死锁避免
    通过一系列资源分配策略,从而避免形成死锁,比如经典的银行家算法

  3. 死锁检测与解除
    检测到死锁后进行解除。比如直接剥夺进程拥有的资源。



可重入函数与不可重入函数?如何编写不可重入函数?

  • 可重入函数:可以被打断,重新进入的函数。

  • 不可重入函数:不可以被打断,不能够重新进入的函数。不可重入函数由于拥有了一些公共资源,如果被中断重新进入则会出现问题。

满足下列条件的函数属于不可重入函数:

  1. 使用了静态,全局的变量;
  2. 调用malloc,free函数;
  3. 调用标准IO函数。


静态链接和动态链接的区别?

  • 动态链接

相当于只是建立一个引用,而真正的代码和数据都存放在另外的目标模块中,在可执行文件运行时再装入该目标木块。此时程序较小,但是需要依赖环境变量。

  • 静态链接

相当于把所有的代码和数据都复制到目标模块中,真正运行的时候就不再需要库了。此时程序较大,但是不需要依赖环境变量。



静态库与动态库的区别?

要了解静态库与动态库,得先了解静态链接和动态链接的区别(见上一个问题)。

首先库是一种编译好的二进制代码。

  • 静态库:静态链接需要的库,例如<stdio.h>就是静态库。
  • 动态库:动态链接需要的库,例如Posix多线程的-lpthread就是链接动态库。

编写库的目的有两个:

  1. 不希望别人看到源码。
  2. 对于不会再修改的代码,将其做成库,减少编译成本。


软链接与硬链接的区别?

  • 软链接

也称为符号链接,类似于创建Windos的快捷方式。相当于对该inode节点创建了一个快捷方式。

  • 硬链接

类似于引用计数的概念。假设A文件和B文件同时硬链接向一个inode节点,该inode节点的引用计数就为2,当inode节点的引用计数为0时删除该inode节点。



程序编译到运行的流程?

预编译->编译->汇编->链接->执行

  • 预编译:进行宏替换以及头文件展开等
  • 编译:将高级语言编译为汇编语言
  • 汇编:将汇编语言转换成二进制代码(.o文件)
  • 链接:将多个二进制文件链接成为可执行文件
  • 执行:运行程序


逻辑地址与物理地址是什么?

  • 逻辑地址

又称为虚拟地址,也就是在程序编译时将目标模块从0开始编址,装入内存之后再转换成物理地址,从0开始编制的地址就称为逻辑地址。例如C语言中的取地址操作符(&)就是求的逻辑地址。

  • 物理地址

又称为绝对地址,是加载到内存单元中的真正物理地址。


一般来说,从逻辑地址到物理地址有两种方式:分页和分段。操作系统根据映射表,将逻辑地址转换为物理地址。



简述分页系统?

  1. 组成

分页系统是将 磁盘区分为固定大小的数据块,称为页;也将 内存分为固定大小的数据块,称为页框,程序载入时,将页装入页框中,缺页中断时也是将需要的页放入页框中。

  1. 地址结构

分页系统分为 页号+页偏移。地址空间最有有 220 页,页内偏移量为4KB。

在这里插入图片描述

  1. 页表
    作用是实现 页号->物理块号 的地址映射。

在这里插入图片描述



简述分段系统?

  1. 组成

分段系统是程序员人为对代码进行分段在高级编程语言中由编译器帮助我们完成;例如C++的分段系统将内存段划分为:堆段,栈段,代码段,全局静态变量段,文字常量段。

  1. 地址结构

分段系统分为 段号+段内偏移,最多有 216 个段,每个段大小为 64KB。
在这里插入图片描述

  1. 段表

作用是实现 段号->物理块号 的 地址映射。

在这里插入图片描述



分页与分段的区别?

  1. 分页的目的在于实现虚拟内存以便拥有更大的内存空间;分段的目的在于将代码与数据进行分区以便共享以及保护。

  2. 分页对于程序员是透明的,由操作系统直接帮助我们完成;而分段则是在编译过程中进行的,需要程序员自己设定,在高级语言中由编译器帮助划分段。

  3. 分页系统由于页的大小相同,地址空间是一维的;分段系统由于段长不相同,所以地址空间是二维的。

  4. 分页系统属于固定分区,会产生内部碎片;分段系统属于动态分区,会产生外部碎片。



虚拟内存是什么?

虚拟内存实质上就是将硬盘中的一部分当做内存来使用,从而创建了一个比实际内存大得多的虚拟内存
原理在于程序装入内存时将需要使用的部分调入,不需要使用的部分调出到磁盘
虚拟内存通过分页系统实现。



页面置换算法有哪些?

  1. 最佳置换算法(OPT)
    将之后不会使用的页面调出内存,由于并不知道之后会不会使用哪些页面,所以这种理想算法无法实现。

  2. LRU算法
    将最近最久没有使用的页面调出内存。

  3. FIFO算法
    先进先出式算法,会出现Belady异常。



简述Linux文件系统结构?

Linux的哲学是万物皆文件,文件系统结构是树结构,文件类型包括普通文件目录文件

每一个文件由两部分构成:

  1. inode节点号
    每一个文件都会占用一个inode,inode的数据结构可以通过 man fstat命令 查看。

  2. block
    用于记录文件的内容。
    在读取一个文件时,首先找到其inode,然后根据inode找到block并进行读取。



写一个c程序判断系统是32位还是64位的?

cout << sizeof(long) << endl;

如果是32位系统则输出4;
如果是64位系统则输出8。



写一个c程序判断系统是大端字节序 还是 小端字节序?

大端模式就是高位优先存放,小端模式就是低位优先存放
如数据 0x12345678

  • 大端模式:0x12345678
  • 小端模式:0x78563412
int main()
{
    short a = 0x1234;
    char b = static_cast<char>(a);
    if (b == 0x12)
        cout << "大端模式" << endl;
    else if (b == 0x34)
        cout << "小端模式" << endl;
    
    return 0;
}



有哪些常见的信号?

可以通过 kill –l 命令查看信号。

  • SIGINT
    中断进程信号,ctrl+c 实现;

  • SIGTSTP
    任务挂起信号,可以通过 fg/bg 命令将其重新放到前台或者后台执行,ctrl+z实现;该信号与SIGSTOP的区别在于SIGSTOP不能够被捕捉或者忽略。

  • SIGKILL
    杀死进程信号,kill -9 pid 实现。

注意:其中SIGKILLSIGSTOP信号不能够被捕捉或者忽略。



i++是原子操作吗?为什么?

i++不是原子操作,因为i++的操作分为了3个阶段(读,写,改):

  1. 从内存读取到寄存器;
  2. 寄存器中进行自加;
  3. 将结果写回内存;

这三个阶段可以被割断,所以不是原子操作。



exit(0),exit(1),return的区别?

  1. exit是程序的退出,return属于函数的退出。

  2. return是C语言中的关键字;exit是系统调用函数。

  3. exit(0)代表程序正常退出,exit(1)代表程序非正常退出;return代表函数返回值。程序员可以通过echo $? 命令查看程序的exit值,从而判断程序是否产生错误。



守护进程如何实现?

守护进程是一种特殊的后台程序,会一直运行到系统关闭。

创建守护进程有五个步骤:

  1. fork()
    创建子进程,终止父进程。

  2. setsid()
    在子进程中创建新的会话,让其摆脱原终端的控制,成为独立的会话。

  3. chdir(“/”)
    由于fork中子进程继承了父进程的工作目录,所以需要改变工作目录。

  4. umask(0)
    由于fork中子进程继承了父进程的文件创建掩码,所以需要改变掩码为0。

  5. close(i)
    由于fork中子进程继承了父进程的文件描述符,所以需要关闭描述符防止消耗系统资源。

总结:创建子进程->成为独立会话->改变fork继承不必要的东西


  • 实例:创建守护进程,向系统日志中定期写入信息。写完后可以通过 sudo cat /var/log/syslog |tail 20 命令查看结果。
void daemon()
{
    if (fork() > 0)
        exit(0);
    setsid();
    chdir("/");
    umask(0);
    for (int i = 0; i < 64; i++)
        close(i);
    int cnt = 0;
    while (cnt < 10)
    {
        syslog(LOG_INFO, "this is %d message", cnt);
        cnt ++;
        sleep(1);
    }
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园的建设目标是通过数据整合、全面共享,实现校园内教学、科研、管理、服务流程的数字化、信息化、智能化和多媒体化,以提高资源利用率和管理效率,确保校园安全。 智慧校园的建设思路包括构建统一支撑平台、建立完善管理体系、大数据辅助决策和建设校园智慧环境。通过云架构的数据中心与智慧的学习、办公环境,实现日常教学活动、资源建设情况、学业水平情况的全面统计和分析,为决策提供辅助。此外,智慧校园还涵盖了多媒体教学、智慧录播、电子图书馆、VR教室等多种教学模式,以及校园网络、智慧班牌、校园广播等教务管理功能,旨在提升教学品质和管理水平。 智慧校园的详细方案设计进一步细化了教学、教务、安防和运维等多个方面的应用。例如,在智慧教学领域,通过多媒体教学、智慧录播、电子图书馆等技术,实现教学资源的共享和教学模式的创新。在智慧教务方面,校园网络、考场监控、智慧班牌等系统为校园管理提供了便捷和高效。智慧安防系统包括视频监控、一键报警、阳光厨房等,确保校园安全。智慧运维则通过综合管理平台、设备管理、能效管理和资产管理,实现校园设施的智能化管理。 智慧校园的优势和价值体现在个性化互动的智慧教学、协同高效的校园管理、无处不在的校园学习、全面感知的校园环境和轻松便捷的校园生活等方面。通过智慧校园的建设,可以促进教育资源的均衡化,提高教育质量和管理效率,同时保障校园安全和提升师生的学习体验。 总之,智慧校园解决方案通过整合现代信息技术,如云计算、大数据、物联网和人工智能,为教育行业带来了革命性的变革。它不仅提高了教育的质量和效率,还为师生创造了一个更加安全、便捷和富有智慧的学习与生活环境。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值