Geekiter/geekiter.github.io

240416Note: em - driver&os

Opened this issue · 0 comments

1. 驱动开发

1.1 Linux驱动程序的功能是什么?

  • 对设备初始化和释放
  • 进行内核与硬件的数据交互
  • 检测和处理设备出现的错误

1.2 内核程序申请内存使用什么函数?

  • kmalloc()
  • kzallo()
  • vmalloc()

解读:

void *kmalloc(size_t, size, gfp_t flags)
- 申请连续的物理内存这对于要进行DMA的设备十分重要但大小不能超过128KB其中16B是被页描述符占用了
- 较常用的flag有GFP_ATOMIC分配内存的过程是一个原子过程GFP_KERNEL正常分配内存GFP_DMA给DMA控制器分配内存
- 对应的内存释放函数为void kfree(const void *objp)

void *kzalloc(size_t size, gfp_t flags);
- kzalloc()相对于kmalloc()只是额外增加了_GFP_ZERO标志除了申请内存外还会对申请到的内存清零
- 对应的释放函数也是kfree()

void *vmalloc(unsigned long size);
- 申请虚拟地址连续的内存空间但其对应的物理内存不一定连续因此对申请的内存大小没有限制
- 对应的内存释放函数为void vfree
- 注意vmalloc()和vfree()可以睡眠因此不能再中断上下文调用

1.3 内核程序中申请内存和应用程序申请内存有什么区别?

内核中申请内存空间用的是函数kmalloc、kzalloc、vmalloc,应用程序申请内存用的是函数malloc

  • kmalloc、kzalloc直接分配连续的物理地址,虚拟也是连续的
  • vmalloc分配连续的虚拟地址,但物理地址不一定连续。分配时实际分配了物理内存,不过这个物理内存页面在公共的页表进行了映射,并没有在本进程的页表进行映射,当访问这段内存时,触发do_page_fault异常(缺页中断)才完成页表的同步工作
  • malloc是用户空间申请内存的方法,分配连续的虚拟地址,物理地址一般不会连续。在分配时并没有做实际物理页的分配动作,实际分配物理页的动作是在do_page_fault异常(缺页中断)处理中完成的

1.4 自旋锁和信号量在互斥使用时需要注意什么,在中断服务程序里面的互斥是使用自旋锁还是信号量?

  • 使用自旋锁的进程不会睡眠,而使用信号量的进程会睡眠
  • 中断服务程序使用的是自旋锁,原因是中断服务程序处于中断上下文,中断上下文是不参与调度的,也就没有保护现场与恢复现场,一旦睡眠就回不来了。

1.5 驱动卸载异常可能是由什么原因引起的?

可能是由进程在使用该模块

1.6 Linux中引入模块机制有什么好处?

  • 应用程序在退出时,可以不管资源的释放或者其他的清除工作,而把这些任务交给模块退出函数exit
  • 模块机制有助于缩短模块的开发周期,因为模块的安装和卸载都很方便

1.7 Linux设备驱动程序中,使用哪两个函数进行中断处理程序的注册和注销?

  • 注册中断
    • int request_irq
    • 输入:中断号、中断处理函数、中断管理有关掩码、中断请求设备名、中断信号线
  • 注销中断
    • void free_irq
    • 中断号、中断信号线

1.8 写一个中断服务程序注意点

  • 尽可能短,放底部
  • 不能有阻塞操作,完全占用CPU
  • 返回值要用操作系统的宏,不能自己定义
  • 中断服务程序不能有不可重入的操作

1.9 Linux系统打开设备文件,进程可能处于三种基本状态,如果多次打开设备文件,驱动程序应该实现什么?

互斥

1.10 简述static对于工程模块化的作用

static可以让全局变量或函数的作用域限制在当前模块,不会与其他模块发生冲突。因为在嵌入式系统中,一个程序可能是很多程序员共同完成的,在定义变量及函数的过程中,可能会重名,给系统集成带来麻烦

1.11 并发是什么?驱动里面为什么要有互斥控制,如何实现?

  • 并发是指多个执行单元、并行地被执行,而并发的执行单元对共享资源,硬件和软件的全局变量、静态变量的访问很容易导致竞态
  • 解决竞态问题的途径是保证对共享资源的互斥访问
  • 访问共享资源的代码区域被称为临界区,临界区需要用某种互斥机制加以保护、中断屏蔽、原子操作、信号量、自旋锁都是Linux设备驱动中可以采取的互斥机制

1.12 Linux内核有哪些同步方式?

  • 原子操作
  • 信号量
  • 自旋锁
  • 读写锁
  • 顺序锁

1.13 在一个多任务嵌入式系统中,有一个CPU可直接寻址的32寄存器REGn,地址为0x1F000010,编写一个安全的函数将寄存器REGn的指定位反转?

void bit_reverse(uint32_t nbit){
	*((volatile unsigned int *)0x1F000010) ^= (0x01 << nbit)
}
  • 指定位反转用异或^
  • 由于是寄存器地址,因此强制类型转换要加上volatile

2 操作系统

2.1 Linux系统的组成部分?

  • Linux内核
  • Linux文件系统
  • Linux Shell
  • Linux 应用程序

2.2 Linux内核的组成部分

  • 第一种:内存管理子系统、进程管理子系统、文件管理子系统、I/O管理子系统
  • 第二种:进程调度、进程间通信、内存管理、虚拟文件系统、网络接口

2.3 内存管理MMU的作用?

  • 地址映射
  • 内存分配和回收
  • 内存保护
  • 内存扩充

2.4 常见的操作系统进程调度策略

  • 先来先服务
  • 短进程优先
  • 高响应比优先
  • 时间片轮转
  • 多级反馈队列
  • 最高优先权优先

2.5 满足短作业优先又不会发生饥饿现象的算法是什么

高响应比优先

2.6 I/O子系统层次结构

从上到下

  • 用户层I/O软件
  • 设备独立性软件
  • 设备驱动程序
  • 中断处理程序

2.7 逻辑地址、线性地址、物理地址、总线地址、虚拟地址的区别

  • 逻辑地址: 与内存段相关的偏移地址部分。例如在c中获取指针变量的值,就是逻辑地址,不和绝对的物理地址相关
  • 线性地址:线性地址=逻辑地址+基地址
  • 物理地址:如果启用了分页机制,那么线性地址使用页变换后就是物理地址。如果没有启用分页机制,那么线性地址就是物理地址。
  • 总线地址:x86下I/O地址,ARM下的物理地址,在x86下,外设的I/O地址是独立的,即有专门的指令访问外设I/O,I/O地址就是“总线地址”,而RAM地址就是“物理地址”。在ARM下,I/O和RAM同一编址,但linux为了统一各个平台,仍然保留了这个概念
  • 虚拟地址,MMU内存管理单元虚拟出来的地址

2.8 操作系统的内存分配一般有哪几种方式,各有什么优缺点?

  • 分页存储管理:优点是不需要连续的内存空间,内存利用率高,缺点是不易实现内存共享和保护
  • 分段存储管理:优点是易于实现段内共享和保护;缺点是每段都需要连续的内存空间,会产生外部碎片,内存利用率较低
  • 段页式存储管理,优点是不需要连续的内存空间,内存利用率高,只需要很小的业内碎片,易于实现段内共享和保护;缺点是管理软件复杂性高,需要的硬件以及占用的内存也有所增加,使得执行速度下降

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

方式 解释
系统调用SCI 用户空间进程通过系统调用接口访问指定的内核空间数据
信号 内核空间出现一些异常时会发送信号给用户空间进程
proc文件系统 是一种特殊的伪文件系统,是Linux内核信息的抽象文件接口,大量内核中的信息以及可调参数都被作为常规文件映射到这个目录树中,用户可通过echo和cat这样的命令对系统信息进行修改和查询
共享内存mmap 将内核空间的地址映射到用户空间
netlink 类似socket的通信方式,可以读写大量数据

2.10 用户进程调用read()/write() API时,内核做了哪些事情?

read()/write() -> kernel -> sys_read()/sys_write()->fop.read()->fop.write()

2.11 系统调用的作用

  • 为应用程序提供访问硬件资源的统一接口,不必关心具体的硬件操作细节
  • 对系统内核进行保护,保证系统的稳定和安全。

2.12 BootLoader、Linux内核、根文件系统的关系?

  • 系统一上电、就执行BootLoader来初始化处理器及外设,将系统的软硬件环境带到一个合适的状态
  • 然后将Linux内核、根文件系统从非易失性存储器读取到内存中并执行Linux内核
  • Linux内核完成初始化之后就挂载某个文件系统作为根文件系统

2.13 BootLoader的启动过程大多可以分为哪两个阶段?

  • 第一阶段是汇编,完成一些依赖于CPU体系结构的初始化,并调用第二阶段的代码
  • 第二阶段是C语言,进一步完成硬件初始化,建立内存映射,并将内核映像和根文件系统读取到内存中,然后调用内核

2.14 Linux下查看内存使用情况的命令?

  • ps -aux
  • free
  • vmstat
  • top
  • cat/proc/meminfo

2.15 在Linux里面用gcc编译程序时,分为哪4个阶段?

  • 预处理:引入头文件、进行宏替换、处理条件编译指令、去除注释、添加行号
  • 编译:进行语法分析,生成汇编代码
  • 汇编:将汇编代码转成二进制代码.o
  • 链接:将有关的目标文件彼此链接为可执行代码,分为静态链接和动态链接,静态链接是将库文件代码搬迁到可执行文件中,后缀是.a,动态链接是在执行的时候转到库文件代码执行,后缀是.so

2.16 什么是死锁?产生死锁的原因是什么?

  • 死锁是指多个进程因竞争资源而造成的一种僵局,互相等待,若无外力作用,这些进程将无法向前推进
  • 原因:
    • 系统资源不足
    • 系统分配不当
    • 进程推进的顺序不合适

2.17 死锁的四个必要条件是什么?

  • 互斥条件:一个资源只能被一个进程使用,其他进程只能等待
  • 请求与保持条件:进程已经获得至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占用,此时该进程被阻塞,但对已获得资源依然保持不放
  • 不可剥夺条件:进程所获的的资源不能被其他进程剥夺,智能被自己释放
  • 循环等待条件:若干进程形成收尾相接循环等待资源的关系
  • 互斥、请求与保持、不可剥夺、循环等待

2.18 死锁的处理方法?

  • 预防死锁:通过设置一些限制条件,去破坏产生死锁的必要条件
  • 避免死锁:在资源分配过程中,使用某种方法避免系统进入不安全状态,从而避免发生死锁
  • 检测和解除死锁:允许死锁的发生,但是通过系统的检测之后,采取一些措施,将死锁清除掉
  • 破坏死锁条件、资源分配避免死锁、检测死锁破坏死锁

2.19 怎么预防死锁?

  • 破坏请求与保持条件
    • 静态分配:即每个进程开始执行时,就申请它所需要的全部资源
    • 动态分配:每个进程在申请所需要的资源时,它本身不占用系统资源
  • 破坏不可剥夺条件
    • 释放阻塞的进程
  • 破坏循环等待条件
    • 采用资源的有序分配

2.20 硬链接和软链接的区别

  • 链接:是给系统中已有的某个文件指定另外一个可用于访问它的名称,名称,链接也可以指向目录。即使我们删除这个链接,也不会破坏原来的目录和文件
  • 硬链接:引用的是文件在文件系统中的物理索引inode,当你移动或删除原文件时,硬链接不会被破坏。硬链接只能引用同一文件系统中的文件
  • 软链接:就是新建一个文件inode,这个文件专门用来指向别的文件,若移动或删除原文件,则相应的软链接不可用。软链接可以跨文件系统,也可以对一个不存在的文件名或目录名进行链接。

2.21 虚拟内存是什么?

虚拟内存是内存管理的一种技术,使得应用程序认为自己拥有连续的内存空间,而实际上它对应的物理内存是不连续的,甚至还有一部分对应着外部磁盘存储器,在需要时再进行数据交换。

2.22 内存零头、外零头、内零头

  • 内存零头:操作系统在内存分配时产生的一些无法利用的内存碎片
  • 外零头:内存中存在着一些内存碎片,但这些内存碎片不归任何进程所有。段式存储管理会产生外零头,其中段的大小是程序逻辑确定的,大小不定
  • 内零头:内存中存在着一些内存碎片,而这些内存碎片是归属于某个进程。页式存储管理会产生内零头,其中页的大小是由系统确定的,大小固定。

2.23 64位的计算机有哪些优点?

  • 可以进行更大范围的整数计算
  • 可以支持更大的内存,虚拟内存空间大小一般位2^48(256TB)。64位的Linux一般使用48位表示虚拟内存空间地址,40位表示物理内存地址。

2.24 中断分为哪两种?

  • 异步中断:也叫外部中断,由CPU外设产生的电信号,其发生时间不可预估。其引入是为了支持CPU和设备之间的并行操作。
  • 同步中断:也叫内部中断、异常,由CPU内部产生的电信号,其特点是当前指令执行完才产生中断。其引入是为了表示CPU执行时本身出现的问题。

2.25 Linux系统的挂起、待机、休眠?

  • 挂起:CPU、内存工作,而硬盘和显示器等外部设备停止工作
  • 待机:只对内存供电,CPU、外设停止工作
  • 休眠:CPU、内存停止工作,内存中的数据保存在硬盘中,外部设备也停止工作。

2.26 Linux关机、重启的命令有哪些?

  • 关机:halt、shutdown -h 时间、poweroff
  • 重启:reboot、shutdown -r 时间

2.27 Linux目录结构:/use,/tmp,/etc目录的作用?

  • Linux目录结构
    • bin
    • boot
      • grub
    • dev
    • etc
      • 系统的设定文档
    • home
    • lib
    • mnt
    • opt
    • proc
    • root
    • sbin
    • sys
    • tmp
      • 让一般使用者或者是正在执行的程序暂时放置档案的地方
    • usr
      • 是unix software resource的缩写,也就是unix操作系统软件资源所放置的目录
    • var

2.28 简述实时操作系统和非实时操作系统的区别

  • 实时操作系统,是可强占式内核,响应外部事件尽可能快且响应时间具有确定性。有硬件实时操作系统和软实时操作系统,硬实时操作系统的抖动(时间偏差)比软实时操作系统小
  • 非实时操作系统,非可抢占式内核,响应外部事件的时间没有保证

2.29 常用的实时操作系统有哪些,非实时

  • 实时:Vxworks
  • 软实时或非实时:Linux、WinCE

2.30 Linux内核的调度策略有哪些?

  • 分时调度
  • 实时调度,先到先服务
  • 实时调度,时间片轮转

2.31 块与页有什么关系

块是操作系统读写硬盘的最小单位,页是操作系统读写内存的最小单位

2.32 简述处理器在读内存过程中,CPU、MMU、cache、内存如何协同工作?

  • CPU内核发出VA向TLB请求表项,它缓存最近查找的VA对应的页表项。如果TLB中刚好缓存了该VA对应的页表项则直接返回给CPU;否则就由MMU去物理内存中读出页表项保存在TLB中,同时返回给CPU内核
  • MMU首先检测页表项中的权限位,如果没有访问权限,就引发一个异常给CPU内核;有权限则检测是否允许缓存,页表项中不仅保存着物理页面的基地址,还保存着权限和是否允许cache的标准
  • 如果不允许cache则MMU直接发出PA从物理内存中读取数据到CPU内核
  • 如果允许cache,则MMU以VA为索引到cache中查找是否缓存了要读取的数据,如果是则直接返回给CPU内核;如果不是则MMU发出PA从物理内存中读取数据并缓存到cache中,同时返回给CPU内核

2.33 ARM CPU上的地址转换涉及哪三个概念

  • 虚拟地址VA:CPU内核对外发出VA
  • 变换后的虚拟地址MVA modified virtual address:VA被变换位MVA供cache和MMU使用,由硬件自动完成。如果VA<32M,则需要使用PID来转换位MVA,目的是当两个进程的虚拟地址空间有重叠时,把重叠的VA映射到不同的PA上去,减少切换进程的代价
  • 物理地址PA:最后使用PA读写实际设备

2.34 MMU的和不同MMU的操作系统由哪些?带MMU和不带MMU的CPU有哪些

  • 用MMU的操作系统:Windows、MacOS、Linux
  • 不用MMU的操作系统:FreeRTOS、VxWorks、UCOS
  • 带MMU的CPU:Cortex-A、ARM9、ARM11
  • 不带MMU的CPU:Cortex-M 比如STM32

2.35 为什么uboot要关掉cache

cache主要用来加快CPU读取内存中指令的速度,但在CPU初始化时,内存并未准备就绪,直接进行数据读取,势必导致指令取址异常

2.36 内核函数mmap的实现原理

mmap函数能够实现把一个文件映射到一个内存区域,使得我们可以像读写内存一样读写文件,比单纯地调用read/write函数要快上许多。我们可以把内存中的内容拷贝到一个文件中实现内存备份,也可以把文件映射到内存来恢复某些服务。

2.37 默认的Linux系统,从后台启动进程,应在命令的结尾加上&

2.38 ps跟top有什么区别

  • ps看到的是命令执行瞬间的进程信息;而top可以实时地持续监视,不断更新进程状态
  • ps只是查看进程信息,而top还可以监视系统性能,如CPU负载,内存消耗
  • 另外top还可以操作进程。如改变优先级命令r和关闭进程命令k

2.39 写出下列常用命令

  • Linux查看线程ID
    • ps -T -p 进程号
    • top -H -p 进程号
    • pstree -Aup -h 进程号
  • Linux设置文件目录权限
    • chmod
  • uboot查看环境变量
    • printenv