• 《Linux4.0设备驱动开发详解》笔记第二章:Linux内核及内核编程


    2.1 Linux内核发展及演变

    • 1991年10月5日 Linus Torvalds创建
    • 五个支柱:Unix系统、Minix系统、GNU计划、POSIX标准和Internet
    • 每2-3个月更新一次大的版本号

    2.2 Linux2.6后的内核特点

    1. 新的调度器:高负荷下的出色性能,更好的处理器扩展,采用CFS算法,新增调度类:SCHED_DEADLINE,它实现了EDF(最早截止期限优先)算法
    2. 内核抢占:提高系统的实时性,增强系统的交互性,但也有不可抢占的空间:中断上下文、软中断上下文和自旋锁的区间,如果打上RT-Preempt补丁,即可支持硬实时。
    3. 改进线程模型:采用NPTL(本地POSIX线程库)模型,操作速度极大提高,更加遵循POSIX规范
    4. 虚拟化内存变化:融合了r-map(反向映射,通过页结构快速找到页面的映射)技术,改善虚拟内存在一定大小负载下的性能
    5. 文件系统:新增基于B树的Btrfs,是下一代的Linux文件系统
    6. 音频:高级Linux音频体系结构ALSA取代缺陷很多的OSS,支持USB音频和MIDI设备,并支持双工重放等功能
    7. Linux3.7以后实现一个Linux可以适用于所有的arm系统

    2.3 Linux内核组成

    2.3.1 Linux内核代码的目录结构

    • arch:和硬件体系结构相关的代码,每个平台每个目录
    • block:块设备驱动的I/O调度
    • crypto:常用加密和散列算法,还有一些压缩以及CRC校验算法
    • documentation:内核各部分的通用解释和注释
    • fs:支持的各种文件系统
    • include:内核API级别的头文件,与系统相关的头文件放在include/linux子目录下
    • init:内核代码的初始化代码
    • ipc:进程间通信代码
    • lib:库文件代码
    • mm:内存管理代码
    • script:配置内核的脚本文件
    • usr:用于打包和压缩的cpio等

    2.3.2 内核组成部分

    • 进程调度:多数进程是由用户空间创建,通过系统调用进入内核空间,内核编程是可以启动内核线程来处理并发任务,这些线程没有用户空间
    • 内存管理:控制多个进程安全的共享内存区域,通过MMU完成进程从虚拟空间向物理空间的转换
    • 虚拟文件系统:隐藏各个硬件的具体细节,为所有的设备提供了统一的接口,是文件系统的抽象
    • 网络接口:对各种网络标标准的存取和各种网络硬件的支持,分为网络协议和网络驱动程序
    • 进程间通信:信号量、共享内存、消息队列、管道以及Unix域套接字等

    2.3.3 内核空间和用户空间

    • 内核可以进行任何操作,但应用程序被禁止对硬件的直接访问和对内存的未授权访问
    • 这两个名词用来区分程序执行的两种不同的状态,他们使用不同的地址空间,用户空间可以通过系统调用和硬件中断来访问内核空间

    2.4 内核的编译及加载

    2.4.1 Linux内核配置系统组成

    • Makefile:分布于内核源代码
    • 配置文件(Kconfig):给用户提供配置选项
    • 配置工具:命令解析器和配置用户界面,都是脚本语言
    • 通过make config、make menuconfig生成.config文件记录哪部分被编入内核,哪部分被编译成模块
    • source可以引入每一层的Kconfig

    2.4.2 Kconfig和Makefile

    2.4.2.1linux增加程序需要完成以下3项工作

    • 将编写的源码复制到Linux内核源代码相应得目录中
    • 在目录的Kconfig文件中增加关于源代码相应的编译配置选项
    • 在目录的Makefile文件中增加对新源代码的编译条目

    2.4.1.2Makefile语法规则

    • 目标定义:用来定义哪些内容要作为模块编译,哪些要编译并链接进内核,如:obj-y/m/n += foo.o,obj-$(CONFIG_ISDN) += isdn.o
    • 多文件模块的定义:如下,模块名为ext2,有balloc.o、dir.o等目标文件最终链接生成ext2.o直至ext2.ko文件,是否包含xattr.o、acl.o等文件取决于内核配置文件的配置情况。
    obj-$(CONFIG_EXT2_FS) += ext2.o
    ext2-y :=balloc.o dir.o file.o ...
    ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o xattr_user.o ...
    ext2-$(CONGIF_EXT2_FS_XIP) += xip.o
    • 目标层次迭代:如下, 当CONFIG_EXT2_FS的值为y或者m时,kbuild将会把ext2目录列入向下的目录中
    obj-$(CONFIG_EXT2_FS) += ext2/

    2.4.2.3Kconfig语法规则

    配置选项

    大多数内核配置选项对应的Kconfig中的一个配置选项,”config” 关键字定义新的配置选项,之后的几行代码定义了诶配置选项的属性。配置选项的属性包含:类型,数据提示,依赖关系,选择关系以及帮助信息、默认值等

    config MODVERSIONS
        bool "Module versioning support"
        help
            Usually, you have to use modules compiled with your kernel.
            Saying Y here makes it ...
    • 每个配置选择必须包含指定的类型,包括bool,tristate, string, hex 和int,其中tristate和string是基本的类型,其他类型都是基于这两种类型,类型定以后可以紧跟输入提示,下面两段脚本是等价的
    bool "Networking support"bool
    prompt "Networking support"
    • 输入提示的一般格式为以下形式,其中可选的if用来表示该提示的依赖关系。
    prompt <prompt> [if <expr>]

    默认值的格式为以下形式,如果用户不设置对应的选项则配置选项的值就是默认值

    default <expr> [if <expr>]
    • 依赖关系的格式为以下形式,多重依赖中间要用“&&”间隔
    depends on (或者requires) <expr>

    依赖关系也可以用在菜单中的其他选项,如下两段脚本是等价的

    bool "foo" if BAR
    default y if BAR
    和
    depends on BAR
    bool "foo"
    default y
    • 选择关系的格式如下,如果A选择了B,那么A选中的情况下自动选中B
    select <symbol> [if <expr>]
    • 数据范围格式如下
    range <symbol> <symbol> [if <expr>]
    • Kconfig中的expr定义如下
    <expr> :: <symbol>
                <symbol> '=' <symbol>
                <symbol> '!' <symbol>
                '(' <expr> ')'
                '!' <expr>
                    <expr> '&&' <expr>
                    <expr> '||' <expr>

    symbol分为两类,一类由菜单入口配置项定义的非常数symbol,另一类是作为expr组成部分常数symbol。比如

    config SHDMA_R8A73A4
           def_bool y
           depends on ARCH_R8A73A4 && SH_DMA != n

    表达式“depends on ARCH_R8A73A4 && SH_DMA !=n”暗示只有当ARCH_R873A4被选中,而SH_DMA没有选中的时候,才可能出现这个SHDMA_R8A73A4。

    • 为int和hex类型的选项设置可以接受的输入值范围,用户只能输入大于等于第一个symbol,且小于等于第二个symbol的值
    • 帮助信息的格式为
    help(或---help---)
        开始
        ...
        结束

    菜单结构

    配置选项在菜单结构的中的位置可有两种方法决定。
    第一种方法为:

    menu "Network device support"
        depends on NET
    config NETDEVICES
        ...

    所有处于“menu”和“endmenu”中的选项都会成为“Network device support”的子菜单,而且,所有的子菜单(config)选项都会继承父菜单(menu)的依赖关系,比如,“Network device support”对“NET”的依赖会被加载到配置选项NETDEVICES的依赖列表中。
    注意:menu后面跟的“Network device support”项仅仅是一个菜单,没有对应真实的匹配项,也不具备不同的三种状态,这与config的区别。

    另一种方法为:
    同过分析依赖关系生成菜单结构。如菜单项在一定程度上依赖与前面的选项,他就能成为该选项的子菜单。如果父选项为“n”,子选项不可见;如果父选项可见,子选项才可见。例如:

    config MODULES
        bool "Enable loadable module support"
    
    config MODVERSIONS
        bool "Set version information on all module symbol"
        depends on MODULES
    
    comment "module support disabled"
        depends on !MODULES

    MODVERSIONS直接依赖MODULES,只有MODULES不为“n”时,该选项才可见。
    除此之外,Kconfig中还可能使用“choices … endchoice”、”comment”、“if…endif”这样的语法结构。其中“choices … endchoice”的结构

    choice
    <choice options>
    <choice block>
    endchoice

    它定义一个选择群,其接受的选项(choice potions)可以是前面描述的任何属性,例如,LDD6410的VGA输出分辨率可以是1024*768或者是800*600,在driver/video/samsung/Kconfig中就定了如下choice

    choice
    depends on FB_S3C_VGA
    prompt "Select VGA Resolution for S3C Framebuffer"
    default FB_S3C_VGA_1024_768
    config FB_S3C_VGA_1024_768
        bool "1024*768@60Hz"
        ---help---
        TBA
    config FB_S3C_VGA_640_480
        bool "640*480@60Hz"
        ---help---
        TAB
    endchoice

    上述例子中,prompt配合choice起到提示的作用。
    具体例子见《Linux设备驱动开发详解》第三版 P72-73

    2.4.3 Linux内核的引导

    1. 上电 => SOC嵌入bootrom 引导=> CPU0上的bootloader
    2. 其他非CPU0进入WFI状态等待CPU0唤醒
    3. CPU0引导bootloader唤醒非CPU0,唤醒后和CPU0都投入运行
    4. CPU0导致用户空间的init程序被调用,init派生出其他进程,其他进程在派生出其他进程
    5. bootloader代表为uboot,其代码仓库:http://git.devx.de/u-boot.git/
    6. zimage:是由未压缩的解压算法和压缩的内核组成,bootloader负责解压
  • 相关阅读:
    redis入门
    elementui入门
    1387:搭配购买(buy)
    P1536 村村通
    1388:家谱(gen)
    1389:亲戚
    1385:团伙(group)
    P1305 新二叉树
    P5076 【深基16.例7】普通二叉树(简化版)
    二叉搜索树(BST)模版
  • 原文地址:https://www.cnblogs.com/zcjboke/p/5513137.html
Copyright © 2020-2023  润新知