第三章 Linux内核及内核编程

第三章   Linux内核及内核编程

3.1 Linux内核的发展与演变

3.2 Linux 2.6后的内核特点

  1. 支持内核任务抢占(中断、软中断、自旋锁等原子上下文进程无法抢占执行)
  2. 总线、设备、驱动实现对设备进行控制。通过一种总线类型,将设备和驱动联系起来,总线中的match()函数用来匹配设备和驱动,完成后会执行驱动程序中的probe()函数。

3.3 Linux内核的组成

  1. 内核源码目录
    arch:对不同平台的支持
    block:块设备驱动I/O调度
    crypto:加密、散列算法、压缩和CRC算法
    documentation:解释和注释
    drivers:设备驱动程序,例如char、block、net、mtd、i2c
    fs:所支持的文件系统,例如EXT、FAT、NTFS、JFFS2等
    include:和系统相关的头文件在include/linux下
    init:内核初始化代码
    ipc:进程间通信代码
    kernel:内核核心部分,包括进程调度、定时器等,和平台相关的一部分代码放在arch/*/kernel下
    lib:库文件代码
    mm:内存管理代码,和平台相关的一部分代码放在arch/*/mm下
    net:网络相关代码,常见的网络协议的实现
    scripts:配置内核的脚本
    security:SElinux模块,安全增强
    sound:ALSA、OSS框架
    usr:用于打包和压缩的cpio等
  2. 内核要求drivers和arch软件架构分离,驱动中不包含板级信息。
  3. 内核的通用部分(kernel、fs、ipc、net等)与硬件剥离(arch、drivers)。
  4. Linux内核主要由进程调度(SCHED)、内存管理(MM)、虚拟文件系统(VFS)、网络接口(NET)和进程间通信(IPC)5个子系统组成。

    1. 在Linux内核中,使用task_struct结构体来描述进程,该结构体中包含描述该进程内存资源、文件系统资源、文件资源、tty资源、信号处理等的指针。
    2. 在内核编程中,如果需要几个并发执行的任务,可以启动内核线程,这些线程没有用户空间。启动内核线程的函数为:
      pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
    3. 32位处理器的Linux的每个进程享有4GB的内存空间,0~3GB属于用户空间,3~4GB属于内核空间
    4. Linux支持进程间的多种通信机制,包含信号量、共享内存、消息队列、管道、UNIX域套接字等,这些机制可协助多个进程、多资源的互斥访问、进程间的同步和消息传递。
    5. CPU内部往往实现了不同操作模式(级别),不同模式有不同功能,高层程序往往不能访问低级功能,而必须以某种方式切换到低级模式。在Linux系统中,内核可进行任何操作,而应用程序则被禁止对硬件的直接访问和对内存的未授权访问。

3.4 Linux内核的编译及加载

  1. 配置内核命令:
    1. make config
    2. make menuconfig(不依赖QT和GTK+)
    3. make xconfig
    4. make gconfig
  2. arch/arm/configs/xxx_defconfig文件包含了许多电路板的默认配置。运行make ARCH=arm xxx_defconfig就可以为xxx开发板配置内核。
    编译内核和模块的命令:
    1. make ARCH=arm zImage
    2. make ARCH=arm modules
    3. 在源代码的根目录下会得到未压缩的内核映像vmlinux和内核符号表文件System.map,在arch/arm/boot/目录下会得到压缩的内核映像zImage,在内核各对应目录内得到选中的内核模块。
  3. 使用make config、make menuconfig等命令后,会生成一个.config配置文件,记录哪些部分被编译入内核、哪些部分被编译为内核模块。
  4. 运行make menuconfig等时,配置工具首先分析与体系结构对应的/arch/xxx/Kconfig文件(xxx即为传入的ARCH参数),Kconfig又可能再次通过source引入下一层的Kconfig
  5. 在Linux内核中增加程序需要完成以下3项工作:
    1. 将编写的源代码复制到Linux内核源代码的相应目录中。
    2. 在目录的Kconfig文件中增加关于新源代码对应项目的编译配置选项。
    3. 在目录的Makefile文件中增加对新源代码的编译条目。
  6. Kconfig语法和Makefile:
    1. 在内核源代码的drivers目录内的相应子目录中增加新设备驱动的源代码或者在arch/arm/mach-xxx下新增加板级支持的代码,同时增加或修改Kconfig配置脚本和Makefile脚本
    2. Makefile语法:
      1. 目标定义:eg:obj -y += a.o 将a.c或者a.s文件编译为a.o
        1. obj -y 无条件编译
        2. obj -m 编译为模块
        3. obj -n 不编译
        4. 常见做法是根据.config文件中的变量进行判断:eg:obj -$(CONFIG_A) += a.o ;eg :obj -$(CONFIG_ABC) += abc.o
      2. 多文件模块的定义
        1. 如果一个模块由多个文件组成,应采用模块名加 -y 或 -objs 后缀
          obj-$(CONfiG_EXT2_FS) += ext2.o 
          ext2-y := balloc.o dir.o file.o fsync.o ialloc.o inode.o ioctl.o namei.o super.o              symlink.o 
          ext2-$(CONfiG_EXT2_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o 
          ext2-$(CONfiG_EXT2_FS_POSIX_ACL) += acl.o 
          ext2-$(CONfiG_EXT2_FS_SECURITY) += xattr_security.o 
          ext2-$(CONfiG_EXT2_FS_XIP) += xip.o
      3. 目录层次的迭代:
        1. obj-$(CONfiG_EXT2_FS) += ext2/  当CONFIG_EXT2_FS的值为y或m时,kbuild将会把ext2目录列入向下迭代的目标中。
    3. Kconfig语法:
      1. 配置选项:
        1. config关键字:定义新的配置选项,之后的几行代码定义了该配置选项的属性。配置选项的属性包括类型、数据范围、输入提示、依赖关系、选择关系及帮助信息、默认值等
        2. 每个配置选项都必须指定类型,类型包括bool、tristate、string、hex和int
        3. 输入提示的一般格式为:prompt <prompt> [if <expr>] 其中if用来提示依赖
        4. 默认值的格式:default <expr> [if <expr>] 
        5. 依赖关系depends on <expr>,如果定义了多重依赖关系,它们之间用“&&”间隔。
        6. 选择关系:select <symbol> [if <expr>]
        7. 数据范围的格式为:range <symbol> <symbol> [if <expr>]
        8. 表达式:
          config SHDMA_R8A73A4
                     def_bool y 
                     depends on ARCH_R8A73A4 && SH_DMAE != n
          表示当ARCH_R8A73A4被选中且SH_DMAE没有被选中的时候,才可能出现这个SHDMA_R8A73A4
        9. 帮助信息:help
      2. 菜单结构:
        1. menu和endmenu:
          menu "Network device support" 
                     depends on NET 
          config NETDEVICES
                      … 
          endmenu
        2. 通过分析依赖关系生成菜单结构。如果菜单项在一定程度上依赖于前面的选项,它就能成为该选项的子菜单。如果父选项为“n”,子选项不可见;如果父选项可见,子选项才可见。
  7. LINUX内核引导:
    1. ARM LINUX内核的引导过程:

      上电时bootrom运行。对于CPU0而言,bootrom会去引导bootloader,而其他CPU则判断自己是不是CPU0,进入WFI的状态等待CPU0来唤醒它。CPU0引导bootloader,bootloader引导Linux内核,在内核启动阶段,CPU0会发中断唤醒CPU1

3.5 Linux编程风格

  1. 下划线命名
  2. Linux的代码缩进使用“TAB”。
  3. Linux中代码括号“{”和“}”的使用原则如下:
    1. 对于结构体、if/for/while/switch语句,“{”不另起一行
    2. 如果if、for循环后只有1行,不要加“{”和“}”
    3. if和else混用的情况下,else语句不另起一行
    4. 对于函数,“{”另起一行
    5. 在switch/case语句方面,Linux建议switch和case对齐
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Linux内核一直是学习的难点:将近3000万行代码,5万多个源文件,代码庞大繁杂、代码很难看懂。《Linux内核编程》将突破以往传统的学习方式,采取更有效和科学的学习方法,多角度地对内核进行多层次分析,不局限于形式,不拘泥细节,目的只有一个:更轻松、更高效地去理解内核、学习内核。为了更好地让学员掌握内核编程技能,更好地理解内核,本课程将采用并不局限于以下学习方法进行课程的录制:降维分析,化简为繁,将复杂的系统简单化用软件工程的方法分析内核:软件分层、模块化分解、框架迭代多角度立体分析Linux内核,目的只有一个:更好地理解内核利用Linux内核中的面向对象编程思想去分析复杂的子系统、子系统交互利用多任务编程的思想去分析Linux内核本套课程预计分为20个左右的小模块,每个模块一个专题,每个专题会陆续发布。拟录制的模块包括但不限于:模块机制、内核裁剪与配置、内核编译与启动、系统调用、中断、文件系统、调度、内存管理、内核同步、设备模型、字符驱动、块驱动、定时器、input、platform设备驱动、device tree、proc、sysfs、I/O...  本课程是《Linux内核编程》的入门篇,主要给大家介绍一下Linux内核开发、Linux驱动开发的就业行情、行业生态、需要掌握哪些技能、Linux内核的学习方法、如何搭建Linux内核的学习开发环境。 
Linux内核编程指南(第三版)》是一本对Linux操作系统内核编程进行详细介绍和指导的重要参考书。该书由 Linux 内核的主要维护者之一,Jonathan Corbet 等人共同编写,是学习和理解Linux内核编程的重要工具。 首先,《Linux内核编程指南(第三版)》从基础知识开始介绍了Linux内核的结构和组织,帮助读者了解Linux内核的基本概念,包括进程管理、内存管理、文件系统、设备驱动等核心内容。同时,该书还对Linux内核的设计原则和工作机制进行了深入解析,使读者能够更好地理解Linux内核的运行机制。 其次,该书还详细介绍了Linux内核编程的工具和技术,包括编译和调试工具的使用、内核模块的编写和加载,以及异常处理和中断处理等内容。这些内容都是Linux内核编程必备的知识和技能,读者可以通过学习该书中的实例和案例,更好地理解和掌握Linux内核编程的方法和技巧。 此外,《Linux内核编程指南(第三版)》还介绍了Linux内核的最新发展和变化,包括对最新内核版本的支持和适应,以及对Linux内核开发的最新趋势和发展方向的展望。这些内容使得该书具有时效性和实用性,读者可以及时了解到最新的Linux内核编程技术和方法。 综上所述,《Linux内核编程指南(第三版)》是一本权威性、全面性和实用性的Linux内核编程指南。通过阅读该书,读者可以深入了解Linux内核的工作原理和设计原则,并具备进行Linux内核编程的基本技能和知识。无论是对于Linux内核开发者,还是对于对Linux内核感兴趣的读者,都是一本不可或缺的参考书。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值