1   CentOS5.X/6.X平台内核定制与编译

1.1 为什么选择centos

centos是redhat红帽公司企业发行版rhel系列的开源发行版本,它也是面向企业服务器架构的,由于紧跟redhat rhel商业版本的步伐,centos的成熟度/稳定性都有保证,特别是能够全面并及时支持新型的驱动著称,更为重要的是centos发行版本更适合内核开发者进行内核开发,提供了非常便捷的开发环境,基本上不需要配置即可立刻开始内核开发。当然市面上还有ubuntu,suse等一批优秀的发行版本,有的适用于pc桌面用户,有的不具备灵活快捷的内核开发支撑,我们推荐在此次系列课程培训中使用centos发行版本,当然只要我们具备了linux系统扎实的基础和经验,大家一定会快速的无缝的切换到其它发行版本的使用上,这一块大家不用太过纠结和担心,内核是一样的相通的,发行版本只是提供了桌面化的窗口使用环境和系统服务。

1.2 为什么centos5.2和centos6.2都要介绍

当前centos重点推进维护的是5.x/6.x系列,有的企业环境长时间内还在使用5.x系列系统,因为5.x非常成熟稳定,有的则紧跟步伐shiyong 6.x系列,我们的系列课程从5.x/6.x上各选择一款版本进行介绍,一个方面的考虑是5.x/6.x在内核编译上细节上略有不同,通过比较式的学习大家能够更全面的掌握编译技能,同时我们在后续过滤块设备驱动开发实战的课程中也有所考虑,5.x/6.x列列的内核版本是不同的,通过在不同的内核版本上进行驱动开发实战可以让大家实际感受和练习一下如何进行内核代码的移植,比如将自己写好的在5.2版本内核上运行的驱动移植到6.2内核上运行。

1.3 什么是内核编译与定制

操作系统就是内核,内核也是一堆程序代码,这堆代码一样要通过编译器编译成二进制代码后才能在机器上运行,内核代码又是很庞大的,为了编译它,优秀的内核开发人员精心设计了编译步骤,并尽量封装简化过程,让其操作方便,这就是内核编译,也是我们上册课程主要跟大家分享的。

内核定制,顾名思义就是有选择性的加入或者拿掉内核的功能或者模块,平常老听到所谓的内核裁减其实就是这个意思,举个例子来说,就跟汽车选择配件一样,发动机引擎是必不可少的,真皮座椅是可选择的,定制也就是这样,聪明的内核作者们精心设计了一个简单可操作的界面让你进行定制选择,接下来我们赶紧揭开这个面纱吧。

1.4 热热身,作点准备工作- 写一个简单的内核模块

我们在实战内核编译前,先热热身,大家直接来写一个内核代码模块,先体会一下如何进行内核代码开发,这个例子非常简单,并且在后续章节介绍相关功能时都会应用到此模块。

我们首先贴一下内核代码源文件talk.c

#include<linux/module.h>

static int__init talk_init(void)

{

printk(”Welcome to Trace the linuxkernel!\n");

return 0;

}

staticvoid __exit talk_exit(void)

{

printk("mod exitsuccessfuly!\n");

}

module_init(talk_init);

module_exit(talk_exit);

MODULE_LICENSE("GPL");

大家可以实际在自己虚拟机上把这几行代码敲一下,在这里我们先不做过多介绍这个代码的解读,里面有很多奇怪的名字或者关键字,有些是内核特定的宏定义,大家先认识一下,先不要尝试一下子全部理解,我们在下册内核块设备开发时会慢慢告诉大家如何理解这个代码,现在先让我们照葫芦画瓢,动手写写,主要是为接下来我们的内核编译作点准备工作,然后我们再写一个Makefile文件,来指导我们如何编译talk.c文件内核代码,Makefile如下:

obj-m:=talk.o

KERNELDIR?= /lib/modules/$(shell uname -r)/build

PWD := $(shell pwd)

default:

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:

rm -rf *.o *~ core .depend .*.cmd *.ko*.mod.c *.tmp_versions *.symvers .tmp_versions

好了,至此我们写好了一个简单的内核模块,执行make即可把talk.c编译为内核模块,然后执行insmod talk.ko,我们就把talk.ko插入内核中了,dmesg敲一下看看,最后输出信息是否打出了talk_init函数中的打印的信息,然后执行rmmod talk再dmesg看看是否再最后又打出了talk_exit函数中打印的信息。注意这两个函数很简单,都是调用printk打印信息,并且要注意这不同于我们写应用程序代码中使用的printf函数,而是换了个名字叫printk,这是内核的打印信息函数,这也是我们遇到的第一内核API函数,insmod和rmmod命令是用于加载和卸载内核模块用的。下面针对内核模块的构造和运行进行了几个知识点的分析,大家可以预先熟悉一下,在下册块设备驱动实战中会继续剖析。

关于头文件

大部分内核代码中都要包含相当数量的头文件,以便获得函数、数据类型和变量的定义。有些头文件是专门用于模块的,必须包含在每个可装载的模块中。所有的模块代码中都包含下面这代码:

#include <linux/module.h>

module.h包含有可装载模块需要的大量符号和函数的定义。

许可证

尽管不是严格要求的,但模块应该指定代码所使用的许可证,需要包含:

MODULE_LICENSE("DualBSD/GPL");

表示模块遵行公共许可,一般来说都要加上,这样不会出现警告。"Dual BSD/GPL"是BSD/GPL双重许可证。

函数printk在Linux内核中定义,模块能够调用它是因为在insmod函数装入模块后,模块就连接到了内核,因而可以访问内核的公用符号。

编译过程- Makefile

该makefile文件被执行了两次,当命令行执行make时调用此makefile,此时KERNELRELEASE变量尚未设置,KERNELDIR=选项可以定位内核源码目录,在找到内核源代码树之后,这个makefile会调用default:目标,这个目标会先读源码目录的顶层Makefile文件,M=选项让该makefile在构造modules目标之前返回到模块源代码目录,此时会第二次读取该目录下的Makefile文件,modules目标指向Makefile中obj-m变量设定的模块,然后内核的makefile负责真正构造模块。

初始化函数

模块的初始化函数负责注册模块所提供的任何设施。设施指的是一个可以被应用程序访问的新功能,它可能是一个完整的驱动程序或者仅仅是一个新的软件抽象。初始化函数的实际定义通常如下:

static int __intinitialization_function(void)

{

/*初始化代码*/

}

module_init(initialization_function);

初始化函数应该被声明为static,因为它在特定文件之外毫无意义。而一个模块函数如果要对内核其他部分可见,必须被显示导出方可。__init标记表示该函数仅在初始化期间使用。在模块被卸载之后,模块装载器会将初始化函数扔掉,释放内存。因此不要在结束初始化后仍要使用的函数(或者数据结构)上使用__init标记(和__initdata)两个标记。module_init的使用是强制性的。这个宏会在模块的目标代码中增加一个特殊的段,用于说明内核初始化函数所在的位置。没有这个定义,初始化函数永远不会被调用。

模块清除函数

每个重要的模块都需要一个清除函数,该函数在模块被移除前注销接口并向系统中返回所有资源。该函数定义如下:

static void __exit cleanup_function(void)

{

/*清除代码*/

}

module_exit(cleanup_function);

清除函数没有返回值,因此被声明为void。__exit标记代码仅用于模块卸载。如果模块被直接内嵌到内核中,或者内核的配置不允许卸载模块,则被标记为__exit的函数将被简单地丢弃。因此被标记为__exit的函数只能在模块被卸载或者系统关闭时被调用,其他的任何用法都是错误的。如果一个模块未定义清除函数,则内核不允许卸载该模块。

内核定制与编译准备工作相关推荐

  1. 编译linux源码报错,记录一次Linux内核源码编译实验

    记录一次Linux内核源码编译实验 文章目录 记录一次Linux内核源码编译实验 0. 实验环境 1. 选择.下载内核源码 2. 安装必要的依赖软件以及性能要求 3. 解压.配置和编译内核源码 3.1 ...

  2. linux 内核驱动模块的编译及加载

    主机:Windows 7旗舰版,VMware7.1.2,Fedora9 编译环境:arm-linux-gcc 4.4.3 Linux版本:linux-2.6.32.2 busybox版本:busybo ...

  3. Linux内核裁剪及编译

    Linux内核裁剪及编译可加载模块 一 Linux基础知识 linux内核组要由五个子系统组成: 进程调度 内存管理 文件系统 网络接口 进程间通信 Linux源码目录 arch    目录中包含于体 ...

  4. 如何将内核静态库编译连接到驱动程序中去【转】

    转自:http://blog.csdn.net/ganjianfeng2003/article/details/8089551 如何将内核静态库编译连接到驱动程序中去 2010-12-07 08:27 ...

  5. 【华为云技术分享】Linux内核的分布式编译(2)

    上一期中我们介绍了用源码包安装distcc的方法,这一期我们尝试用distcc对Linux 4.19.90内核进行分布式编译. 一.Linux内核的分布式编译 我们尝试用同一个子网中的三台服务器对Li ...

  6. 【华为云技术分享】Linux内核的分布式编译(1)

    上一期中我们介绍了Linux内核模块依赖图的绘制方法,这一期中我们将介绍Linux内核的分布式编译方法和分布式编译工具distcc的安装过程. 一.Linux内核的分布式编译 分布式编译是指将源程序通 ...

  7. linux 网络内核 ko文件,编译内核模块 .ko文件缺少:mmzone.h bounds.h

    出现的问题:编译的时候提示缺少头文件 mmzone.h ....bounds.h...等 include/linux/mmzone.h:18:26: error: linux/bounds.h: No ...

  8. Android 内核源码编译记录

    注:此处内容总结自google官网:AOSP 编译内核.编译完成后刷机部分参考自其他大佬的文章.文中末尾提供了上传至CSDN的msm内核和Aarch64gcc工具 的下载链接,不想从官网下载的可以直接 ...

  9. 【linux内核-源码编译之centos7】

    linux内核-源码编译之centos7 一. 为什么要编译内核 二.疑难杂症 三.演示环境 四.下载源码 4.1.两者源码区别 4.2.将获取到的源码放在/usr/src/kernels/ 下 五. ...

最新文章

  1. 在数据中心利用AI的5个理由
  2. python爬虫教程网-python爬虫入门10分钟爬取一个网站
  3. Docker Hub 镜像加速器
  4. 为自己的网站添加RSS功能(转载)
  5. WinRAR 命令行简体中文说明
  6. 表格内容排序(js实现)
  7. Lecture 2 Asymptotic Notation
  8. RESTful最佳实践
  9. ScrollView嵌套listview高度适应
  10. PHP获取本月当月,起始结束日期
  11. matlab分析分子动力学,分子动力学程序框架
  12. T检验、F检验、Z检验、卡方检验
  13. 往事如烟 - 老钟14
  14. 混合开发模式下主流移动开发平台分析
  15. 挑战程序设计竞赛(第2版)pdf
  16. 【Flink】参数不生效
  17. 致初级软件开发人员并自勉
  18. Qt QVector 详解:从底层原理到高级用法
  19. 选择 Delphi 2007 ( CodeGear Delphi 2007 for Win32 Version 11.0.2837.9583 ) 的理由
  20. postgresql 数据库巡检

热门文章

  1. LPWSTR类型字符串的用法
  2. Windows禁用驱动强制签名
  3. 2021年第十二届蓝桥杯软件类省赛python组
  4. web性能优化 页面性能优化小结
  5. android粗字体下载,Android中粗字体
  6. 双开大话西游计算机重启,大话小技巧:哥教你缓解多开大话电脑卡机
  7. [UWP]如何使用Fluent Design System (上)
  8. Zynq Linux 使用 SPI ADC (ADS8332)
  9. 从Intel和ARM争霸战,看看做芯片有多难
  10. 定时器Timer(三)—— 定时器Timer的使用