Linux内核

1. Linux内核代码的目录结构

Linux 内核源代码包含如下目录。

● arch :包含和硬件体系结构相关的代码,每种平台占一个相应的目录,如 i386、arm、 arm64、powerpc、mips 等。Linux 内核目前已经支持 30 种左右的体系结构。在 arch 目录下,存放的是各个平台以及各个平台的芯片对 Linux 内核进程调度、内存管理、 中断等的支持,以及每个具体的 SoC 和电路板的板级支持代码。

● block:块设备驱动程序 I/O 调度。

● crypto:常用加密和散列算法(如 AES、SHA 等),还有一些压缩和 CRC 校验算法。 ● documentation:内核各部分的通用解释和注释。

● drivers :设备驱动程序,每个不同的驱动占用一个子目录,如 char、block、net、 mtd、i2c 等。

● fs:所支持的各种文件系统,如 EXT、FAT、NTFS、JFFS2 等。

● include:头文件,与系统相关的头文件放置在 include/linux 子目录下。

● init:内核初始化代码。著名的 start_kernel() 就位于 init/main.c 文件中。 ● ipc:进程间通信的代码。

● kernel :内核最核心的部分,包括进程调度、定时器等,而和平台相关的一部分代码 放在 arch/*/kernel 目录下。

● lib:库文件代码。

● mm:内存管理代码,和平台相关的一部分代码放在 arch/*/mm 目录下。 ● net:网络相关代码,实现各种常见的网络协议。

● scripts:用于配置内核的脚本文件。

● security:主要是一个 SELinux 的模块。

● sound:ALSA、OSS 音频设备的驱动核心代码和常用设备驱动。

● usr:实现用于打包和压缩的 cpio 等。

● include:内核 API 级别头文件。

2. Linux内核的组成

Linux 内核主要由进程调度(SCHED)、内存管理(MM)、虚拟文件系统 (VFS)、网络接口(NET)和进程间通信(IPC)5 个子系统组成。

2.1 进程调度

进程调度控制系统中的多个进程对CPU的访问,使得多个进程能在CPU中“微观串行, 宏观并行”地执行。进程调度处于系统的中心位 置,内核中其他的子系统都依赖它,因为每个子 系统都需要挂起或恢复进程。Linux 的进程在几个状态间进行切换在设备驱动编程中,当请求的资源不能得到满足时,驱动一般会调度其他进程执行, 并使本进程进入睡眠状态,直到它请求的资源被释放,才会被唤醒而进入就绪状态。睡眠分成可中断的睡眠不可中断的睡眠,两者的区别在于可中断的睡眠在收到信号的时候会醒。

在 Linux 内核中,使用task_struct结构体来描述进程,该结构体中包含描述该进程内存资源、文件系统资源、文件资源、tty资源、信号处理等的指针。Linux 的线程采用轻量级进程模型来实现,在用户空间通过pthread_create()API创建线程的时候,本质上内核只是创建了一个新的 task_struct,并将新task_struct的所有资源指针都指向创建它的那个task_struct 的资源指针。 绝大多数进程(以及进程中的多个线程)是由用户空间的应用创建的,当它们存在底层资 源和硬件访问的需求时,会通过系统调用进入内核空间。有时候,在内核编程中,如果需要几个并发执行的任务,可以启动内核线程,这些线程没有用户空间。启动内核线程的函数为

pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long ffags);

2.2 内存管理

2.3 虚拟文件系统

2.4 网络接口

2.5 进程间通信

2.6 Linux 内核空间与用户空间的概念

3. Linux内核模块

Linux设备驱动会以内核模块的形式出现。

内核模块的特点:

  • 模块本身不被编译进内核映像,从而控制了内核的大小;
  • 模块一旦被加载,他就和内核中的其他部分完全一样。

一个内核模块主要由以下几部分组成:

  1. 模块加载函数。当通过insmod或modprobe 命令加载内核模块时,模块的加载函数会自动被内核执行完成本模块的相关初始化工作。
  2. 模块卸载函数。当通过mmmod命令卸载某模块时,模块的卸载函数会自动被内核执行,完成与模块卸载函数相反的功能。
  3. 模块许可证声明。许可证(LICENSE)声明描述内核模块的许可权限,如果不声明LICENSE,模块被加载时,将收到内核被污染(KernelTainted)的警告。在Linux内核模块领域,可接受的LICENSE包括“GPL”、“GPL V2”、“GPL andadditional rights"、“ Dual BSD/GPL”、" Dual MPL/GPL"和“Proprietary”(关于模块是否可以采用非GPL许可权,如“Proprietary”,这个在学术界和法律界都有争议)。大多数情况下,内核模块应遵循GPL兼容许可权。Limux内核模块最常见的是以MODULELICENSE(“GPLv2”)语句声明模块采用 GPL v2。
  4. 模块参数(可选)。模块参数是模块被加载的时候可以传递给它的值,它本身对应模块内部的全局变量。
  5. 模块导出符号(可选)。内核模块可以导出的符号(symbol,对应于函数或变量),若导出,其他模块则可以使用本模块中的变量或函数。
  6. 模块作者等信息声明(可选)

PS:为什么编译驱动程序之前要先编译内核?

驱动程序要用到内核文件:比如驱动程序中这样包含头文件:#include <asm/io.h>,其中的 asm 是 一个链接文件,指向 asm-arm 或 asm-mips,这需要先配置、编译内核才会生成 asm 这个链接文件。

编译驱动时用的内核、开发板上运行到内核,要一致: 开发板上运行到内核是出厂时烧录的,你编译驱动时用的内核是你自己编译 的,这两个内核不一致时会导致一些问题。所以我们编译驱动程序前,要把自己 编译出来到内核放到板子上去,替代原来的内核。

更换板子上的内核后,板子上的其他驱动也要更换: 板子使用新编译出来的内核时,板子上原来的其他驱动也要更换为新编译出 来的。所以在编译我们自己的第 1 个驱动程序之前,要先编译内核、模块,并且 放到板子上去。

PS:韦东山im6ull开发板内核编译步骤:

  1. make mrproper命令通常用于清理构建环境;
  2. make 100ask_imx6ull_defconfig命令这个命令的目的是选择或设置一个特定的配置(在这个例子中是100ask_imx6ull_defconfig),以便为接下来的构建过程准备内核或系统;
  3. make zImage J4 命令。这条命令通常用于构建Linux内核的zImage格式的内核映像,并且可能包含了一个特定的目标板(board)或配置(configuration)参数J4;
  4. make dtbs命令。编译设备树文件。
  5. cp arch/arm/boot/zImage /home/book/nfs_rootfs。拷贝zImage到Ubuntu某个目录备用。
  6. cp arch/arm/boot/dts/100ask_imx6ull-14x14.dtb /home/book/nfs_rootfs。拷贝设备树到Ubuntu某个目录备用。
  7. make modules命令。编译内核模块。
  8. make ARCH=arm INSTALL_MOD_PATH=/home/book/nfs_rootfs modules_install。安装内核模块到ubuntun某个目录备用。

SYNC命令的使用非常简单,只需要在终端中输入“sync”即可。执行SYNC命令后,系统会立即将内存缓冲区中的数据写入磁盘,确保数据的完整性和安全性。同时,SYNC命令也会释放与这些数据对应的buffer,使得这些buffer可以被重新使用,提高了系统的运行效率。

  • 9
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值