1. patch文件结构
  2. 生成patch文件 --diff命令
  3. patch 使用 -- patch命令

    3.1 打path

    3.1撤销patch
  4. 使用举例

    4.1 基本命令使用

    4.2 内核打补丁

1. patch文件的结构

补丁头

补丁头是分别由---/+++开头的两行,用来表示要打补丁的文件。

一个补丁文件中的多个补丁

一个补丁文件中可能包含以---/+++开头的很多节,每一节用来打一个补丁。所以在一个补丁文件中可以包含好多个补丁。

块是补丁中要修改的地方。它通常由一部分不用修改的东西开始和结束。他们只是用来表示要修改的位置。

他们通常以@@开始,结束于另一个块的开始或者一个新 的补丁头。

块的缩进

块会缩进一列,而这一列是用来表示这一行是要增加还是要删除的。

块的第一列

+号表示这一行是要加上的。

-号表示这一行是要删除的。

没有加号也没有减号表示这里只是引用的而不需要修改。

diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index f5d7f4134524..26a2198c59b3 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -220,9 +220,6 @@ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables # Avoid indirect branches in kernel to deal with Spectre
ifdef CONFIG_RETPOLINE
-ifeq ($(RETPOLINE_CFLAGS),)
- $(error You are building kernel with non-retpoline compiler, please update your compiler.)
-endif
KBUILD_CFLAGS += $(RETPOLINE_CFLAGS)
endif

2. 生成patch文件 -- diff命令

diff命令比较两个文件的不同,然后记录下来,也就是所谓的diff补丁。

语法格式:

diff 【选项】 源文件(夹) 目的文件(夹)
diff -Naur 旧的目录 新的目录 > patch文件
diff -Naur 旧的文件 新的文件 > patch文件
给源文件(夹)打个补丁,使之变成目的文件(夹),术语也就是“升级”。

下面介绍三个最为常用选项:

-r 是一个递归选项,设置了这个选项,diff会将两个不同版本源代码目录中的所有对应文件全部都进行一次比较,包括子目录文件。

-N 选项确保补丁文件将正确地处理已经创建或删除文件的情况。

-u 选项以统一格式创建补丁文件,这种格式比缺省格式更紧凑些。

diff 对目录有一些限制,需要保持目录的一致性。

在创建patch的时候文件夹的层数应当是一样的,比如

代码:

--- old/modules/pcitableMon Sep 27 11:03:56 1999

+++ new/modules/pcitableTue Dec 19 20:05:41 2000

这样是可以的。

而代码:

--- old/try1/other/modules/pcitableMon Sep 27 11:03:56 1999

+++ new/modules/pcitableTue Dec 19 20:05:41 2000

这样做可能会有一些问题。

3.patch使用 -- patch命令

patch命令,利用diff制作的补丁来实现源文件(夹)和目的文件(夹)的转换。这样说就意味着你可以有源文件(夹)――>目的文件(夹),

也可以目的文件(夹)――>源文件(夹)。

对于一个patch文件,有两种常用使用方法:

cat new-patch | patch -p0
patch -p0 < new-patch
patch -R -p0 < new-patch
-p0 选项要从当前目录查找目的文件(夹)
-p1 选项要忽略掉第一层目录,从当前目录开始查找。
-E 选项说明如果发现了空文件,那么就删除它
-R 选项说明在补丁文件中的“新”文件和“旧”文件现在要调换过来了(实际上就是给新版本打补丁,让它变成老版本)

patch命令里面的层数(-p0?-p1?)

参数-p来指定从第几层开始比较。比如有一个patch文件的补丁头是这样的:

代码:

--- old/modules/pcitableMon Sep 27 11:03:56 1999

+++ new/modules/pcitableTue Dec 19 20:05:41 2000

如果使用参数-p0,就表示从当前目录,找一个叫作new的目录,在它下面找一个叫modules的目录,再在它下面找一个叫 pcitableMon的目录。

如果使用参数-p1,就表示忽略第一层,从当前目录找一个叫modules的目录,在它下面找一个叫modules的目录。这样会忽略掉补丁头提到的 new目录。

依此类推。

4. 使用例子

4.1 diff命令生成patch
#diff -aurN a/c a/b
diff -aurN a/c/c/a.c a/b/c/a.c
##diff命令会在补丁文件中记录这两个文件的首次创建时间
--- a/c/c/a.c 2019-02-24 10:59:30.351334765 +0800
+++ a/b/c/a.c 2019-02-24 10:52:19.139836763 +0800
@@ -10,5 +10,6 @@
#include<string.h>
#include "head.h"
int main(){
+ printf("hello world\r\n");
return 0;
}
diff -aurN a/c/c/head.h a/b/c/head.h
--- a/c/c/head.h 2019-02-24 10:59:30.355336764 +0800
+++ a/b/c/head.h 2019-02-24 10:52:32.942734763 +0800
@@ -7,5 +7,6 @@
************************************************************************/
#ifndef HEADER_H
#define HEADER_H
+extern void test();
#endif
4.2 patch使用

打patch

lin@lin:~/mytest$ patch -p0 < 123.patch
patching file a/c/c/a.c
patching file a/c/c/head.h

查看文件

lin@lin:~/mytest$ cat a/c/c/a.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "head.h"
int main(){
printf("hello world\r\n");
return 0;
}
lin@lin:~/mytest$ cat a/c/c/head.h
#ifndef HEADER_H
#define HEADER_H
extern void test();
#endif

撤销patch

lin@lin:~/mytest$ patch -R -p0 < 123.patch
patching file a/c/c/a.c
patching file a/c/c/head.h

查看文件

lin@lin:~/mytest$ cat a/c/c/head.h
#ifndef HEADER_H
#define HEADER_H
#endif lin@lin:~/mytest$ cat a/c/c/a.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "head.h"
int main(){
return 0;
}
4.3  内核打patch

内核不同版本介绍:

(一)Linux内核版本类型及patch简介:

1)基础版本

2.6.x为基础版本,patch位置:

http://www.kernel.org/pub/linux/kernel/v2.6/

2)修正版本

2.6.x.y为2.6.x基础版本之上派生出来的修正版本,称为-stable内核版本,patch位置:

http://www.kernel.org/pub/linux/kernel/v2.6/

3)发布版本

2.6.x.rcN(Release Candidate)内核,是在2.6.(x-1)之上派生出来的之后版本的侯选版本;此种内核

不稳定,发布的时候表示可以用来测试了;

例如对2.6.21加了新功能后派生出2.6.22-rc1,patch位置:

http://www.kernel.org/pub/linux/kernel/v2.6/testing/

4)git版本

git内核是每日内核树的快照,此类型比rc内核更不稳定,从基础版本或rc版本派生出来;

例如2.6.26-git1,2.6.26-rc9-git2,patch位置:

http://www.kernel.org/pub/linux/kernel/v2.6/snapshots/

5)mm版本

mm内核是专门针对内核的mm模块维护的版本,类似于git版本从基础版本或rc版本派生出来;

例如2.6.21-mm2, 2.6.21-rc2-mm1,patch位置:

http://www.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/

不同类型内核的patch名称在前面加上“patch-”(mm内核除外,直接用的版本号),例如:patch-2.6.21, patch-2.6.21.7, patch-2.6.26-git1, patch-2.6.26-rc9-git2, 2.6.21-mm2, 2.6.21-rc2-mm1

(二) 内核补丁类型

  1. 增量补丁

    同一类型的版本的补丁是用本版本对相邻的前一个版本制作的。

    例如,patch-2.6.21是对2.6.20做的补丁,patch-2.6.22是对2.6.21做的补丁,这就是增量补丁。

    2.6.x基础版本内核,采用的是增量补丁。

  2. 非增量补丁

    也增量补丁相反,是基本某一固定版本制作的补丁,而非相邻的前一个版本。

    例如,patch-2.6.21.3是2.6.21.3版本相对于2.6.21基础版本做的补丁,patch-2.6.21.4是2.6.21.4版本相对于2.6.21基础版本做的补丁,

    也就是说2.6.21.4与2.6.21.3之前没有补丁可用。

    rc内核,git内核和mm内核都是非增量补丁,都是相对于当前基础版本或rc版本制作出来的补丁。

另外,对于rc内核,git内核,相应的patch目录下面有inc目录中,包含有增量补丁。

(三)内核版本升级

  1. 同版本升级内核版本

    现有基础内核版本2.6.21,想转成2.6.21.7内核stable版本,应该怎么办?

    (a) 去内核源码目录下载patch-2.6.21.7;

    (b) Linux shell下面,cd到2.6.21内核源文件根目录(linux-2.6.21),

    将patch-2.6.21.7也放在本目录(命令执行的当前止录),执行patch命令:
patch -p1 < patch-2.6.21.7
(p1的意思是忽略patch文件(即diff文件)内容中的第一个路径)

c) 打完补丁后,即变成了2.6.21.7的内核了,如果想回退至2.6.21基础版本,执行如下命令即可:

patch -R -p1 < patch-2.6.21.7
(-R的参数意思表示回退这个patch)

2.不同版本内核升级

现有基础内核版本2.6.21,想转成2.6.23.1内核stable版本,应该怎么办?

a) 同1中下载patch-2.6.22, patch-2.6.23, patch-2.6.23.1文件,并设置执行路径和环境;

b) 多次打补丁

patch -p1 < patch-2.6.22 变成了2.6.22
patch -p1 < patch-2.6.23 变成了2.6.23
patch -p1 < patch-2.6.23.1 变成了2.6.23.1

c) 回退操作

patch -R -p1 < patch-2.6.23.1 变成了2.6.23
patch -R -p1 < patch-2.6.23 变成了2.6.22
patch -R -p1 < patch-2.6.22 变成了2.6.21

3.不同内核版本升级

现有基础内核版本2.6.21-git2,想转成2.6.22-rc1-mm2内核stable版本,应该怎么办?

a) 同1中下载patch-2.6.21-git2, patch-2.6.22-rc1, 2.6.22-rc1-mm2文件,

并设置执行路径和环境;

b)打补丁

patch -R -p1 < patch-2.6.21-git2 变成了2.6.21
patch -p1 < patch-2.6.22-rc1 变成了2.6.22-rc1
patch -p1 < 2.6.22-rc1-mm2 变成了2.6.22-rc1-mm2

c) 回退操作

patch -R -p1 < 2.6.22-rc1-mm2 变成了2.6.22-rc1
patch -R -p1 < patch-2.6.22-rc1 变成了2.6.21
patch -p1 < patch-2.6.21-git2 变成了2.6.21-git2

内核诊断(二)-- patch 和diff的更多相关文章

  1. patch与diff的恩怨

    一.概述 diff和patch是一对相辅相成的工具,在数学上来说,diff类似于对两个集合的差运算,patch类似于对两个集合的和运算.diff比较两个文件或文件集合的差异,并记录下来,生成一个dif ...

  2. linux内核(二)内核移植(DM365-DM368开发攻略——linux-2.6.32的移植)

    一.介绍linux-2.6.32: Linux-2.6.32的网上介绍:增添了虚拟化内存 de-duplicacion.重写了 writeback 代码.改进了 Btrfs 文件系统.添加了 ATI ...

  3. linux内核第一二章总结

    1 Linux内核简介 1 Unix的历史 1.Unix演化版实现了任务管理.换页机制.TCP/IP等新的特性. 2.Unix的特点: Unix很简洁,仅仅提供几百个系统调用并且有一个非常明确的设计目 ...

  4. GIT打补丁 - patch和diff应用

    一. 准备工作: [root@guangzhou gittest]# git br * master [root@guangzhou gittest]# git chk -b patch-test1 ...

  5. 深入理解PHP内核(十二)函数-函数的定义、传参及返回值

    原文链接:http://www.orlion.ga/344/ 一.函数的定义 用户函数的定义从function 关键字开始,如下 function foo($var) {    echo $var; ...

  6. windbg内核诊断方式--转载

    一.WinDbg是什么?它能做什么? WinDbg是在windows平台下,强大的用户态和内核态调试工具.它能够通过dmp文件轻松的定位到问题根源,可用于分析蓝屏.程序崩溃(IE崩溃)原因,是我们日常 ...

  7. linux内核系列(二)内核数据结构之链表

    双向链表 传统链表与linu内核链表的区别图: 图一 图二 从上图中看出在传统链表中各种不同链表间没有通用性,因为各个数据域不同,而在linux内核中巧妙将链表结构内嵌到数据域结构中使得不同结构之间能 ...

  8. Linux内核 实践二

    实践二 内核模块编译 20135307 张嘉琪 一.实验原理 Linux模块是一些可以作为独立程序来编译的函数和数据类型的集合.之所以提供模块机制,是因为Linux本身是一个单内核.单内核由于所有内容 ...

  9. (笔记)Linux内核学习(二)之进程

    一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器. 内核调度的对象是线程而不是进程.对 ...

随机推荐

  1. (广搜)Dungeon Master -- poj -- 2251

    链接: http://poj.org/problem?id=2251 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2137 ...

  2. java并发编程实战:第四章----对象的组合

    一.设计线程安全的类 找出构造对象状态的所有变量(若变量为引用类型,还包括引用对象中的域) 约束状态变量的不变性条件 建立对象状态的并发访问管理策略(规定了如何维护线程安全性) 1.收集同步需求(找出 ...

  3. 解决部分版本kali升级后w3af无法运行的问题

    1,w3af简介 w3af是一个Web应用程序攻击和检查框架.该项目已超过130个插件,其中包括检查网站爬虫,SQL注入(SQL Injection),跨站(XSS),本地文件包含(LFI),远程文件 ...

  4. delphi Overload 和override的区别

    overload是重载;相同的函数名,参数不同,使用不同的函数体   override   是对父类声明的vitural或dynamic方法进行覆盖 overload的使用方法: [delphi] v ...

  5. ERROR 3009 (HY000): Column count of mysql.user is wrong. Expected 45, found 43. Created with MySQL 5

    ERROR 3009 (HY000): Column count of mysql.user is wrong. Expected 45, found 43. Created with MySQL 5 ...

  6. php数组转成php编程代码

    将php数组转成可以在php上面运行的编程代码,支持一维及多维数组 <?php //一维数组 $test1 = array(1,2,3); //二维数组 $test2[0] = array( ' ...

  7. 执行计划--WHERE条件的先后顺序对执行计划的影响

    在编写SQL时,会建议将选择性高(过滤数据多)的条件放到WHERE条件的前面,这是为了让查询优化器优先考虑这些条件,减少生成最优(或相对最优)的执行计划的时间,但最终的执行计划生成过滤顺序还是决定这些 ...

  8. 10-09 Linux的文件系统介绍以及各种设备的说明

    Linux的文件编程 linux文件管理系统分为3部分:与文件管理有关的软件,被管理的文件,实施文件管理需要的数据结构 用C语言建立,打开,关闭文件,向文件写入和读出数据等. Linux文件系统简介 ...

  9. 朋友,请待你的朋友——BUG好一点!

    程序猿嘛,难免会被BUG缠身,我相信,没有一个程序猿在被BUG缠身时是感觉轻松的,消灭BUG一定是你最大的愿望.本周,我们团队的项目进入调试阶段,各种BUG层出不穷,眼看下个周就要进行项目答辩会,所以 ...

  10. C#计算两个日期之间相差的天数

    说明:如:1900-01-01与1900-01-01之间算一天 private static int DateDiff(DateTime dateStart, DateTime dateEnd) { ...