前言
我们在参与某些开源项目的过程当中,经常会遇到漏洞之类的问题,需要我们打补丁解决。尤其是 Linux
源码,源码代码量较多,在修改完内核并发布新内核的时候,基本采用补丁的方式进行发布,而不是将整个内核打包发布
我们使用补丁发布有很多好处
-
补丁体积很小,方便成员获取 -
补丁方便保存,本地可以保存多个版本内核 -
使用方便快捷,直接将补丁放到源码对应目录,然后执行相应命令即可
注:博主本人并没有给 linux 提过补丁,本文仅为学习提交补丁的记录,希望对大家有帮助,勿喷
如果了解这方面的佬,也欢迎评论区交流
diff / patch
生成补丁
我们以经典的 linux 0.11
版本源码为例,假如说我们当前目录下有两个源码文件夹,未经修改的源码文件夹为 linux-0.11
,以及修改完毕的补丁源码 linux-0.11-new
注:linux 0.11 是早期的 Linux 内核版本,发布于 1991 年,相当古老,仅供学习使用,但是工程上已经没有使用价值,最新版内核可以到下方的源码库寻找
linux 源码库:torvalds/linux: Linux kernel source tree (github.com)[1]
linux 0.11 源码库:karottc/linux-0.11: the source code of linux-0.11 for study linux kernel (github.com)[2]

我们可以拉取两份 linux 0.11
源码,其中一份保持原样,另外一份做出相应修改,并且重命名文件夹为 linux-0.11-new
注:我这里拉取源码时使用参数
--exclude=.git
排除 .git 文件夹,防止后续打补丁干扰。如果 git 版本过低,没有该功能,可以先克隆,再删除文件夹
git clone --exclude=.git git@github.com:karottc/linux-0.11.git
或者是
git clone git@github.com:karottc/linux-0.11.git
git clone git@github.com:karottc/linux-0.11.git ./linux-0.11-new
rm -rf linux-0.11/.git
rm -rf linux-0.11-new/.git
然后使用下面的 diff
命令,输出原始源码和修改之后的源码的文件区别,并重定向输出到 linux.patch
补丁文件中
sudo diff -uprN linux-0.11/ linux-0.11-new/ > linux.patch
注:
.patch
为约定俗称的补丁文件扩展名,尽量遵守规范,除此之外名字可以随便起
参数解释:
-
-u
: 生成统一格式的差异输出,通常用于生成补丁文件。 -
-p
: 在差异输出中显示更多的上下文信息,以方便阅读。 -
-r
: 对目录进行递归比较,而不仅仅比较单个文件。 -
-N
: 当比较的文件是空文件时,也显示差异信息。
使用补丁
我们可以直接在当前目录下执行如下打补丁命令
patch -p0 < linux.patch
注:-p 参数代表忽略哪级文件路径,0 标识去掉全路径,1 标识去掉第一层路径
或者是进入未经修改的 linux 源码根目录下执行如下打补丁命令
patch -p1 < ../linux.patch
注:这里的重定向符号大家注意不要写反,我开始就写反了,然后执行命令后系统就会卡死,不会报错,但是也不会终止
我这里简单作为示例,仅修改了 README.md
文件
举例解释 -p
参数,比如说 patch 文件片段如下
--- old/modules/pcitable Mon Sep 27 11:03:56 1999
+++ new/modules/pcitable Tue Dec 19 20:05:41 2000
如果使用参数 -p0,那就表示从当前目录找一个叫做 old 的文件夹,再在它下面寻找 modules/pcitable 文件来执行 patch 操作
而如果使用参数 -p1,那就表示忽略第一层目录(即不管 old),从当前目录寻找 modules 的文件夹,再在它下面找 pcitable
最后我们可能出现冲突,通常是因为原始文件已经被修改过,这时我们只需要手动解决这些冲突,然后重新执行补丁即可
注:但是建议最好不要手动修改原版代码,不然后续改比较麻烦
撤销补丁
我们可以执行如下命令撤销补丁
patch -Rp0 < linux.patch
或者是进入未修改源码根目录,然后执行如下命令
patch -Rp1 < ../linux.patch
单文件补丁
上面是对于整个文件夹打补丁,下面将会讲解如何对单个文件打补丁
使用单独文件依次打补丁,可以更加有效的验证补丁正确性,方便后续进行功能测试
比如说我们当前目录有原文件 a.c
,修改之后的文件 b.c
,我们可以使用如下命令生成补丁文件
diff -u a.c b.c > test.patch
# 使用补丁
patch a.c < test.patch
# 撤销补丁
patch -RE < test.patch
quilt

简介
当我们在开发自己项目的过程中,可能会只制作大量补丁,管理这些数量庞大的补丁会非常耗费时间
所以 linux 内核开发者 [Andrew Morton](http://en.wikipedia.org/wiki/Andrew_Morton_(computer_programmer “Andrew Morton”)) 开发出 [quilt](http://en.wikipedia.org/wiki/Quilt_(software “quilt”)) 补丁管理工具,以帮助我们更好的管理补丁
官方相关文档
-
quilt-doc.dvi (shakthimaan.com)[3] -
Linux Kernel Configuration – Managing Your Patches With quilt (linuxtopia.org)[4] -
quilt man | Linux Command Library[5]
本章将会简单讲解 quilt 使用流程,更多详细信息可以查看上方官方文档
使用
只要我们在源代码树里使用了 quilt 命令,quilt 就会在源代码树的根目录建立两个特殊目录:patches 和.pc
patches 文件夹下为管理的补丁文件
.pc 文件夹下保存着其内部工作状态
可以使用如下命令安装
sudo apt-get install quilt
新建补丁文件
quilt new xxx.patch
补丁文件关联修改文件,关联后即可对文件进行修改,如要关联多个文件,重复添加然后修改即可
quilt add file
查看补丁是否正确
quilt diff
保存补丁,之后补丁文件会保存在 patches
quilt refresh
git

git 提供了两种补丁方案
-
git diff 生成的 .diff 文件 -
git format-patch 生成的 .patch 文件
git diff 生成的文件不含有 commit 信息,可以指定文件生成 diff,也可以指定单个 commit, 多个 commit 生成
git format-patch 生成的 .patch 文件 含有 commmit 信息,一个 commit 对应一个 patch 文件
注:本章将会简单讲解 git 补丁流程,如果您需要更详细的文档说明,博主会将在每小章开头附上 git 官网文档链接,供您参考
git diff
官方文档:Git – git-diff Documentation (git-scm.com)[6]
制作补丁命令如下
# 单独文件补丁
git diff Test.java > test.patch
# 所有文件补丁
git diff > test.patch
指定 commit id
制作补丁
git diff [commit sha1 id] [commit sha1 id]> test.patch
git format-patch
官方文档:Git – git-format-patch Documentation (git-scm.com)[7]
制作当前分支超前于指定分支提交的补丁
注:命令示例即为制作超前于 master 分支的补丁
git format-patch -M master
制作某次提交以后的补丁
git format-patch [commit id]
某两次提交之间补丁
git format-patch [commit sha1 id]..[commit sha1 id]
应用补丁
检查补丁文件
git apply --stat xxx.patch
检查能否应用成功
git apply --check xxx.patch
使用补丁
git am --signoff < xxx.patch
但是可能会出现我们上面提到的冲突,导致使用补丁失败,出现如下错误
$ git am PATCH
Applying: PACTH DESCRIPTION
error: patch failed: file.c:137
error: file.c: patch does not apply
error: patch failed: Makefile:24
error: libavfilter/Makefile: patch does not apply
Patch failed at 0001 PATCH DESCRIPTION
When you have resolved this problem run "git am --resolved".
If you would prefer to skip this patch, instead run "git am --skip".
To restore the original branch and stop patching run "git am --abort".
解决冲突
使用下面命令自动合并不冲突代码,保留冲突部分
执行后会生成后缀为 .rej
的文件,保存没有合并进去的部分的内容,可以参考这个进行冲突解决
解决完冲突后删除后缀为 .rej 的文件,然后提交代码到源码库即可
git apply --reject xxxx.patch
参考链接
-
linux内核生成补丁和打补丁的方法 – 知乎 (zhihu.com)[8] -
为文件/文件夹打补丁 – 简书 (jianshu.com)[9] -
Linux diff 命令 | 菜鸟教程 (runoob.com)[10] -
Linux patch命令 | 菜鸟教程 (runoob.com)[11] -
patch 命令打补丁,diff 命令制作补丁-腾讯云 (tencent.com)[12] -
Linux 下打 patch-腾讯云开发者社区-腾讯云 (tencent.com)[13] -
Quilt初探 – 使用 quilt 產生和管理 patch [14] -
quilt补丁制作 | Luobu (luobudiao.github.io)[15] -
提交第一份 Patch 到 Linux Kernel – HackMD[16]
参考资料
torvalds/linux: Linux kernel source tree (github.com): https://github.com/torvalds/linux
[2]
karottc/linux-0.11: the source code of linux-0.11 for study linux kernel (github.com): https://github.com/karottc/linux-0.11
[3]
quilt-doc.dvi (shakthimaan.com): http://www.shakthimaan.com/downloads/glv/quilt-tutorial/quilt-doc.pdf
[4]
Linux Kernel Configuration – Managing Your Patches With quilt (linuxtopia.org): https://www.linuxtopia.org/online_books/linux_kernel/kernel_configuration/apas02.html
[5]
quilt man | Linux Command Library: https://linuxcommandlibrary.com/man/quilt
[6]
Git – git-diff Documentation (git-scm.com): https://git-scm.com/docs/git-diff
[7]
Git – git-format-patch Documentation (git-scm.com): https://git-scm.com/docs/git-format-patch
[8]
linux内核生成补丁和打补丁的方法 – 知乎 (zhihu.com): https://zhuanlan.zhihu.com/p/573563830
[9]
为文件/文件夹打补丁 – 简书 (jianshu.com): https://www.jianshu.com/p/0f72615c2347
[10]
Linux diff 命令 | 菜鸟教程 (runoob.com): https://www.runoob.com/linux/linux-comm-diff.html
[11]
Linux patch命令 | 菜鸟教程 (runoob.com): https://www.runoob.com/linux/linux-comm-patch.html
[12]
patch 命令打补丁,diff 命令制作补丁-腾讯云 (tencent.com): https://cloud.tencent.com/developer/article/1828653
[13]
Linux 下打 patch-腾讯云开发者社区-腾讯云 (tencent.com): https://cloud.tencent.com/developer/article/1943930
[14]
Quilt初探 – 使用 quilt 產生和管理 patch : http://wen00072.github.io/blog/2014/06/08/study-on-the-quilt/
[15]
quilt补丁制作 | Luobu (luobudiao.github.io): https://luobudiao.github.io/2021/01/27/quilt-bu-ding-zhi-zuo/
[16]
提交第一份 Patch 到 Linux Kernel – HackMD: https://hackmd.io/@steven1lung/submitting-patches
原文始发于微信公众号(编程杂烩):手把手教你如何给『Linux』打补丁
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/226149.html