创建你自己的内核模块

请注意,假若你修改你的内核,你将不再获得 CentOS 开发小组的支持或帮助。这里所描述的步骤并没有 CentOS 的官方认可。这个教学文档的原意是要帮助你创建自己的内核模块。

在某些情况下你也许会需要更改或创建一个新的内核模块。也许你要加入某个功能,或者只是做一个修正。在这件教学文档内,我们会尝试将一个错误修正加进现有的模块内,然后安装它。

这里假设你已经安装了整个内核的源代码。如果你是按照「我需要内核的源代码」的第 2 部份,它会位於 ~/rpmbuild/BUILD/kernel-2.6.18/linux-2.6.18.`uname -m`/ 这个目录内。这份教学文档亦假设系统是 32 位元的结构。因此 `uname -m` 所返回的符串是 i686,而以上的目录将会是 ~/rpmbuild/BUILD/kernel-2.6.18/linux-2.6.18.i686/。

1. 创建一个内核模块(*.ko)

设我们假设,作为一个样例,你将会针对位於 ~/rpmbuild/BUILD/kernel-2.6.18/linux-2.6.18.i686/fs/cifs/ 目录内的 cif 模块加入修正。

1. 针对源代码档进行所需的修正。

2. 进到内核源代码的主目录。如果这次是内核首次被编译,请设置内核,并谨记在配置文件(.conf)内将相关的组件设为模块。

[user@host]$ cd ~/rpmbuild/BUILD/kernel-2.6.18/linux-2.6.18.i686

[user@host linux-2.6.18.i686]$ make oldconfig

[user@host linux-2.6.18.i686]$ make menuconfig

[user@host linux-2.6.18.i686]$ make prepare

3. 创建编译外置模块时所需的文件。

[user@host linux-2.6.18.i686]$ make modules_prepare

注:就算 CONFIG_MODULEVERSIONING 这个参数已被设置,make modules_prepare 仍然不会创建 Module.symvers 档。因此你必须事先重建整个内核,然后模块版本的功能才会生效。欲知详情,请参阅 /usr/share/doc/kernel-doc-2.6.18/Documentation/kbuild/modules.txt 内的 #2.4 及 #7 部份。

4. 通过指定模块的 Makefile 及源代码的相对路径来编译模块。

[user@host linux-2.6.18.i686]$ make M=fs/cifs

注:藏有模块的目录可以位於任何一个位置。举个例说,假如它位於 ~/mycifs/,你可以在内核源代码的主目录里执行以下的指令:

[user@host linux-2.6.18.i686]$ make M=~/mycifs

5. 除非你编译这个模块作侦错用途,否则你应该删除不必要的符号。

[user@host linux-2.6.18.i686]$ strip --strip-debug fs/cifs/cifs.ko

6. 这个样例创建了 cifs.ko 这个文件。请以 root 的身份将 .ko 文件复制到 /lib/modules//extra/ 目录内。

[root@host linux-2.6.18.i686]# cp fs/cifs/cifs.ko /lib/modules/`uname -r`/extra

要知道更多关於模块安装用的目录,请参阅 /usr/share/doc/kernel-doc-2.6.18/Documentation/kbuild/modules.txt 内的 #6 部份。

7. 以 root 的身份执行 depmod 指令来更新模块的依赖档。

[root@host linux-2.6.18.i686]# depmod -a

8. 还有数个步骤是用来创建不同类型的内核的模块。请编辑内核源代码的主目录内的 Makefile。在 CentOS 5 上,请找寻:

EXTRAVERSION = -prep

然后(按你的情况)取代为:

EXTRAVERSION = -274.12.1.el5

EXTRAVERSION = -274.12.1.el5PAE

EXTRAVERSION = -274.12.1.el5xen

EXTRAVERSION = -274.12.1.el5.centos.plus

EXTRAVERSION = -274.12.1.el5.centos.plusPAE

EXTRAVERSION = -274.12.1.el5.centos.plusxen

如果你将会用 modprobe 来安装模块,这个数字并不重要。(一个 -274.el5 模块可以安装在一个 -274.12.1.el5 内核上,如此类推)。但你必须有 PAE 及 xen 的修饰词才能应用在这类型内核上。

提示:当你为标准内核编译好模块后,编辑 EXTRAVERSION 这行来加入 PAE 或 xen,然后执行 make modules_prepare。接著执行 make M=xxx 来编译 EXTRAVERSION 所指定的内核版本的模块。

2. 利用动态内核模块支持(DKMS)创建一个内核模块

上面所描述的方法是为某个特定的内核版本创建一个模块。一旦你将内核升级或者更改硬件的结构,你将会须要将模块重新创建。动态内核模块支持(DKMS)这个结构基本上是在内核代源码以外的地方复制一棵目录树,当中藏有某个模块的源代码及编译了的二进制程序。DKMS 可以用来创建、安装及卸装模块。DKMS 需要在系统上找到模块的源代码。DKMS 库亦能代你创建及安装模块到你系统上的任何内核里。

在这里我们会采用与上面相同的样例来创建及安装 cifs 这个模块。在下面整个部份,你都须要有 root 的权限。

1. 安装所有与这个模块的目标内核版本相乎的 kernel-devel 组件。

2. 安装 RPMForge 软件库内的 dkms 组件。

3. 创建一个 /usr/src/-/ 的目录

[root@host]# mkdir /usr/src/cifs-1.45fixed/

4. 将模块的代源码复制到这个目录。

[root@host]# cd ~/rpmbuild/BUILD/kernel-2.6.18/linux-2.6.18-i686/fs/cifs

[root@host cifs]# cp -a * /usr/src/cifs-1.45fixed/

5. 在 /usr/src/-/ 这个目录内置立 dkms.conf 档

[root@host cifs]# cd /usr/src/cifs-1.45fixed

[root@host cifs-1.45fixed]# vi dkms.conf

dkms.conf 档须要包含以下内容:

PACKAGE_NAME="cifs"

PACKAGE_VERSION="1.45fixed"

BUILT_MODULE_NAME[0]="cifs"

DEST_MODULE_LOCATION[0]="/kernel/fs/cifs/"

AUTOINSTALL="yes"

注:DEST_MODULE_LOCATION[0] 这一行将会在安装模块时被忽视,因为它一定会是 /lib/modules//extra/ 这个目录。然而,这个参数却指定当模块被卸装时,旧有被存储的模块(假若有的话)应该被撤消到哪个位置。

6. 将 / 加进 DKMS 的目录树。

[root@host cifs-1.45fixed]# dkms add -m cifs -v 1.45fixed

7. 在 DKMS 的控制下编译模块。

[root@host cifs-1.45fixed]# dkms build -m cifs -v 1.45fixed

8. 在 DKMS 的控制下安装模块。

[root@host cifs-1.45fixed]# dkms install -m cifs -v 1.45fixed

其它值得注意的 DKMS 动作包括 uninstall、remove、status 及 mkrpm。它们分别会将模块从内核删除,将 / 从 DKMS 目录树删除,显示 DKMS 的现时状况,及在 /var/lib/dkms///rpm/ 这个目录内置立一个 rpm 文件。

请亦参阅:

3. 创建一个内核模块的 rpm 组件(kmod)

你亦可以为内核模块创建 rpm 文件。这个内核模块的组件(kmod)便可以像其它组件一样通过 rpm 指令来安装。然而,包装内核模块的 rpm 与标准的包装过程有不同的处理方法。以下的样例提供了基本的内核模块 rpm 包装技巧。

再一次,我们会以 cifs 模块作为样例来创建一套 kmod-cifs 的 rpm 档。

1. 安装所有对应你现有内核的 kernel-devel 组件。

2. 正如上面的第 1 部份,已修正的代源码位於 ~/rpmbuild/BUILD/kernel-2.6.18/linux-2.6.18.i686/fs/cifs/ 这个目录内。请复制这个目录。

[user@host]$ mkdir ~/cifs-1.45/

[user@host]$ cd ~/rpmbuild/BUILD/kernel-2.6.18/linux-2.6.18.i686/fs/cifs

[user@host]$ cp -a * ~/cifs-1.45/

3. 创建一个藏有来源目录的 bzip2 压缩档。

[user@host]$ cd

[user@host]$ tar -jcf cifs-1.45.tar.bz2 cifs-1.45/

4. 将压缩档复制到 SOURCES 目录内。

[user@host]$ cp cifs-1.45.tar.bz2 ~/rpmbuild/SOURCES/

5. 复制 kmodtool 这个脚本(它是 redhat-rpm-config 组件的一部份)到 SOURCES 目录内。

[user@host]$ cd ~/rpmbuild/SOURCES/

[user@host SOURCES]$ cp /usr/lib/rpm/redhat/kmodtool kmodtool-cifs-el5.sh

6. 编辑你所复制的 kmodtool-cifs-el5.sh 文件,并确定当中提及 kmod-common 的行都被改为注释。然后加入一行在 %files 内会扩充成指向 kmod-cifs.conf 档的指令。

[user@host SOURCES]$ vi kmodtool-cifs-el5.sh

由第 105 行起 ——#

# RHEL5 - Remove common package requirement on general kmod packages.

# Requires: ${kmod_name}-kmod-common >= %{?epoch:%{epoch}:}%{version}

#

由第 168 行起 ——echo "%files -n kmod-${kmod_name}${dashvariant}"

if [ "" == "$kmp_override_filelist" ];

then

echo "%defattr(644,root,root,755)"

echo "/lib/modules/${verrel}${variant}/"

echo "%config /etc/depmod.d/kmod-${kmod_name}.conf"

#BZ252188 - I've commented this out for the moment since RHEL5 doesn't

# really support external firmware e.g. at install time. If

# you really want it, use an override filelist solution.

#echo "/lib/firmware/"

else

cat "$kmp_override_filelist"

fi

7. 在 SPECS 目录内置立 cifs-kmod.spec 档。

[user@host SOURCES]$ cd ~/rpmbuild/SPECS/

[user@host SPECS]$ vi cifs-kmod.spec

# Define the kmod package name here.

%define kmod_name cifs

# If kversion isn't defined on the rpmbuild line, define it here.

%{!?kversion: %define kversion 2.6.18-8.el5}

Name: %{kmod_name}-kmod

Version: 1.45

Release: 1%{?dist}

Group: System Environment/Kernel

License: GPLv2

Summary: %{kmod_name} kernel module(s)

URL: http://www.centos.org/

BuildRequires: redhat-rpm-config

BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-build-%(%{__id_u} -n)

ExclusiveArch: i686 x86_64

# Sources.

Source0: %{kmod_name}-%{version}.tar.bz2

Source10: kmodtool-%{kmod_name}-el5.sh

# Define the variants for each architecture.

%define basevar ""

%ifarch i686

%define paevar PAE

%endif

%ifarch i686 x86_64

%define xenvar xen

%endif

# If kvariants isn't defined on the rpmbuild line, build all variants for this architecture.

%{!?kvariants: %define kvariants %{?basevar} %{?xenvar} %{?paevar}}

# Magic hidden here.

%{expand:%(sh %{SOURCE10} rpmtemplate_kmp %{kmod_name} %{kversion} %{kvariants})}

# Disable the building of the debug package(s).

%define debug_package %{nil}

# Define the filter.

%define __find_requires sh %{_builddir}/%{buildsubdir}/filter-requires.sh

%description

This package provides the CentOS-5 bug-fixed %{kmod_name} kernel module (bug #1776).

It is built to depend upon the specific ABI provided by a range of releases

of the same variant of the Linux kernel and not on any one specific build.

%prep

%setup -q -c -T -a 0

for kvariant in %{kvariants} ; do

%{__cp} -a %{kmod_name}-%{version} _kmod_build_$kvariant

done

echo "/usr/lib/rpm/redhat/find-requires | %{__sed} -e '/^ksym.*/d'" > filter-requires.sh

echo "override %{kmod_name} * weak-updates/%{kmod_name}" > kmod-%{kmod_name}.conf

%build

for kvariant in %{kvariants} ; do

KSRC=%{_usrsrc}/kernels/%{kversion}${kvariant:+-$kvariant}-%{_target_cpu}

%{__make} -C "${KSRC}" %{?_smp_mflags} modules M=$PWD/_kmod_build_$kvariant

done

%install

%{__rm} -rf %{buildroot}

export INSTALL_MOD_PATH=%{buildroot}

export INSTALL_MOD_DIR=extra/%{kmod_name}

for kvariant in %{kvariants} ; do

KSRC=%{_usrsrc}/kernels/%{kversion}${kvariant:+-$kvariant}-%{_target_cpu}

%{__make} -C "${KSRC}" modules_install M=$PWD/_kmod_build_$kvariant

done

%{__install} -d %{buildroot}%{_sysconfdir}/depmod.d/

%{__install} kmod-%{kmod_name}.conf %{buildroot}%{_sysconfdir}/depmod.d/

# Set the module(s) to be executable, so that they will be stripped when packaged.

find %{buildroot} -type f -name \*.ko -exec %{__chmod} u+x \{\} \;

%clean

%{__rm} -rf %{buildroot}

%changelog

* Wed Jan 05 2011 Alan Bartlett - 1.45

- Revised this specification file.

* Fri May 18 2007 Akemi Yagi - 1.45

- Initial el5 build of the kmod package.

8. 创建组件。

[user@host SPECS]$ rpmbuild -bb --target=`uname -m` cifs-kmod.spec 2> build-err.log | tee build-out.log

你果你不想创建一个对应使用中的内核的 kmod 组件,你可以在命令行上指定内核的版本。例如:

[user@host SPECS]$ rpmbuild -bb --target=`uname -m` --define 'kversion 2.6.18-274.el5' cifs-kmod.spec 2> build-err.log | tee build-out.log

这样做便会为 2.6.18-274.el5 内核创建 kmod 组件。

利用同一个方法,你可以选择创建哪一个内核类型的 kmod 组件。例如:

[user@host SPECS]$ rpmbuild -bb --target=`uname -m` --define 'kvariants ""' cifs-kmod.spec 2> build-err.log | tee build-out.log

这样做便只会创建基本内核的 kmod 组件。

当编译完成后,~/rpmbuild/RPMS/`uname -m`/ 目录内将会藏有一套 kmod-cifs 的 rpm 档。

请亦参阅:

Translation of revision 115

Linux如何创建一个内核模块,创建你自己的内核模块相关推荐

  1. 数据库SQL语句 创建一个数据库,创建表,并添加约束

    USE master Go 进入master模式 创建数据库 USE master GOCREATE DATABASE TestData ON PRIMARY (Name = 'TestData',F ...

  2. jenkins pipeline之如何创建一个流水线

    一.为什么使用pipeline 我之前实现了一套完整的升级自动化构建流程,每个步骤分别对应一个Job(为了各Job之间能够方便的自由组合).现在想根据不同的测试场景,将多个Job串联起来,准备用pip ...

  3. 【C语言】利用for循环来创建一个金字塔

    先上代码 char ch = 0;ch = getchar();int i = 0;for (i = 0;i < 6;i++){int j = 0;for (j = 0;j < 5 - i ...

  4. Vue.js 学习笔记十二:Vue CLI 之创建一个项目

    目录 创建一个项目 创建一个项目 运行以下命令来创建一个新项目: vue create vuecli-demo 你会被提示选取一个 preset.你可以选默认的包含了基本的 Babel + ESLin ...

  5. 利用GLFW创建一个窗口

    利用GLFW创建一个窗口 创建窗口前的准备工作 GLFW初始化 设置界面属性 界面相关属性 缓冲区相关属性 上下文相关属性 各个属性的默认值和取值范围 创建窗口 显示窗口 完整代码 窗口事件交互 完整 ...

  6. linux添加以太网头部函数,linux – 在内核模块中创建一个以太网数据包并发送它...

    我需要创建一个以太网数据包并在我的内核模块中发送它.有人可以帮我这样做吗? 我想我需要使用dev_alloc_skb创建一个skb,然后我需要编写mac_ethernet,插入数据并使用dev_que ...

  7. linux创建一个交换分区,如何创建linux交换分区

    匿名用户 1级 2017-03-26 回答 1.mkswap 把一个分区格式化成为swap交换区: [root@localhost]# mkswap /dev/sda6 注:创建此分区为swap 交换 ...

  8. 【 Linux 】创建一个文件夹并在此文件下创建一个c源文件

    我们需要单独创建一个文件夹来存放自己的文件,例如存放使用vim编写的c源文件,或者一个工程内的所有东西. 我们以在Linux下的home文件夹下创建一个vim文件夹,然后在此文件夹下创建一个c源文件, ...

  9. 【LINUX】——linux如何使用Python创建一个web服务

    问:linux如何使用Python创建一个web服务? 答:一句话,Python! 一句代码: /usr/local/bin/python -m SimpleHTTPServer 8686 > ...

最新文章

  1. Python中的高阶变量
  2. 解决idea 中web项目无法正常显示的问题
  3. 分享Silverlight/WPF/Windows Phone一周学习导读(12月13日-12月19日)
  4. springboot开始
  5. matplotlib -work4
  6. Python Tricks(一)—— np.where 与最大最小截断
  7. redis hash field过期时间_Redis系列-Redis数据类型
  8. android iso打开软件,安卓手机如何打开.iso文件?
  9. 辣椒app软件测试,testflight辣椒视频
  10. 南邮 | 算法分析与设计实验三:回溯法
  11. angular 脏值检测基础流程
  12. iPhone13再现粉屏问题,同时出现闪退/卡顿/重启?
  13. 打开win10电脑的蓝牙
  14. 波束成形算法之波束宽度
  15. CSP2020考试感悟
  16. Matlab应变片仿真,应变片传感器的应用.ppt
  17. 清华2020计算机系张晨,本科三篇顶会一作、超算竞赛冠军,2020清华本科特奖结果出炉...
  18. 使用python将数据导出到表格中
  19. 北京计算机大专录取线,北京多少分能上大专,北京大专院校最低分数线
  20. 如何把图片扫描成word文档?

热门文章

  1. mybatis 二级缓存失效_给我五分钟,带你彻底掌握MyBatis的缓存工作原理
  2. java视频编辑怎么实现_OpenGL 实现视频编辑中的转场效果
  3. 常用针织实用技术名词
  4. 视觉平台搭建——光源选型介绍
  5. 2017.7.8 MS SQL Server and BI workshop
  6. 8、周期性任务、find、break和continue 学习笔记
  7. Coding List
  8. Android 应用启动速度优化
  9. Mysql物化视图应用
  10. 调用百度API实现人像动漫化(C++)