嵌入式操作系统知识点整理

第一章 系统内核

1. 分类

按其是否具有实时性来分:

  1. 嵌入式非实时系统
  2. 嵌入式实时系统

2. 常见的嵌入式操作系统

  • μC/OS-II
  • VxWorks

3. 定义

  • 一般定义

    以应用为中心、以计算机技术为基础、软件硬件可裁剪、功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。

  • 广义上讲

    凡是带有微处理器的专用软硬件系统都可称为嵌入式系统。

  • 从狭义上讲

    那些使用嵌入式微处理器构成独立系统,具有自己操作系统,具有特定功能,用于特定场合的专用软硬件系统称为嵌入式系统。

4. 交叉开发模型

在嵌入式开发过程中,有宿主机和目标机的角色之分

  • 宿主机是执行编译、链接嵌入式软件的计算机
  • 目标机是运行嵌入式软件的硬件平台。

image-20200629222715978

5. 重要特征

  1. 系统内核小
    由于嵌入式系统一般是应用于小型电子装置的,系统资源相对有限,所以内核较之传统的操作系统要小得多。
  2. 专用性强
    嵌入式系统的个性化很强,其中的软件系统和硬件的结合非常紧密,一般要针对硬件进行系统的移植。即使在同一品牌、同一系列的产品中也需要根据系统硬件的变化和增减不断进行修改。同时针对不同的任务,往往需要对系统进行较大更改,程序的编译下载要和系统相结合,这种修改和通用软件的“升级”是完全不同的概念。
  3. 系统精简
    嵌入式系统一般没有系统软件和应用软件的明显区分,不要求其功能设计及实现上过于复杂,这样一方面利于控制系统成本,同时也利于实现系统安全。
  4. 高实时性OS
    这是嵌入式软件的基本要求,而且软件要求固态存储,以提高速度。软件代码要求高质量和高可靠性、实时性。
  5. 嵌入式软件开发走向标准化
    嵌入式系统的应用程序可以没有操作系统直接在芯片上运行。 为了合理地调度多任务、利用系统资源、系统函数以及和专家库函数接口,用户必须自行选配RTOS(Real-Time Operating System)开发平台,这样才能保证程序执行的实时性、可靠性,并减少开发时间,保障软件质量
  6. 嵌入式系统开发需要开发工具和环境
    由于其本身不具备自主开发能力,即使设计完成以后,用户通常也是不能对其中的程序功能进行修改,必须有一套开发工具和环境才能进行开发。这些工具和环境一般是基于通用计算机上的软硬件设备以及各种逻辑分析仪、混合信号示波器等。开发时往往有主机和目标机的概念,主机用于程序的开发,目标机作为最后的执行机,开发时需要交替结合进行。

6. 基本组成

嵌入式系统由 硬件软件 两个部分组成:

  • 嵌入式硬件以芯片、模板、组件、控制器形式埋藏于设备内部。
  • 嵌入式软件是实时多任务操作系统和各种专用软件,一般固化在ROM或闪存中。

image-20200629223218628

嵌入式系统软硬兼施,融为一体,成为产品,但在开发过程中需要一些开发工具进行辅助开发。

7. Linux内核的版本号命名规则

版本号的格式通常为“主版本号.次版本号.修正号”。

主版本号和次版本号标志着重要的功能变动,修正号表示较小的功能变更。

以2.6.22版本为例,2代表主版本号,6代表次版本号,22代表修正号。其中次版本还有特定的意义:如果是偶数数字,就表示该内核是一个可以放心使用的稳定版;如果是奇数数字,则表示该内核加入了某些测试的新功能,是一个内部可能存在着BUG测试版。如2.5.74表示是一个测试版的内核,2.6.22表示是一个稳定版的内核。

8. Linux内核的功能结构

其中重要的5个功能子模块:

  1. 进程调度(SCHED)

    进程调度控制系统中的多个进程对CPU的访问,使得多个进程能在CPU中“微观串行,宏观并行”地执行。进程调度处于系统的中心位置,内核中其他的子系统都依赖它,因为每个子系统都需要挂起或恢复进程。

  2. 内存管理(MM)

    允许多个进程安全地共享主内存区域 。Linux的内存管理支持虚拟内存,即在计算机中运行的程序,其代码、数据和堆栈的总量可以超过实际内存的大小,操作系统只将当前使用的程序块保留在内存中,其余的程序块则保留在磁盘上。必要时,操作系统负责在磁盘和内存之间交换程序块。

    内存管理核心功能:

    • 虚拟地址与物理地址的映射
    • 物理内存的分配
  3. 虚拟文件系统(VFS)

    Linux虚拟文件系统(VFS)隐藏各种了硬件的具体细节,为所有的设备提供了统一的接口。而且,它独立于各个具体的文件系统,是对各种文件系统的一个抽象,因此它还支持多达数十种不同的文件系统,这也是Linux较有特色的一部分。

    虚拟文件系统可分为逻辑文件系统和设备驱动程序。逻辑文件系统指Linux所支持的文件系统,如ext2, fat等,设备驱动程序指为每一种硬件控制器所编写的设备驱动程序模块。

  4. 网络接口(NET)

    网络接口提供了对各种网络标准的存取和各种网络硬件的支持。如图所示,在Linux中网络接口可分为网络协议和网络驱动程序,网络协议部分负责实现每一种可能的网络传输协议,网络设备驱动程序负责与硬件设备通信,每一种可能的硬件设备都有相应的设备驱动程序。

  5. 进程间通信(IPC)

    进程通信支持提供进程之间的通信,Linux支持进程间的多种通信机制,包含信号量、共享内存、管道等,这些机制可协助多个进程、多资源的互斥访问、进程间的同步和消息传递。

9. 为什么配置内核

​ Linux 作为一个自由软件,在广大爱好者的支持下,内核版本不断更新。新的内核修订了 旧内核的 bug,并增加了许多新的特性。如果用户想要使用这些新特性,或想根据自己的系统度身定制一个更高效,更稳定的内核,就需要重新编译内核。
​ 通常,更新的内核会支持更多的硬件,具备更好的进程管理能力,运行速度更快、更稳定,并且一般会修复老版本中发现的许多漏洞等,经常性地选择升级更新的系统内核是Linux 使用者的必要操作内容。

10. 配置内核命令

  1. make config: 基于文本模式的交互式配置
  2. make menuconfig: 基于文本模式的菜单式配置
    • < >:表示不选择该功能
    • < M >:表示将该功能作为模块进行编译
    • < * >:表示必须编译该功能

11. 内核编译命令

  1. make zImage
  2. make bzImage

区别:在X86平台,zImage只能用于小于512K的内核。

编译好的内核位于**arch//boot/**目录下

12. 内核模块编译

  1. make modules:进行编译内核模块,编译后以 .ko 结尾的文件
  2. make modules_install:将编译好的内核模块,从内核源代码目录复制至 /lib/modules/ 下,为打包做好准备

13. 什么是 Boot Loader

​ Boot Loader 就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核做好一切准备。

Boot Loader有若干种,其中Grub、Lilo和spfdisk是常见的Loader。

在嵌入式系统中直接从Bootloader开始运行。

14. Boot Loader 两种工作模式

  • 启动加载(boot loading)模式:

    ​ 这种模式也称为”自主”(autonomous)模式。也即 boot loader 从目标机上的某个固态存储设备上将操作系统加载到 ram 中运行,整个过程并没有用户的介入。这种模式是 boot loader 的正常工作模式,因此在嵌入式产品发布的时侯,boot loader 显然必须工作在这种模式下

  • 下载(downloading)模式:

    ​ 在这种模式下,目标机上的 boot loader 将通过串口连接或网络连接等通信手段从主机(host)下载文件,比如:下载内核映像和根文件系统映像等。从主机下载的文件通常首先被 boot loader 保存到目标机的 ram 中,然后再被 boot loader 写到目标机上的flash 类固态存储设备中。boot loader 的这种模式通常在第一次安装内核与根文件系统时被使用;此外,以后的系统更新也会使用 boot loader 的这种工作模式。

​ 工作于这种模式下的 boot loader 通常都会向它的终端用户提供一个简单的命令行接口。像 blob 或 u-boot 等这样功能强大的 boot loader 通常同时支持这两种工作模式,而且允许用户在这两种工作模式之间进行切换。比如,blob 在启动时处于正常的启动加载模式,但是它会延时 10 秒等待终端用户按下任意键而将 blob 切换到下载模式。如果在 10 秒内没有用户按键,则 blob 继续启动 linux 内核。

15. 系统的典型结构图

image-20200629225737466

一个嵌入式Linux系统的典型结构,划分成了4个区:

  1. Bootloader区存放的是Bootloader,它负责嵌入式系统最初的硬件初始化、驱动和内核加载。
  2. 参数区不是必须的,通常存放了一些系统参数,并且通常这个区是没有文件系统,参数以原始数据的格式来存放。
  3. 内核镜像区存放的Linux内核压缩镜像,它被解压后运行于内存,作为嵌入式设备的Linux操作系统。
  4. 文件系统区存放经过压缩的文件系统,它会被Linux内核解压并挂载,并作为各种应用程序、文件的主要载体。

这4个区都以二进制数据的形式存放于嵌入式设备的Flash芯片上。

16. 内核根文件目录

根文件系统至少包括以下目录:

  • /etc/:存储重要的配置文件
  • /bin/:存储常用且开机时必须用到的执行文件
  • /sbin/:存储着开机过程中所需的系统执行文件
  • /lib/:存储/bin/及/sbin/的执行文件所需的链接库,以及Linux的内核模块
  • /dev/:存储设备文件

五大目录必须存储在根文件系统上,缺一不可。

17. init进程执行过程

  • 在内核引导结束并启动init之后,系统就转入用户态的运行,在这之后创建的一切进程,都是在用户态进行。

init进程虽然是从内核开始的,即在前面所讲的init/main.c中的init()函数在启动后就已经是一个核心线程,但在转到执行init程序(如 /sbin/init)之后,内核中的init()就变成了/sbin/init程序,状态也转变成了用户态,也就是说核心线程变成了一个普通的进程。

  • 这样一来,内核中的init函数实际上只是用户态init进程的入口,它在执行execve(“/sbin/init”,argv_init, envp_init)时改变成为一个普通的用户进程。这也就是exec函数的乾坤大挪移法,在exec函数调用其他程序时,当前进程被其他进程“灵魂附体”。
  • 除此之外,它们的代码来源也有差别,内核中的init()函数的源代码在/init/main.c中,是内核的一部分。而/sbin/init程序的源代码是应用程序。
  • init程序启动之后,要完成以下任务:检查文件系统,启动各种后台服务进程,最后为每个终端和虚拟控制台启动一个getty进程供用户登录。由于所有其它用户进程都是由init派生的,因此它又是其它一切用户进程的父进程。
  • init进程启动后,按照/etc/inittab的内容进程系统设置。很多嵌入式系统用的是BusyBox的init,它与一般所使用的init不一样,会先执行/etc/init.d/rcS而非/etc/rc.d/rc.sysinit。

第二章 设备驱动模型

1. 驱动模式

image-20200629230654335

2. 设备文件

Linux将所有外部设备看成是一类特殊文件,称之为 “设备文件” 位于/dev/目录

  • Linux抽象了对硬件的处理,所有的硬件设备都可以作为普通文件
    一样来看待。
  • 可以使用和操作文件相同的、标准的系统调用接口来完成打开、关闭、读写和I/O控制操作,对用户来说,设备文件与普通文件并无区别。
  • 字符设备和块设备是通过文件节点访问的。在Linux的文件系统中,可以找到(或者使用mknod创建)设备对应的文件名,称这种文件为设备文件。

3. 用户如何使用驱动程序

Linux用户程序通过设备文件(又名:设备节点)来使用驱动程序操作字符设备和块设备。

4. 字符型设备驱动模型图

image-20200629231156243

  • 分配 cdev

    1. 静态分配:struct cdev mdev;
    2. 动态分配:struct cdev *pdev = cdev_alloc();
  • 初始化 cdev

    cdev_init(struct cdev *cdev, const struct file_operations *fops)

    参数:

    • cdev:待初始化的 cdev 结构
    • fops:设备对应的操作函数集
  • 注册 cdev

    cdev_add(struct cdev *p, dev_t dev, unsigned count)

    参数:

    • p:待添加到内核的字符设备结构
    • dev:设备号
    • count:该类设备的设备个数
  • 注销 cdev

    init cdev_del(struct cdev *p)

    参数:

    • p:要注销的字符设备结构

5. 为什么有内核模块

​ Linux内核的整体结构非常庞大,其包含的组件也非常多。如果将所有组件都编译进内核文件,会导致内存占用过多。而模块就能让内核文件本身并不包含某组件,而是在该组件被使用的时候,动态的添加到正在运行的内核中。

6. 内核模块的特点

  1. 模块本身并不被编译进内核文件(zImage或者bzImage)
  2. 可以根据需求,在内核运行期间动态的安装或卸载

7. 内核模块的安装卸载

  • 安装:insmod
  • 卸载:rmmod
  • 查看:lsmod
1
2
3
4
5
6
insmod /home/dnw_usb.ko
# 安装 dnw_usb
remod dnw_usb
# 卸载 dnw_usb
lsmod
# 查看模块

8. 内核模块实例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# include <linux/init.h>
# include <linux/init.h>

static int hello_init(void)
{
printk(KERN_WARNING"Hello, word !\n");
return 0;
}

static int hello_exit(void)
{
printk(KERN_INFO"Goodbye, word\n");
}

moudle_init(hello_init);
moudle_exit(hello_exit);

9. 驱动程序代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#1nclude < 1inux/module .h>
#include < 1inux/init . h>

struct cdev mdev;

const struct file_operations memfops =
{
.llseek = mem_lseek,
.read = mem_read,
.write = mem_write,
.open = mem_open,
.release = mem_close,
};

int memdev_init ()
{
cdev_init(&mdev, &memfops);
return 0;
}

void mendev_exit ()
{
}
module_init (memdev_init);
module_exit (memdev_exit);

10. GCC 常用命令

最基本用法:**gcc [options] [filenames]**:

  • options:编译器所需要的编译选项
  • filenames:要编译的文件名
  1. -o output_filename:确定可执行文件的名称为 output_filename,如果不给出这个选项就给出预设的可执行文件 a.out
  2. -c:只编译,不连接成为可执行文件,编译器只是由输入的 .c 等源代码文件生成 .o 为后缀的目标文件
  3. -g:产生调试工具:(GUN的gdb)所必要的符号信息,要想对编译的程序进行调试,就必须加入这个选项
  4. -O:对程序进行优化编译、链接,采用这个选项,整个源代码会在编译、连接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、连接的速度就相应地要慢一些。
  5. -O2:比-O更好的优化编译、连接,当然整个编译、连接过程会更慢。

11. 常用Linux命令

  • pwd:查看当前目录
  • ls:查看当前目录下文件
  • cd:切换目录
  • chmod:修改文件权限

第三章 文件系统

1. 什么是文件系统

文件系统包含两个层次的含义:

  1. 按照固定格式组织的目录与文件(看得见)
  2. 在特定的存储介质.上管理这些目录和文件需要的数据(看不见)

文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构;即在存储设备上组织文件的方法。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。

2. Windows常用文件系统

  • FAT(File Allocation Table)
    • FAT16
    • FAT32
  • NTFS(New Technology File System)
  • exFAT(Extended File Allocation Table)
    • 又叫FAT64

3. Linux常用文件系统

ext2、ext3、vfat、ntfs、iso9660、jffs、romfs、nfs

4. 嵌入式Linux常用文件系统

jffs2, yaffs, cramfs, romfs, ramdisk, ramfs/tmpfs

5. 文件类型

  • 普通文件(-)
    从Linux的角度来说,类似mp4、pdf、html这样应用层面上的文件类型都属于普通文件 Linux用户可以根据访问权限对普通文件进行查看、更改和删除。
  • 目录文件(d,directory file)
    目录文件对于用惯Windows的用户来说不太容易理解,目录也是文件的一种。
    目录文件包含了各自目录下的文件名和指向这些文件的指针,打开目录事实上就是打开目文件,只要有访问权限,你就可以随意访问这些目录下的文件(普通文件的执行权限就是目录文件的访问权限),但是只有内核的进程能够修改它们。
    虽然不能修改,但是我们能够通过vim去查看目录文件的内容。
  • 符号链接文件(l,symbolic link)
    这种类型的文件类似Windows中的快捷方式,是指向另一个文件的间接指针,也就是我们常说的软链接。
  • 块设备文件(b,block)和字符设备文件(c,char)
    这些文件一般隐藏在/dev目录下,在进行设备读取和外设交互时会被使用到
    比如磁盘光驱就是块设备文件,串口设备则属于字符设备文件
    系统中的所有设备要么是块设备文件,要么是字符设备文件,无一例外。
  • FIFO(p,pipe)
    管道文件主要用于进程间通讯。比如使用mkfifo命令可以创建一个FIFO文件,启用一个进程A从FIFO文件里读数据,启动进程B往FIFO里写数据,先进先出,随写随读。
  • 套接字(s,socket)
    用于进程间的网络通信,也可以用于本机之间的非网络通信这些文件一般隐藏在/var/run目录下,证明着相关进程的存在。

6. 什么是 VFS

VFS:Virtual File System虚拟文件系统或Virtual File Switch虚拟文件转换/开关

VFS是Linux和UNIX文件系统中采用的一种技术机制,旨在一个操作系统中支持多个不同类型的文件系统。

7. VFS 作用

VFS提供上/下两类接口

  • 上层接口是提供给用户使用。这些用户包括应用程序和内核的其它管理模块。通过该接口使用I/O系统,如打开,关闭等。
  • 下层接口提供给真实文件系统。VFS支持的每个真实文件系统都提供对这个接口的实现。只要实现了这组接口,VFS就认为它是一个真实的文件系统。

image-20200630000705358

第四章 MTD子系统

1. NOR Flash与NAND Flash

嵌入式存储技术的发展促进了嵌入式闪存的变革,目前流行的小型存储设备例如U盘等几乎都是以闪存作为存储介质。闪存的制造工艺决定了其体积小、非挥发性与抗震性的优点,常见的闪存有NOR与NAND flash。

  • NOR FLASH的特点是芯片内执行,程序可直接在芯片上运行,不用像NAND FLASH那样将程序拷贝至内存中执行。使用方便,存储与读写方式上与内存类似,读写速度高并支持片上运行与随机读写,非常适合嵌入式系统的小容量存储。

image-20200630001418901

2. 什么是 MTD

MTD(memory technology device内存技术设备):
是用于访问memory设备(ROM、flash)的Linux的子系统。MTD的主要目的是为了使新的memory设备的驱动更加简单,为此它在硬件和上层之间提供了一个抽象的接口。

MTD主要就是为NorFlash和NandFlash设计的其余像接口映射、RAM和ROM都是辅助功能。

3. MTD 作用

​ 闪存既不满足块设备描述也不满足字符设备的描述。它们表现的类似块设备,但又有所不同。比如,块设备不区分写和擦除操作。因此,一种符合闪存特性的特殊设备类型诞生了, 就是 MTD 设备。所以 MTD 既不是块设备,也不是字符设备。

4. Flash设备驱动

Linux系统中的Flash设备驱动可将分为四层:

  1. 设备节点
  2. MTD设备层
  3. MTD原始设备层
  4. 硬件驱动层

image-20200630002206733

5. 交叉工具链

image-20200630002523104

6. MakeFile工程管理工具

 一个工程中的源文件按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
1
2
 target: prerequisites (预备知识,先决条件)
command(指令)
  • target:一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。
  • prerequisites:要生成那个target所需要的文件或是目标。
  • command:make需要执行的命令。(任意的Shell命令)

20190402134118712

第五章 调试技术

1. GDB 调试流程

  1. 编译生成可执行文件

    1
    gcc -g test.c -o test
  2. 启动 GDB

    1
    gdb test
  3. 在 main 函数处设置断点

    1
    break main
  4. 运行程序

    1
    run
  5. 使用其他调试命令

2. 其他 GDB 调试命令

  • list(l):查看程序
  • break(b) 函数名:在某函数入口处添加断点
  • break(b) 行号:在指定行添加断点
  • break(b) 文件名:行号:在指定文件的指定行添加断点
  • info break:查看所有设置的断点
  • delete 断点编号:删除断点
  • next(n):单步运行程序(不进入子函数)
  • steps(s):单步运行程序(进入子函数)
  • continues(c):继续运行程序
  • print(p) 变量名:查看指定变量值
  • set var = value:设置变量的值
  • quit(q):退出 gdb

3. Core Dump

Core Dump:核心转存
当程序在运行过程中发生异常,这时Linux系统可以把程序出错时的内存内容存储在一个core文件中,这种过程叫Core Dump。

用来处理一下段错误(Segment fault):

  • 数组访问越界
  • 访问空指针
  • 栈溢出
  • 修改只读内存
1
2
3
4
5
# Linux中默认是关闭 Core dump 功能的
ulimit -c unlimited
# 打开
ulimit -c O
# 关闭

4. 交叉调试(远程调试)结构

​ 远程调试(Remote Debugging):又叫交叉调试(Cross Debugging),是指主机上的调试器通过某种方式能够控制目标机上被调试程序的运行方式,并查看和修改目标机上的内存、寄存器以及被调试程序中的变量等内容的一种调试方式。

image-20200630005201715

宿主机(Host):又称上位机,在远程调试中,是调试器运行的平台;
目标机(Target):又称下位机,是指运行嵌入式软件运行的平台。

image-20200630005309339

5. 调试技术

  1. 在线仿真器ICE技术

    在线仿真器(英语:In-Circuit Emulator,简称:ICE)是调试嵌入式系统软件的硬件设备,是一种有效的工具,可为MCU设计人员提供调试代码和运行硬件的能力。

  2. JTAG技术

    JTAG是一种片上调试OCD(On Chip Debugging)技术的标准协议。片上调试是指在微处理器内的芯片上内置仿真功能实现对目标程序进行调试。现在广泛使用的主要有两种片上调试协议:JTAG(Joint Test Action Group)、BDM(Background Mode Debug)。

  3. 源程序模拟器技术

    源程序模拟器(Simulator)是在广泛使用的、人机接口完备的工作平台上(如PC机),通过软件手段模拟在某个嵌入式处理器上执行的一种测试工具。比较高级的Simulator可以模拟目标机的外部设备。利用Simulator的最大好处就是不用真正的目标机,并且在调试时可以提供更详细的错误诊断信息。

  4. 调式代理技术 (KGDB)

    在目标操作系统和调试器内分别加入某些功能模块,二者互通信息来进行调试,这些功能模块统称为调试代理(debugging agent)。在调试代理方案中,调试器与目标操作系统通过指定通信端口(串口、网卡或USB)遵循远程调试协议进行通信。目标操作系统的所有异常处理最终都要转向调试代理模块,告知调试器当前的异常号,调试器据此向用户显示被调试程序产生了哪一类异常。
    对调试器控制、访问被调试程序的请求都将转换成对被调试程序的地址空间或目标平台的某些寄存器的访问,目标操作系统接收到这样的请求可以直接处理。这样的“调试器对调试代理”组合为代码调试提供了功能强大而低价的解决方案,但也存在一些明显的缺点:调试代理程序需要占用宝贵的系统资源(内存、中断、串口),如果在调试时目标崩溃,对目标的连接往往丢失。

  5. 利用打印消息调试 (知道)

    在调试Linux内核程序时最简单也是最常用的,就是在应用内部合适的点加上printk函数打印需要观察的变量的值来确定错误发生的位置。printk 函数属于内核原生函数不需要C语言函数库的支持,在内核程序的各个部分都能使用。

  6. 利用/porc文件系统调试 (知道)

    /proc 中的文件都是出核心创建的文本文件,这些文件为用户提供了一个动态查询、修改系统运行状态信息的接口。通过/proc文件系统,内核、模块开发者可以对处于运行态的内核和模块进行控制,例如,可以通过对/proc下的kcore文件(当前内核映像)传递参数来动态改变内核行为,同时,在/proc文件系统下还包含了众多关于网络、文件系统的性能微调接口文件,用户可以通过这些微调接口文件完成有关特性的参数调整。

  7. 利用ioctl命令调试 (知道)

    作为替代/proc文件系统的方法,开发人员可以为调试实现若干ioctl 命令。这些命令从驱动程序空间复制相关数据到进程空间,在进程空间里检查这些数据。只有使用ioctl 获取信息比起/proc来要困难一些, 因为必须写一个程序来调用ioctl 并显示结果。必须编写这样的程序,还要编译、保持被测试模块间的一致性等。不过有时候这是最好的获取信息的方法,因为它比读/proc来要快的多。如果在数据写到屏幕前必须完成某些处理工作,以二进制获取数
    据要比读取文本文件有效的多。此外,ioctl 不限制返回数据的大小。ioct方法的一个优点是,当调试关闭后调试命令仍然可以保留在驱动程序中。/proc文件对任何查看这个目录的用户都是可见的,然而与/porc文件不同,未公开的ioctl 命令通常都不会被注意到。此外,如果驱动程序有什么异常,它们仍然可以用来调试,唯一的缺点就是模块会稍微大一些。

6. KGDB 调试原理

​ KGDB 提供了一种使用 GDB 调试 Linux 内核的机制。使用 KGDB 可以象调试普通的应用程序那样,在内核中进行设置断点、检查变量值、单步跟踪程序运行等操作。使用 KGDB 调试时需要两台机器,一台作为开发机(Development Machine),另一台作为目标机(Target Machine),两台机器之间通过串口或者以太网口相连。串口连接线是一根RS-232接口的电缆,在其内部两端的第2脚(TXD)与第3脚(RXD)交叉相连,第7脚(接地脚)直接相连。调试过程中,被调试的内核运行在目标机上,GDB 调试器运行在开发机上。

image-20200630010314284