嵌入式八股文(二)Linux应用篇

系列文章目录

嵌入式八股文(一)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 特点及其应用场景

TCPUDP
特点面向连接、可靠、基于字节流无连接的、不可靠的、可向多主机发送
优势面向连接、拥塞控制、流量控制、可靠开销小、不需要连接
劣势耗时、开销占用大不可靠、无序
应用场景适用于需要高可靠性和完整性的数据传输,例如文件传输适用于对实时性要求较高的应用,如视频通话、音频流传输和实时游戏等。

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 连接流程

  其链接通常涉及以下几个步骤:

  1. 建立TCP连接(三次握手):
  2. 发送HTTP请求:请求包括请求行、请求头和可选的请求体(用于POST请求等)。
  3. 接收HTTP响应:响应包括状态行、响应头和响应体(如HTML页面内容)。
  4. 关闭TCP连接:在HTTP早期版本,每次请求-响应周期完成后都会关闭TCP连接;在HTTP/1.1及之后,引入了持久连接(Keep-Alive)选项,默认情况下允许在同一个TCP连接上发送多个请求和响应,从而减少建立新连接的时间开销。

2.4 网络拓扑及常见结构

  网络拓扑是指网络中各个节点及他们之间的连接关系,拓扑决定了数据在网络中是如何流动、如何通讯的。
在这里插入图片描述

2.3.2 HTTPS和HTTP的区别

特性HTTPHTTPS
安全性不安全,数据明文传输安全,数据加密传输
数据加密不支持使用 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 线程池

  线程池是一种多线程管理模式,目的是提高系统的并发性和资料利用率。线程池创建了一定数量的线程,其被反复利用来执行任务,从而避免了频繁创建和销毁线程的开销。线程池的核心组件是线程队列、任务队列及线程管理机制,其工作流程如下:

  1. 初始化线程池:启动时,线程池会创建一定数量的线程并使其进入等待
  2. 提交任务:有任务需要执行,任务被提交到线程池的任务队列
  3. 分配任务:从任务队列取出任务,并交给空闲线程
  4. 执行任务:分配到进行执行,结束后将任务返回到线程池
  5. 重复利用:任务可以反复使用,避免频繁创建及注销

四、存储

4.1 RAM、ROM和Flash的区别

  RAM、ROM和Flash是计算机及电子设备中常见的三种存储类型,其区别如下:

特性RAMROMFlash
全称Random Access MemoryRead-Only MemoryFlash Memory
易失性易失性(断电数据丢失)非易失性(断电数据保留)非易失性(断电数据保留)
读写能力可读可写通常只读(某些类型可编程写入)可读可写(需按块擦除后写入)
主要类型DRAM(动态)、SRAM(静态)PROM、EPROM、EEPROMNAND 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 内部的高速存储器,由硬件直接管理,目的是减少访问内存的延迟。其具有以下三个特点:

  1. 高速: 接近CPU,访问速度比主存(RAM)更快
  2. 临时性:存储是临时的,空间不足会被覆盖
  3. 层次结构:三级缓存(L1:cpu内部、L2:紧邻CPU、L3:多核CPU中共享)
嵌入式软件开发是一种特殊的软件开发领域,以下是八股文的主要内容: 1. 了解目标平台:首先需要了解目标平台的硬件架构、操作系统以及其他相关的开发工具和资源。这包括选择适合的处理器架构(如ARM、x86等)以及操作系统(如Linux、RTOS等)。 2. 编译器选择和配置:根据目标平台选择适合的交叉编译器,并进行相应的配置。交叉编译器是一种能够在一种计算机环境中运行的编译程序,能够编译出在另外一种环境下运行的代码。交叉编译的过程被称为交叉编译。 3. 内核配置和编译:根据目标平台的要求,进行内核的配置和编译。这包括下载源码、建立交叉编译环境、必要时对源码进行修改等。 4. 文件系统制作:根据需求制作文件系统,例如RAM disk,用于挂载根文件系统。文件系统的制作可以根据具体需求进行定制,添加自己的应用程序等。 5. 应用程序开发:根据需求开发嵌入式应用程序。这包括编写代码、调试程序、保留#pragma编译指令等。保留#pragma编译指令是为了设定编译器的状态或者指示编译器完成特定的动作。 6. 下载和调试:将开发好的程序下载到目标平台上,并进行调试。这包括通过调试工具对程序进行单步调试、查看变量的值、检测和修复错误等。 总结起来,嵌入式软件开发的八股文包括了了解目标平台、选择和配置交叉编译器、配置和编译内核、制作文件系统、开发应用程序、保留#pragma编译指令、下载和调试等步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值