Linux驱动设计——内核组成

1、内核源码目录结构

下面请看4.4内核根目录的源码:
在这里插入图片描述
简要说明:

  • 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、内核的组成部分

有五个组成部分:

  • 进程调度(SCHED)
  • 内存管理(MM)
  • 虚拟文件系统(VFS)
  • 网络接口(NET)
  • 进程间通信(IPC)

关系如下图所示:
在这里插入图片描述

2.1 进程调度

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

Linux进程状态:

  • 就绪
  • 深度睡眠
  • 浅度睡眠
  • 执行
  • 暂停
  • 僵死

Linux的进程在几个状态间进行切换。在设备驱动编程中,当请求的资源不能得到满足时,驱动一般会调度其他进程执行,并使本进程进入睡眠状态,直到它请求的资源被释放,才会被唤醒而进入就绪状态。睡眠分成可中断的睡眠和不可中断的睡眠,两者的区别在于可中断的睡眠在收到信号的时候会醒。如下图所示:
在这里插入图片描述
应用看将创建线程:pthread_create()
内核控件重建线程:pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);

2.2 内存管理

内存管理的主要作用是控制多个进程安全地共享主内存区域。当CPU提供内存管理单元(MMU)时,Linux内存管理对于每个进程完成从虚拟内存到物理内存的转换。

一般而言,32位处理器的Linux的每个进程享有4GB的内存空间,0~3GB属于用户空间,3~4GB属于内核空间,内核空间对常规内存、I/O设备内存以及高端内存有不同的处理方式。当然,内核空间和用户空间的具体界限是可以调整的,在内核配置选项Kernel Features→Memory split下,可以设置界限为2GB或者3GB。
相关术语技概念:

  • Buddy算法
  • LRU 算法

内存管理的整体体系:
在这里插入图片描述
内存管理这块的内容相对来讲非常复杂,推荐国内笨叔 奔跑吧 linux内核 这本书,对内存管理这块分析的很到位。

2.3 虚拟文件系统

Linux虚拟文件系统隐藏了各种硬件的具体细节,为所有设备提供了统一的接口。而且,它独立于各个具体的文件系统,是对各种文件系统的一个抽象。它为上层的应用程序提供了统一的vfs_read()、vfs_write()等接口,并调用具体底层文件系统或者设备驱动中实
在这里插入图片描述

2.4 网络接口

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

2.5 进程间通信

  • 信号量
  • 共享内存
  • 消息队列
  • 管道
  • UNIX域套接字
    这部分内容在应用层的详细使用,博哥后续会在linux应用开发中逐一讲解。

3、内核的编译及加载

在编译内核的时候,首先需要进行内核模块的配置,英文linux功能强大,在实际的项目中,不可能用到所有模块,尤其是嵌入式设备,在资源相对受限的情况下,裁剪显得尤为重要。经过裁剪后,会在kernel的根目录下生成.config文件,然后内核会根据.config进行编译,生成镜像。

内核的配置系统有三部分:

  • Makefile 分布在内核源码中,定义Linux内核的编译规则
  • 配置文件:给用户提供配置选择功能
  • 配置工具: 界面或是命令解释器

3.1 内核配置的方法

  • make config(基于文本的最为传统的配置界面,不推荐使用)
  • make menuconfig(基于文本菜单的配置界面)
  • make xconfig(要求QT被安装)
  • make gconfig(要求GTK+被安装)

说道这里,请大家一定自己根据实际情况去下载内核去编译。这里使用4.4.252

在这里插入图片描述

3.2 内核及模块的编译

以arm开发板举例:
make ARCH=arm zImage
make ARCH=arm modules

执行完上述命令后,在源代码的根目录下会得到未压缩的内核映像vmlinux和内核符号表文件System.map,在arch/arm/boot/目录下会得到压缩的内核映像zImage,在内核各对应目录内得到选中的内核模块。

猜你喜欢

转载自blog.csdn.net/weixin_42955871/article/details/112981933