系列文章目录
嵌入式八股文(一)C语言篇
嵌入式八股文(二)Linux应用篇
嵌入式八股文(三)Linux驱动篇
嵌入式八股文(四)FreeRTOS篇
前言
在继续开始Linux驱动学习之前,本期继续带来linux篇的八股文学习,以为后续的学习打个基础。本系列会不定期持续更新(随笔者的学习进度),大家可以收藏一下时不时看一下。
一、Linux相关问题
1.1 Linux是什么操作系统
Linux 本质上是一个 分时操作系统,但它也支持构建分布式系统。分时操作系统的核心特点是允许多个用户/任务共享 CPU 和时间片资源,每个用户或进程看似“独占”系统。以下是常见操作系统的详细分类和解释:
类型 | 核心特点 |
---|---|
分时操作系统 | 多用户、多任务、时间片轮转调度 是(Linux 的核心设计) |
实时操作系统 | 严格保证任务在确定时间内完成(如工业控制、自动驾驶) |
分布式操作系统 | 多台机器透明协作,全局资源管理 |
批处理系统 | 按队列顺序执行任务,无交互性 |
1.2 初识u-boot
这部分我们学习笔记还没有更新到,这里仅仅简单列一下理论,后续学到这部分在详细讲一下。
1.2.1 bootloader
Linux启动时需要的一段小程序,负责初始化时钟、中断和其他外设等,然后将内核从flash中加载到SDRAM中,并启动内核,相当于PC机的BIOS。U-Boot(Universal Bootloader)是一个开源的引导加载程序,是Bootloader的一个具象化的表现。
1.2.2 为什么使用uboot启动内核
使用U-Boot启动内核的原因主要有以下几点:
- 初始化硬件:CPU不能直接从块设备(如SD卡、iNand、Nandflash等)中执行代码。在启动Linux内核之前,需要进行一系列的硬件初始化工作,如时钟、串口、DRAM等。U-Boot就是一个复杂的裸机程序,它负责这些初始化工作,为Linux内核的启动创造一个合适的环境。
- 加载内核:U-Boot会将Linux内核镜像从块设备中读取到内存中的特定位置(如链接地址处)。这个过程确保了内核代码在正确的内存地址处执行。
- 启动内核:在硬件初始化和内核加载完成后,U-Boot会执行一个特定的命令(如bootm命令)来启动Linux内核。这个命令告诉CPU从内存中的特定位置开始执行代码,从而启动Linux内核。
- 提供交互性:U-Boot还提供了一个交互式的命令行界面,允许用户进行配置、调试和维护操作。这使得在启动Linux内核之前或之后,用户可以对系统进行更精细的控制和调试。
- 支持多种平台和架构:U-Boot是一个开源的引导加载程序,支持多种处理器架构和嵌入式平台。这使得它成为嵌入式系统开发中广泛使用的工具之一。
1.2.3 u-boot的启动过程
U-Boot的启动过程可以分为两个阶段,每个阶段都有其特定的功能和任务。
- 第一阶段(汇编语言阶段):
- 设置异常向量表:当系统发生异常时,处理器会跳转到这些固定地址的向量表中进行处理。
- 硬件初始化:配置时钟相关参数,如内核时钟、总线时钟、IO接口时钟等。
- 准备RAM空间:使内存芯片可用,以便加载U-Boot第二阶段的代码。
- 复制U-Boot第二阶段的代码至RAM中。
- 定义入口
- 第二阶段:
- 初始化外设:包括串口、以太网接口、存储设备等。
- 检测内存映射:确定系统的内存布局和大小。
- 将内核从Flash或其他存储设备读取到RAM中。
- 为内核设置启动参数:这些参数包括内存大小、设备树地址等,用于内核启动时的初始化。
- 调用内核:将控制权交给内核,完成系统的启动过程。
1.2.4 u-boot和内核的数据传输
在完成相关设置(R1和R2)之后,uboot将机器ID通过R1发送给内核,并利用R2存放内存基地址。这里会产生标记的概念,他是一种数据结构是tag_header结构体和一个联合体组成。
1.3 运行地址、链接地址、加载地址
概念 | 定义 | 关键特点 |
---|---|---|
链接地址 | 程序在编译链接阶段确定的代码和数据的预期内存地址(由链接脚本指定) | 静态地址,写入二进制文件 |
加载地址 | 程序实际被加载到内存中的起始地址(由加载器或启动代码决定) | 可能与链接地址不同 |
运行地址 | 程序在运行时指令和数据实际访问的物理/虚拟地址(最终生效的地址 | ) 动态地址,受加载地址和重定位影响 |
1.4 硬件中断号与Linux内核的IRQ号的映射
在某些情况下,一个硬件中断可以直接映射到一个Linux IRQ。例如,现代PC上的传统外设(如键盘、鼠标)都有明确的一对一映射。但是,有些较复杂的设备可能会有多个硬件中断共享同一个IRQ。例如,在一些高级DMA控制器下,不同通道可能会共享同一个IRQ,即多对一映射。
二、网络
这部分我们在之前的Linux应用篇简单介绍过了,这次主要是摘出来应付一下“八股取士”。下面是常见的协议汇总:
所在层 | 协议 |
---|---|
物理层 | RJ45 、 CLOCK 、 IEEE802.3 (中继器,集线器) |
数据链路 | PPP 、 FR 、 HDLC 、 VLAN 、 MAC (网桥,交换机) |
网络层 | ==IP ==、 ICMP 、 ARP 、 RARP 、 OSPF 、 IPX 、 RIP 、 IGRP 、 (路由器) |
传输层 | TCP 、 UDP 、 SPX (网关) |
会话层 | NFS 、 SQL 、 NETBIOS 、 RPC |
表示层 | JPEG 、 MPEG 、 ASII |
应用层 | FTP , DNS,Telnet(TELNET) ,SMTP,HTTP , WWW ,NFS,SNMP |
2.1 TCP和UDP
2.1.1 TCP的三次握手和四次挥手
TCP的三次握手应用于建立连接:
- 第一次握手:客户端向服务器发送一个SYN包(同步包),其中包含客户端的初始序列号。此时,客户端进入SYN_SEND状态,等待服务器的确认。
- 第二次握手:服务器收到SYN包后,会确认客户端的SYN(通过发送一个ACK包,其中ack=客户端的序列号+1),同时服务器也会发送一个自己的SYN包,其中包含服务器的初始序列号。这个包通常被称为SYN+ACK包。此时,服务器进入SYN_RECV状态。
- 第三次握手:客户端收到服务器的SYN+ACK包后,会再次发送一个ACK包以确认收到服务器的SYN包(ack=服务器的序列号+1)。发送完这个ACK包后,客户端和服务器都进入ESTABLISHED状态,表示连接已建立成功。
简记:同步包→同步包+应答包→应答包
TCP的四次挥手应用于释放连接,需要进行的四个步骤,具体步骤如下:
- 第一次挥手:当一方(假设为客户端)决定关闭连接时,它会发送一个FIN(Finish)报文段给对方。
- 第二次挥手:服务器收到FIN报文段后,会对这个FIN报文段进行确认,然后自己也发送一个ACK报文段。
- 第三次挥手:服务器在发送完ACK报文段后,会等待所有的数据传输完成,然后发送一个FIN报文。
- 第四次挥手:客户端收到服务器的FIN报文段后,会对其进行确认,并发送一个ACK报文段给服务器。
简记:Finish包→应答包→Finish包→应答包
2.1.2 特点及其应用场景
TCP | UDP | |
---|---|---|
特点 | 面向连接、可靠、基于字节流 | 无连接的、不可靠的、可向多主机发送 |
优势 | 面向连接、拥塞控制、流量控制、可靠 | 开销小、不需要连接 |
劣势 | 耗时、开销占用大 | 不可靠、无序 |
应用场景 | 适用于需要高可靠性和完整性的数据传输,例如文件传输 | 适用于对实时性要求较高的应用,如视频通话、音频流传输和实时游戏等。 |
2.1.3 TCP协议保证数据传输可靠性的方式
TCP的重传机制
因为发送缓存区会存储已经发送的数据,知道收到ACK报文之后才会逐渐移除缓存区的内容;而UDP发送缓存区数据会直接发送出去,不会等待ACK报文,不会重传和清除,下一条消息会覆盖缓存区。
常见的重传机制包括:超时重传、快速重传、SACK选择性确认、D-SACK。
(1)校验和
(2)序列号
(3)确认应答
(4)超时重传
(5)连接管理
(6)流量控制
(7)拥塞控制
2.2 TCP/IP四层模型
TCP/IP四层可以说是OSI七层模型的简化版,主要有以下四层模型:
- 应用层(应用层+表示层+会话层)
- 传输层
- 网络层
- 网络接口层(物理层+数据链路层)
2.3 HTTP协议
2.3.1 基本特点
HTTP 是一种应用层协议,主要用于Web浏览器与网站服务器之间的通信。HTTP本质上是在TCP(传输控制协议)之上的一个应用层协议。这意味着HTTP使用TCP作为其底层传输机制,以确保数据可靠地从客户端传递到服务器并返回。HTTP消息有两种类型:请求消息和响应消息,具有以下特点:
- 简单:HTTP基本报文格式为header+body,是最简单的key-value的简单文本的形式,易于理解;
- 灵活:HTTP协议里各种信息没有被固定死。此外,HTTP工作在应用层,下层可以随意变化,在HTTP和TCP之间添加SSL/TSL安全传输层,就是HTTPS;将TCP换成基于UDP的QUIC就是HTTPS;
- 不安全:适用明文传输,内容可能被窃听;没有验证通信方身份,可能遭遇伪装;无法保证报文的完整性(没有完整性校验),可能被篡改。
2.3.2 连接流程
其链接通常涉及以下几个步骤:
- 建立TCP连接(三次握手):
- 发送HTTP请求:请求包括请求行、请求头和可选的请求体(用于POST请求等)。
- 接收HTTP响应:响应包括状态行、响应头和响应体(如HTML页面内容)。
- 关闭TCP连接:在HTTP早期版本,每次请求-响应周期完成后都会关闭TCP连接;在HTTP/1.1及之后,引入了持久连接(Keep-Alive)选项,默认情况下允许在同一个TCP连接上发送多个请求和响应,从而减少建立新连接的时间开销。
2.4 网络拓扑及常见结构
网络拓扑是指网络中各个节点及他们之间的连接关系,拓扑决定了数据在网络中是如何流动、如何通讯的。
2.3.2 HTTPS和HTTP的区别
特性 | HTTP | HTTPS |
---|---|---|
安全性 | 不安全,数据明文传输 | 安全,数据加密传输 |
数据加密 | 不支持 | 使用 SSL/TLS 协议进行加密 |
证书要求 | 无需证书 | 需要由 CA 签发的 SSL 证书 |
性能 | 速度稍快 | 略慢于 HTTP(因加密开销,但差异很小) |
使用场景 | 普通非敏感网站内容 | 登录页、支付页、涉及用户隐私信息的页面 |
三、 线程和进程
进程是资源分配和调度的基本单位,而线程是系统调度的基本单位,一个进程中可以同时运行多个线程,共享同一份系统资源。
3.1 线程同步
- 互斥锁 :一种简单的加锁机制,当一个线程获取了互斥锁时,其他试图获取该锁的线程将被阻塞,直到锁被释放。
- 信号量 :一个用于控制对多个共享资源的访问的计数器。
- 条件变量:条件变量通常与互斥锁一起使用,允许线程等待某个条件成立。
- 读写锁:允许多个线程同时读取共享资源,但只允许一个线程写入资源,当有线程正在写入资源时,其他试图读取或写入的线程将被阻塞。
3.2 进程间的通信方式
- 无名管道:半双工,数据单向流通且仅适用于亲缘进程间。
- 命名信号(FIFO):半双工,容许非亲缘进程间通讯。
- 共享内存:映射同一段能被其他进程访问的内存空间。
- 消息队列:保存在内核的消息的列表。
- 信号量:本质上是计数器。
- 套接字:不同设备间进程通讯。
3.3 进程的生命周期
- 运行:该进程正在执行
- 就绪:该进程可以执行但未获得许可,调度器可以在下次任务进行切换
- 睡眠:进程在等待外部事件,调度器无法在下次任务进行切换
3.4 多线程和多进程的实现方法
- 多进程:在主进程利用fork()等申请一个新的子进程,根据返回值判断是否创建成功,并利用exec()函数进行执行新的程序。
- 多线程:利用pthread_create()函数创建一个新的线程,根据返回值判断是否创建成功,并利用互斥锁和条件量等进入子线程操作。
3.5* 守护进程、孤儿进程和僵尸进程
守护进程通常用于执行后台任务,孤儿进程在父进程结束后由init进程接管,而僵尸进程则是因为父进程没有正确释放子进程的资源而产生的。
3.6* 协程
协程(Coroutine)是一种轻量级的用户态线程,操作系统对协程无感知。它实现的是协作式调度(非抢占式调度),即协程切换由当前协程控制,主动让出CPU(例如当前协程在等待异步网络IO时)。通常情况下,一个线程包含多个协程。
3.7 线程池
线程池是一种多线程管理模式,目的是提高系统的并发性和资料利用率。线程池创建了一定数量的线程,其被反复利用来执行任务,从而避免了频繁创建和销毁线程的开销。线程池的核心组件是线程队列、任务队列及线程管理机制,其工作流程如下:
- 初始化线程池:启动时,线程池会创建一定数量的线程并使其进入等待
- 提交任务:有任务需要执行,任务被提交到线程池的任务队列
- 分配任务:从任务队列取出任务,并交给空闲线程
- 执行任务:分配到进行执行,结束后将任务返回到线程池
- 重复利用:任务可以反复使用,避免频繁创建及注销
四、存储
4.1 RAM、ROM和Flash的区别
RAM、ROM和Flash是计算机及电子设备中常见的三种存储类型,其区别如下:
特性 | RAM | ROM | Flash |
---|---|---|---|
全称 | Random Access Memory | Read-Only Memory | Flash Memory |
易失性 | 易失性(断电数据丢失) | 非易失性(断电数据保留) | 非易失性(断电数据保留) |
读写能力 | 可读可写 | 通常只读(某些类型可编程写入) | 可读可写(需按块擦除后写入) |
主要类型 | DRAM(动态)、SRAM(静态) | PROM、EPROM、EEPROM | NAND Flash、NOR Flash |
读写速度 | 快(ns级,SRAM > DRAM) | 慢(写入需特殊操作,如紫外线擦除) | 读快(接近RAM),写慢(ms级) |
容量 | 较小(MB~GB级,受成本限制) | 较小(KB~MB级) | 大(GB~TB级,适合存储) |
主要用途 | 临时存储运行中的程序和数据 | 存储固件、引导程序(如 BIOS) | 存储需长期保存且频繁更新的数据(如SSD、U盘、手机存储) |
寿命 | 无限次读写(依赖供电) | 有限次写入(如EPROM约千次) | 有限擦写次数(如NAND约1万~10万次) |
成本 | 高(尤其SRAM) | 低(一次性编程类型) | 中等(容量越大成本越低) |
示例场景 | 电脑内存条(DRAM)、CPU缓存(SRAM) | 单片机引导程序(EEPROM)、游戏卡带(Mask ROM) | U盘(NAND Flash)、SSD(NAND Flash) |
4.2 cache
缓存本质上是 CPU 内部的高速存储器,由硬件直接管理,目的是减少访问内存的延迟。其具有以下三个特点:
- 高速: 接近CPU,访问速度比主存(RAM)更快
- 临时性:存储是临时的,空间不足会被覆盖
- 层次结构:三级缓存(L1:cpu内部、L2:紧邻CPU、L3:多核CPU中共享)