Linux内核补丁

在为内核源码修改功能或修复BUG后,可以采用补丁的方式发布源码,也可以采用整个内核源码打包的方式进行发布。由于内核补丁只包含了源码的修改部分,比起发布整套源码,代码量相对较小,方便保存和传播,因此一般采用补丁的方式发布源码。
内核补丁由一个或多个文件组成,文件中包含了内核源码的修改部分。每一个补丁文件的结构是固定的,下例是一个名为test.patch的内核补丁文件:

--- fs/proc/kmsg.c      2023-06-18 18:40:20.954611716 +0800
+++ fs/proc/kmsg.c.new  2023-06-18 18:42:30.066678914 +0800
@@ -22,7 +22,7 @@

 static int kmsg_open(struct inode * inode, struct file * file)
 {
-       return do_syslog(SYSLOG_ACTION_OPEN, NULL, 0, SYSLOG_FROM_PROC);
+       return 0;
 }

 static int kmsg_release(struct inode * inode, struct file * file)

补丁文件的前两行是补丁头;以@@开始的一段数据是补丁块,上述补丁从第三行开始到文件的结束是一个补丁块。一般一个补丁文件包含一个或多个补丁头,每个补丁头后面会有一个或多个补丁块。

1.补丁头

补丁头记录了原始文件和修改后文件的文件名和创建时间。以“—”开始的一行对应原始文件,test.patch的第一行fs/proc/kmsg.c是原始文件,意味着该补丁将修改内核源码目录下的fs/proc/kmsg.c文件。以“+++”开始的一行对应修改后的文件,test.patch的第二行fs/proc/kmsg.c.new是修改内核源码fs/proc/kmsg.c后形成的一个文件,这个文件在内核源码中不存在,由开发人员创建。该补丁的作用是将内核源码fs/proc/kmsg.c进行修改,修改后的文件和fs/proc/kmsg.c.new一致,具体修改的内容由补丁块指定。

2 补丁块

补丁块用来保存补丁头描述的文件的改动信息。以“@@”开始的一行是文件修改的行范围,test.patch的第三行“@@ -22,7 +22,7 @@”,其中的“-22,7”,表示改动的范围是从原始文件的第22行开始,总共7行,从源码 3 1第4行开始到文件的结尾,总共8行,减去开头是‘+’的一行,这7行数据表示原始文件的7行数据。而“+22,7”,表示改动的范围是修改后的文件的第22行开始,总共7行。从源码 3 1第4行开始到文件的结尾,不算是开头是‘-’的一行,这7行数据表示修改后文件的7行数据。
补丁块中,开头是‘-’的一行,是存在于原始文件中而在修改后文件中不存在的一行。开头是‘+’的一行,是原始文件中不存在而修改后文件中新增的行,其余的行在原始文件和修改后文件中均存在。如果一个补丁头后面有多个补丁块,表示给同一个文件的不同行打补丁。

3 创建补丁文件

要创建类似test.patch的补丁文件,需要完成如下操作:

  1. 确定要修改内核源码的哪一个或哪一些文件
    本例中,假设需要给fs/proc/kmsg.c文件打补丁,首先在Linux系统中进入内核源码目录,然后将fs/proc/kmsg.c文件复制一份,假设复制后的文件名为kmsg.c.new,该文件复制到内核源码的fs/proc目录下,如下图所示:
    在这里插入图片描述
  2. 根据需要修改内核源码
    假设想要修改fs/proc/kmsg.c文件的第25行,修改前的fs/proc/kmsg.c文件如下图所示(图中第一列表示行数):
    在这里插入图片描述
    kmsg.c的第25行是:return do_syslog(SYSLOG_ACTION_OPEN, NULL, 0, SYSLOG_FROM_PROC);假设需要将该行替换为两行代码,修改为先打印字符串“kmsg open”,然后返回0,则需要修改第1步复制后的kmsg.c.new文件,找到该文件的第25行,修改为如下图所示代码:
    在这里插入图片描述
  3. 制作补丁文件
    在Linux内核源码根目录下输入如下命令完成补丁文件制作:
    diff -urN 修改前的文件路径 修改后的文件路径 > 补丁文件名称
    本例中,可以输入命令:diff -urN fs/proc/kmsg.c fs/proc/kmsg.c.new > linux.patch。其中,fs/proc/kmsg.c是修改前的文件路径,fs/proc/kmsg.c.new是修改后的文件路径,而生成的内核补丁文件名是linux.patch。执行完该命令后,会生成一个名为linux.patch的补丁文件。命令的执行过程如下图所示:
    在这里插入图片描述
    上图首先使用diff命令创建了补丁文件linux.patch,然后通过cat命令打印出补丁文件的内容。在打印出的内容中,补丁头显示了修改之前和修改之后的文件路径和创建时间。补丁块中以‘-’开头的行表示存在于文件fs/proc/kmsg.c中而在文件fs/proc/kmsg.c.new中没有的内容,以‘+’开头的行表示存在于文件kmsg.c.new中而在文件fs/proc/kmsg.c中没有的内容。‘-’表示删除,‘+’表示增加。

4 安装补丁文件

上一节已经创建了一个补丁文件linux.patch,这个时候就可以通过patch命令给内核安装补丁文件(或称为打补丁),在内核源码的根目录下,执行如下命令安装补丁文件:
patch -p0 < linux.patch
执行结果如下图:
在这里插入图片描述
执行完patch命令后,再次打开内核源码目录下的fs/proc/kmsg.c文件,查看文件的第25行附近,可以发现,该文件已经和fs/proc/kmsg.c.new一致,表明已成功打上补丁。这个时候再次编译、安装内核(编译、安装步骤见配套电子书第1章),重新启动操作系统后,就以新的内核启动。
示例补丁文件linux.patch用于修改内核源码目录下的fs/proc/kmsg.c文件,kmsg.c文件的作用是在/proc目录下创建了一个名称为kmsg的文件,用户可以通过访问/proc/kmsg文件来查看内核的调试信息,感兴趣的读者可以尝试阅读该文件的源码。以新的内核启动后,每当访问/proc/kmsg文件时,执行dmesg -c,就会打印出字符串“kmsg open”。
例子中使用patch -p0命令给内核安装补丁文件,在安装补丁文件时,一般使用的命令为:
patch -pN < 补丁文件名 (N=0,1,2……)
上述命令中的N是忽略的路径层级个数,值可以是0、1、2、3……对于例子中的补丁文件linux.patch,如果在内核源码根目录下使用patch -p1 < linux.patch不能够成功安装补丁文件,会提示找不到文件。那么什么时候使用patch -p1或patch -p2?这是由补丁文件的第一行决定的。如果修改补丁文件linux.patch的第一行为如下内容:

--- test1/fs/proc/kmsg.c	2023-12-06 00:05:10.840145821 +0800

则可以在内核源码根目录下通过patch -p1 < linux.patch命令成功安装内核补丁,这里-p后的数字1表示忽略1层目录,即最前面的test1目录被忽略,即文件路径为fs/proc/kmsg.c,而执行该命令的目录是内核源码根目录,可以通过该路径找到kmsg.c文件。

5 撤销补丁文件

在已经安装内核补丁文件的情况下,撤销安装的补丁文件的命令为:
patch -R -pN < 补丁文件名 (N=0,1,2……)
和安装补丁文件的命令类似,只是patch命令多了一个参数-R,如果已经安装了示例补丁文件linux.patch,想要撤销该补丁文件,在内核源码根目录下执行如下命令:
patch -R -p0 < linux.patch
执行完该命令后,查看fs/proc/kmsg.c的第25行附近,可以看到又恢复了打补丁之前的状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值