Linux内核、操作系统、单片机面试八股

Linux内核

1 Linux内核的组成⭐⭐

  1. 进程管理:负责创建、调度、终止和管理进程。包括进程调度、进程间通信(IPC)和进程状态管理。
  2. 内存管理:负责分配和释放系统内存,以及虚拟内存的管理。包括物理内存管理、虚拟内存管理、页面置换算法等。
  3. 文件系统:负责管理文件和目录,以及提供对文件的读写和操作。它支持各种文件系统类型,如ext4、FAT32等,并隐藏了各种硬件的具体细节,为所有设备提供了统一的接口。
  4. 设备驱动:允许内核与硬件设备进行通信。Linux内核包含了大量的设备驱动程序,用于管理和控制硬件设备。
  5. 网络子系统:提供了对各种网络标准的存取和各种网络硬件的支持。它可分为网络协议和网络驱动程序,其中网络协议部分负责实现每一种可能的网络传输协议。

2用户空间与内核通信方式有哪些?⭐⭐⭐⭐⭐

  1. 系统调用:这是用户空间程序请求内核服务的一种方式。用户空间程序通过系统调用来与内核进行通信,从而获取内核提供的各种服务,如文件操作、进程控制等。
  2. 信号:当内核空间出现一些异常情况时,会发送信号给进程。这些信号可以用于通知用户空间程序某些事件的发生,如进程终止、定时器到期等。
  3. /proc接口:/proc文件系统是一个伪文件系统,它允许用户空间程序读取内核空间的配置信息和运行状态,甚至可以设置部分属性的值。通过这种方式,用户空间程序可以获取内核的一些状态和参数,实现与内核的通信。
  4. 文件操作:虽然这不是直接的用户空间与内核空间的通信方式,但用户空间程序可以通过对特定文件的读写操作来实现与内核的间接通信。例如,一些设备文件就允许用户空间程序通过读写操作与内核中的设备驱动程序进行通信。
  5. netlink套接字:netlink套接字提供了一种在用户空间和内核空间之间进行通信的机制。它类似于普通的socket通信方式,但特别适用于内核与用户空间之间的通信。netlink套接字可以支持大量的数据传输,并且可以实现相对复杂的通信功能。
  6. ioctl系统调用:ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。通过ioctl,用户空间的程序可以对设备的I/O通道进行管理,例如配置设备、读取设备的状态等。ioctl机制可以在驱动中扩展特定的ioctl消息,用于将一些状态从内核反映到用户态。然而,ioctl不适合传输大量的数据,通常与内存映射机制结合使用来完成大量数据交换过程。

3系统调用read()/write(),内核具体做了哪些事情⭐⭐

  1. 参数验证:首先,内核会检查传递给 read() 的参数是否有效。这包括检查文件描述符是否有效,以及缓冲区指针和大小是否合法。

  2. 查找文件描述符对应的文件对象:内核会根据文件描述符找到对应的文件对象,这通常涉及查找进程的文件描述符表。

  3. 权限检查:确保调用进程有权限读取目标文件或设备。

  4. 读取(写入)数据

  5. 更新文件偏移量:对于普通文件,读取(写入)操作完成后,内核会更新文件的当前偏移量,以便下一次读取(写入)操作从正确的位置开始

  6. 返回读取(写入)的字节数:内核将实际读取的字节数返回给调用进程。如果到达文件末尾或发生错误,返回的值会小于请求的字节数。

    额外考虑:

  • 并发和同步:在多进程环境中,内核需要确保对文件的并发访问是安全的,可能需要使用锁或其他同步机制。

  • 缓存和缓冲:为了提高性能,内核可能会使用缓存或缓冲区来存储待读取或待写入的数据。这可以减少对磁盘或其他设备的直接访问次数。

  • 错误处理:如果在读取或写入过程中发生错误(如磁盘故障、内存不足等),内核会进行相应的错误处理,并可能向调用进程返回错误代码。

4系统调用的作用⭐⭐⭐⭐⭐

  1. 用户空间与内核空间的交互:系统调用是用户空间程序与内核空间进行交互的唯一方式。通过系统调用,用户空间的程序可以请求内核执行某些操作,如文件操作、进程管理、设备控制等。这种交互机制确保了用户空间程序能够利用内核提供的服务和资源

  2. 资源管理和保护:内核是操作系统的核心部分,负责管理系统的硬件和软件资源。通过系统调用,内核可以对资源进行管理和保护,防止用户空间的程序滥用资源或执行非法操作。例如,系统调用可以限制用户空间程序对文件的访问权限,确保文件的安全性和完整性。

  3. 提供抽象和统一接口:系统调用为用户空间程序提供了抽象和统一的接口,使得程序可以不必关心底层硬件的细节和操作系统的实现方式。这样,程序员可以更加专注于应用程序的开发,而不需要关心底层的复杂性和差异性。

  4. 实现操作系统功能许多操作系统的功能都是通过系统调用来实现的。例如,进程创建、终止、调度,内存分配和释放,文件读写,设备控制等都需要通过系统调用来完成。这些功能对于用户空间程序来说是至关重要的,它们使得程序能够正常运行并与其他程序和硬件设备进行交互。

  5. 安全性和稳定性:系统调用由内核实现,并经过严格的测试和验证,以确保其安全性和稳定性。通过系统调用,用户空间的程序可以获得经过内核审核和管理的服务,从而降低程序出错的可能性,提高系统的整体稳定性和安全性。

5内核态,用户态的区别⭐⭐⭐⭐⭐

  1. 权限级别
    • 内核态:具有最高权限级别,可以执行任何指令和访问任何内存地址。内核态下的代码通常是操作系统内核的一部分,负责管理系统资源、提供系统服务、处理硬件中断等。
    • 用户态:具有较低的权限级别,只能执行部分指令,并且只能访问分配给该用户程序的内存区域。用户态下的代码通常是应用程序的一部分,用于实现特定的功能。
  2. 功能职责
    • 内核态:负责系统的整体管理和控制,包括进程调度、内存管理、设备驱动、文件系统等。内核态下的代码需要处理各种系统级的事务,确保系统的稳定性和安全性。
    • 用户态:主要负责实现用户的具体需求,如文本编辑、图像处理、网络通信等。用户态下的代码主要关注于应用功能的实现,不需要关心底层系统的细节。
  3. 安全性
    • 内核态:由于具有最高权限,一旦内核态的代码出现错误或受到攻击,可能会对整个系统造成严重的后果。因此,内核态下的代码需要经过严格的测试和验证,以确保其安全性和稳定性。
    • 用户态:由于权限较低,即使用户态的代码出现错误或受到攻击,其影响通常也局限于该用户程序本身,不会对整个系统造成太大的影响。
  4. 执行效率
    • 内核态:由于内核态下的代码需要处理系统级的事务,其执行效率通常较高。然而,频繁地进入和退出内核态会导致上下文切换的开销,从而可能影响系统的整体性能。
    • 用户态:用户态下的代码通常不需要频繁地进入和退出内核态,因此其执行效率可能相对较高。但是,如果需要执行系统调用等需要与内核交互的操作,仍然需要切换到内核态

6 bootloader内核 根文件的关系⭐⭐⭐⭐

Bootloader(引导加载程序)是启动计算机系统的第一阶段软件,通常存储在计算机的固件中(如BIOS或UEFI)。它的主要任务是初始化硬件,包括CPU、嵌入式板级设备等,并建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态。在完成这些初始化任务后,Bootloader负责将Linux内核加载到系统内存中,并传递控制权给内核

内核是操作系统的核心,它管理系统的硬件和提供基本的系统服务。当内核从Bootloader中加载到内存中并执行时,它会进一步初始化硬件,建立虚拟内存映射等。内核还包括设备驱动程序、调度器、文件系统、网络协议栈等核心功能。

根文件系统(Rootfs)是文件系统的顶层,包含了操作系统运行所需的基本文件和目录结构。在Linux内核完成初始化后,需要挂载某个文件系统作为根文件系统。这个根文件系统提供了内核运行所需的各种库、配置文件、应用程序等。

因此,Bootloader、内核和根文件在嵌入式Linux系统中的关系可以概括为:Bootloader负责初始化硬件并加载内核;内核在启动时进一步初始化硬件,并挂载根文件系统;而根文件系统则提供了操作系统运行所需的基本文件和目录结构。这三个部分协同工作,共同构成了一个完整的嵌入式Linux系统。

7 Bootloader多数有两个阶段的启动过程:⭐⭐⭐

第一阶段主要使用汇编语言实现,其目标是完成一些依赖于CPU体系结构的初始化工作,并调用第二阶段的代码。在这一阶段,Bootloader会进行硬件设备初始化,为加载第二阶段的代码准备RAM空间,复制第二阶段的代码到RAM中,设置好栈,并跳转到第二阶段代码的C入口点。

第二阶段则通常使用C语言来实现,以提供更复杂的功能和更好的代码可读性与移植性。在这一阶段,Bootloader会初始化本阶段要使用的硬件设备,检测系统内存映射,并将内核映像和根文件系统从Flash上读到RAM空间中。此外,它还会为内核设置启动参数,并最终调用内核启动

8 linux的内核是由bootloader装载到内存中的?⭐⭐⭐

Linux的内核是由Bootloader装载到内存中的。Bootloader是系统启动或复位以后执行的第一段代码,它主要负责初始化处理器及外设,并将Linux内核从非易失性存储器(如Flash或DOC等)中拷贝到RAM中,然后跳转到内核的第一条指令处继续执行,从而启动Linux内核

Bootloader的是连接硬件和软件的关键桥梁,确保内核能够正确加载并运行。

9为什么需要BootLoader⭐⭐⭐⭐

  1. 硬件初始化:BootLoader是系统启动后运行的第一段代码,它负责初始化系统的硬件环境。这包括设置CPU的工作模式、初始化中断向量表、设置内存控制器的功能寄存器、设置时钟源和频率、初始化串口等。这些初始化步骤对于确保系统能够正常运行至关重要。

  2. 引导加载内核:BootLoader的核心任务之一是加载并启动操作系统的内核。它负责将内核映像从Flash存储器或其他存储介质中读取到RAM中,然后跳转到内核的入口点来启动内核。这个过程确保了操作系统内核能够在正确的环境中执行。

  3. 设置系统环境:除了加载内核,BootLoader还需要为内核的执行准备好正确的环境。这可能包括设置CPU寄存器和内存空间映射,初始化内核所需的数据结构,以及准备必要的参数传递给内核。这些参数可能包括内存布局、命令行参数、设备树等,它们对于内核的正确初始化至关重要。

  4. 支持多种操作系统:在一些复杂的嵌入式系统中,可能需要支持多种不同的操作系统或内核。BootLoader可以提供一个统一的启动框架,使得不同的操作系统或内核可以在相同的硬件平台上启动。这提高了系统的灵活性和可维护性。

  5. 提供调试接口:在嵌入式系统的开发过程中,调试是一个重要的环节。BootLoader通常提供了一些调试接口,如串口通信、JTAG接口等,使得开发者可以方便地与系统进行交互,查看系统状态、执行调试命令等。这对于快速定位和解决问题非常有帮助。

10 Linux内核同步方式总结⭐⭐⭐⭐

  1. 自旋锁(Spinlock):主要用于对行为时间很短的情况进行同步,即当需要读取或修改的数据只需要一瞬间就能使用时。当多个进程或线程同时请求同一个资源时,会不断地忙等待(自旋),直到该资源被占用者释放。由于不涉及内核状态转换,因此能够快速访问共享资源。
  2. 互斥锁(Mutex):具有已锁定和未锁定两种状态。在Linux内核中,互斥锁可以使用mutex_tsemaphore实现。
  3. 读写锁(Read-Write Lock):对读写操作进行区分,允许多个读取者同时访问资源,但写入者在进行写操作时会独占资源。
  4. 信号量(Semaphore):用于控制多个进程或线程访问同一资源的同步机制,可以限制同时访问特定资源的进程数量
  5. 顺序锁(SeqLock):也称为seq锁,提供一种简单的机制用于读写共享数据。它主要依靠一个序列计数器来实现,当需要写入数据时,会获得一个锁并增加序列值;在读取数据前后,序列值都会被读取,如果读取的序列值相同,则说明读操作过程中没有新的数据写入
  6. 关闭内核抢占:对于单处理器,在访问临界区期间不允许内核抢占也是一种同步方法。
  7. 大内核锁(Big Kernel Lock, BKL):在早期的Linux内核中,BKL是一个全局锁,用于保护整个内核。
  8. 完成变量(Completion Variable):如果在内核中一个任务需要发出信息号通知另一任务发生了某个特定事件,利用完成变量是使两个任务得以同步的简单方法。

11为什么自旋锁不能睡眠 而在拥有信号量时就可以?⭐⭐⭐⭐

自旋锁的设计初衷是为了保证数据修改的原子性,因此它不允许在锁住的区域内进行睡眠。当自旋锁被占用时,如果某个进程试图获取该锁,它会一直自旋等待(即忙等待),直到锁被释放。这种机制避免了进程状态的切换,从而提高了效率。然而,这也意味着在自旋锁持有期间,进程不能进入睡眠状态,因为睡眠会导致处理器被其他进程抢占,从而破坏了使用锁的目的

相比之下,信号量则是一种睡眠锁。当某个任务试图获取一个已被占用的信号量时,它会被推入一个等待队列并进入睡眠状态。这样,处理器可以重获自由去执行其他代码。当信号量变得可用时,处于等待队列中的任务会被唤醒并获得该信号量。这种机制允许在等待资源时释放处理器,提高了系统的负载能力。

此外,自旋锁通常用于短时间内等待的情况,因为它的忙等待特性不适合用于长时间的临界区代码。而信号量则更适用于运行时间较长的临界区代码,因为它允许进程在等待时进入睡眠状态。

12 linux下检查内存状态的命令⭐⭐⭐

  1. free命令
    free 命令是最常用且基础的内存查看命令,用于显示系统当前的内存使用情况,包括物理内存、交换内存(swap)和内核缓冲区内存。
  2. top命令
    top 命令是一个动态监视系统状态和性能的命令,它可以实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器。在top命令的输出中,你可以看到内存使用的实时数据。
  3. htop命令
    htop 是 top 命令的一个增强版,提供了一个彩色的界面和更多的交互选项,包括水平和垂直滚动,以便更轻松地查看和管理进程。
  4. vmstat命令
    vmstat 命令报告关于进程、内存、分页、块IO、陷阱和CPU活动的信息。
  5. sar命令
    sar 命令是系统活动报告程序,它可以用来收集、报告和保存系统活动信息。通过 sar,你可以查看历史的内存使用情况
  6. cat /proc/meminfo命令
    /proc/meminfo 文件包含了关于系统内存使用的详细信息。你可以使用 cat 命令查看这个文件的内容。

操作系统

1大小端的区别以及各自的优点,哪种时候用⭐⭐⭐⭐⭐

大端模式(Big Endian):高位字节存放在内存的低地址端,低位字节存放在内存的高地址端。这种模式的优点在于符号位在所表示的数据的内容的第一个字节中,便于快速判断数据的正负和大小。此外,大端模式也被广泛用作网络传输的字节序,如TCP/IP协议规定网络传输的字节序为大端字节序。

小端模式(Little Endian):低位字节存放在内存的低地址端,高位字节存放在内存的高地址端。小端模式的优点在于,当CPU做数值运算时,从内存中依次从低到高取数据进行运算直到最后刷新最高位的符号位,这种运算方式会更高效。此外,在强制类型转换数据时,小端模式不需要调整字节的内容,这在某些情况下可以提高处理效率。许多现代处理器,如Intel的x86系列和ARM的芯片,默认使用小端模式,但ARM的芯片也可以切换到大端模式。

2 一个程序从开始运行到结束的完整过程(四个过程)⭐⭐⭐⭐⭐

  1. 加载与预处理
    • 程序首先被加载到内存中。
    • 预处理阶段处理源代码中的预编译指令,如#include(包含头文件)、#define(宏定义)以及条件编译指令如#if#else#endif等。
    • 宏被替换,条件编译指令根据条件决定是否包含某部分代码。
    • 预处理结束后,生成一个修改后的源代码文件
  2. 编译
    • 编译阶段对预处理后的文件进行语法分析、词法分析、语义分析,并生成符号汇总。
    • 编译器将源代码转换为汇编代码,这是一个中间表示,比高级语言更接近机器语言。
    • 在这一过程中,所有的语法和语义错误都会被检测并报告。
  3. 汇编与链接
    • 汇编阶段将汇编代码转换成机器码,即二进制文件,这是机器可以直接执行的代码。
    • 汇编后生成的目标文件(如.o文件在Linux下,.obj文件在Windows下)包含了程序的二进制代码以及符号表,其中符号表为程序中的函数、变量等分配了虚拟地址。
    • 链接阶段将目标文件与系统中提供的库文件(如标准库、第三方库等)链接起来,解决目标文件中引用的外部符号问题。
    • 链接完成后,生成一个可执行文件(如.exe文件在Windows下)。
  4. 执行
    • 可执行文件被加载到内存中,操作系统为其分配所需的资源。
    • 程序开始执行,根据程序中的指令和数据,CPU进行计算和控制。
    • 程序在执行过程中可能会与操作系统、其他程序或硬件设备进行交互。
    • 程序执行完成后,返回操作系统,释放所占用的资源。

3什么是堆,栈,内存泄漏和内存溢出?⭐⭐⭐⭐

  1. 堆(Heap)

    • 堆是程序运行时用于动态内存分配的区域。在C、C++等语言中,使用mallocnew等函数或操作符在堆上分配内存。堆内存的生命周期完全由程序员管理,因此程序员必须显式地释放不再需要的内存,以防止内存泄漏
    • 堆内存的管理通常比栈内存复杂,因为它涉及到内存的分配、回收和碎片整理等问题。
  2. 栈(Stack)

    • 栈是程序运行时用于存储局部变量和函数调用的区域。栈内存的管理是自动的,当函数被调用时,其参数和局部变量会被推入栈中;当函数返回时,这些数据会从栈中弹出。
    • 由于栈内存的管理是自动的,因此程序员通常不需要关心栈内存的分配和释放。然而,如果函数递归过深或者局部变量过大,可能会导致栈溢出
  3. 内存泄漏(Memory Leak)

    • 内存泄漏是指程序在申请内存后,未能释放已不再使用的内存空间。这通常发生在堆内存中,因为堆内存的管理需要程序员显式地进行。如果程序员忘记释放已分配的内存,或者由于某些原因(如程序异常终止)未能释放内存,那么这部分内存就无法被再次使用,造成内存泄漏
    • 内存泄漏可能会导致程序运行变慢,甚至耗尽系统资源,使程序崩溃。
  4. 内存溢出(Memory Overflow)

    • 内存溢出是指程序试图访问或操作其内存空间之外的内存,这通常是由于程序中的错误(如数组越界访问、指针错误等)导致的。内存溢出可能会导致程序崩溃或产生不可预测的行为。
    • 内存溢出
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值