Linux内核开发

Linux内核

  • 1、Linux内核介绍
  • 2、内核结构分析
  • 3、Linux内核部分模块:
  • 4、Linux编程风格
    • 4.1、缩进
    • 4.2、花括号使用如下
    • 4.3、命名规范
    • 4.4、代码长度
    • 4.5、注释
    • 4.6、在程序中对ifdef的处理
    • 4.7、其他
    • 4.8、代码风格的事后修正
  • 5、解Linux镜像的格式及其产生过程
    • 5.1、Linux内核有多种镜像格式:
    • 5.2、zImage镜像产生过程:
    • 5.3、boot.img的生成过程
  • 6、内核的移植
    • 将自己开发的内核代码加入到Linux内核中,需要 有3个步骤:

1、Linux内核介绍

  • Linux内核是Linux系统软件的核心,它的性能对整个 系统的性能起决定作用
  • Linux内核文件数目将近4万个,他们分别位于顶层 目录下的20个子目录中,了解Linux内核的工作过程, 必须从了解其目录结构做起
  • 我们研究并移植的内核为:3.4.39

Linux内核官网https://www.kernel.org/

2、内核结构分析

Linux内核开发_第1张图片

  • arch: 与体系结构相关的代码。对应于每个支持的体系结构,有一个相应的子 目录如x86、arm等与之对应,相应目录下有对应的芯片与之对应

  • drivers: 设备驱动代码,占整个内核代码量的一半以上,里面的每个子目录对应 一类驱动程序,如: block:块设备、char:字符设备、net:网络设备

  • fs:文件系统代码,每个支持的文件系统有相应的子目录,如cramfs, yaffs,jffs2等

  • include: 这里包括编译内核所需的大部分头文件

     与平台无关的头文件放在include/linux子目录下 
     各类驱动或功能部件的头文件(/media、/mtd、/net等)
     与体系相关的头文件 arch/arm/include/ 
     与平台相关的头文件路径 arch/arm/mach-s5p6818/include/mach
    
  • lib:与体系结构无关的内核库代码,与系统调用相关 ,与体系结构相关的内核库代码在arch/arm/lib下

  • init:内核初始化代码,其中的main.c中的start_kernel函数是系统引 导起来后运行的第1个函数,这是研究内核工作过程的起点

  • ipc: 内核进程间通信代码

  • mm:与体系结构无关的内存管理代码, 与处理器体系结构相关的代码在 arch/arm/mm下

  • kernel:内核管理的核心代码,此目录下的文件实现了大多数linux系统的内核函 数,体系结构相关的代码在arch/arm/kernel

  • net: 网络部分代码,其每个目录对应于网络的一个方面

  • scripts:存放一些脚本文件,如配置内核时用到的make menuconfig命令等

  • Documentation:内核相关文档,关于内核各部分的通用解释和注释

  • crypto:常用加密及散列算法,和一些压缩及CRC校验算法

Linux kernel组成:

3、Linux内核部分模块:

进程管理、进程调度、系统调用、中断处理、下半 部和工作队列、内核同步、定时管理、内存管理、
虚拟文件系统、块设备、网络子系统、进程地址空 间、模块机制等等…

4、Linux编程风格

  • 像所有其他大型软件项目一样,Linux制定了一 套编码风格
  • 跟选择一个唯一确定的风格相比,到底选择什么 样的风格反而显得不是那么重要
  • 编码风格的主要规范伴随着Linus一贯的幽默, 都记录在内核源码的Documentation/Coding Style 中了。
  • 制定编码风格的目的,是为了提高编程效率,吸 引更多的开发者眼球。

4.1、缩进

  • 采用制表符(Tab)进行缩进,而不是空格
  • 禁止制表符和空格混合使用

4.2、花括号使用如下

if (flag) {
	fun(); …… 
}
void fun (void) 
{

}
if (flag) 
	fun();

4.3、命名规范

  • Linux规定名称中不允许使用混合大小写字符
  • 单词之间用下划线分隔
  • 避免取有疑惑的简单名称,如pad(),应该写成 platform_add_devices()

4.4、代码长度

  • 每行尽量不超过80个字符(可进行有意义分行切割)
  • 函数体代码长度尽量不超过两屏
  • 函数局部变量尽量不超过十个
  • 根据函数使用频率和函数体大小可以使用inline 声明,以提高调用效率

4.5、注释

  • 一般情况用于描述代码可以做什么和为什么要做,尽量 不写实现方式
  • 函数的修改和维护日志统一集中在文件开头

4.6、在程序中对ifdef的处理

一般不这么用:

……
#ifdef CONFIG_FUN 
	fun(); 
#endif 
……

而是在声明处使用ifdef:

#ifdef CONFIG_FUN 
void fun (void) 
{ 
	…… 
}
#else 
inline void fun (void) { } 
#endif

4.7、其他

  • 指针中的“*”号应靠近变量名,而不是类型关键字
  • 函数之间用空行隔开
  • 函数导出申明紧跟在函数定义的下面
  • 等等……

4.8、代码风格的事后修正

indent命令是大多数Linux系统中都带有的工具,当得到一段 与内核编码风格大相径庭的代码时,可以通过这个工具进行

常用的设置:

indent -npro -kr -i8 -ts8 -sob -l80 -ss -bl  -bli 0

参数说明:

-npro或--ignore-profile  				不要读取indent的配置文件.indent.pro。
-kr  	指定使用Kernighan&Ritchie的格式。
-i8  --indent-level 					设置缩排的格数为8。
-ts8 	设置tab的长度
-sob或--swallow-optional-blank-lines  	删除多余的空白行。
-l80 	代码超过80换行
-ss或--space-special-semicolon  		若for区段只有一行时,在分号前加上空格。
-ncs或--no-space-after-casts  			不要在cast之后空一格。
-bl  	分行显示
-bli 0 	括号缩进为0

5、解Linux镜像的格式及其产生过程

在了解Linux启动流程之前,首先需要了 解Linux镜像的格式及其产生过程

5.1、Linux内核有多种镜像格式:

  • Image:直接生成并且无头部未压缩的内核,一般用于PC机
  • zImage:Image的压缩版,采用gzip进行压缩,比Image体积小, 但启动时需要进行自解压,嵌入式系统中一般采用此种方法
  • uImage:是u-boot专用的一种内核镜像格式,它是在zImage的 基础上又添加了一个长度为64字节的标签头,在u-boot启动时 会去掉此头信息,仍按zImage启动,头信息主要用于区分不同 格式的内核镜像
  • xipImage:片上执行的未压缩内核,(如norflash等)

5.2、zImage镜像产生过程:

Linux内核编译方法:
重命名config_20180626为.config

cp   config_20180626    .config
make
make uImage

对新的内核是需要根据自己需要去配置裁剪:
选择需要的功能模块

make menuconfig

裁剪的结果.config中的变量值,将直接影响到Makefile中的目标是否链接到最终的内核镜像中去。

zImage镜像产生过程:

vmlinux->Image->compressed/vmlinux->zImage
  1. vmlinux是由以下内核代码生成的非压缩镜像(arch/arm/kernel/head.s、kernel/、mm/、fs/、ipc/、crypto/、lib/、 drivers/、net/等等)
  2. Image是使用objcopy工具对vmlinux进行二进制化处理得到的镜像
  3. arch/arm/boot/compressed/vmlinux由压缩的Image和 compressed/head.S、misc.c等文件组成
  4. zImage是由compressed/vmlinux使用objcopy工具二进制化得到
  5. 再对zImage加上头部就成为了uImage

Linux内核开发_第2张图片

5.3、boot.img的生成过程

Linux内核开发_第3张图片
boot.img是使用一种文件系统打包工具制作的,相当 于把各种非必须文件打包在一起成为一整个文件,然 后被烧写进设备

6、内核的移植

  1. Linux内核配置裁剪
make menuconfig
  1. 根据配置裁剪的结果配合Makefile完成内核编译

  2. 在Linux2.6以后的版本中,文件的组织是通过 Kconfig和Makefile来实现的

  3. 通过每层目录的Kconfig和Makefile实现了整个Linux 内核的分布式配置

     Kconfig:对应内核模块的配置菜单
     Makefile:对应内核模块的编译选项
    
  4. Kconfig包含了当前目录下所有模块的配置

  5. 子目录的Makefile在被顶层Makefile调用时,会负责编 译当前目录下的所有模块

  6. 当有新的模块被加入时,需要更改当前目录下的 Kconfig文件,并且更改对应的Makefile文件

     这样在最 终编译之前,可以通过 make menuconfig 对需要添加的模块进行配置和添加 当保存make menuconfig时,
     系统除了会自动更新.config外,还会将选项以宏的形式保存在内核根目录下
     的 include/generated/autoconf.h文件下
    

将自己开发的内核代码加入到Linux内核中,需要 有3个步骤:

  1. 把自己编写的代码放到内核中合适的位置
  2. 把自己开发的功能增加到Linux内核的配置选项中,使 用户能够选中这项功能并编译
  3. 构建或修改Makefile,根据用户的选择,将相应的代码 编译到最终生成的Linux内核中去

具体的操作方法看我上传到CSDN的资料包

你可能感兴趣的:(Linux驱动开发)