2013-11-18 16:46:25 dongwuming 阅读数 2322

Linux系统补丁工具patch AND diff

一、工具概述:

diff制作补丁的工具

diff后面可以接两个文件名或两个目录名生成补丁

patch打补丁的工具

Patch用途:根据原文件和补丁文件生成目标文件

在数学上来说,diff类似于对两个集合的差运算,patch类似于对两个集合的和
运算。diff比较两个文件或文件集合的差异,并记录下来,生成一个diff文件,这也是我们常说的patch文件,即补丁文
件。 patch能将diff文件运用于原来的两个集合之一,从而得到另一个集合。
举个例子来说文件A和文件B,经过diff之后生成了补丁文件C,那么这个过程相当于 |A –B| = C ,那么patch的过程就
是B + C = A 或A - C = B(A + C = B或者B – C = A)。因此我们只要能得到A, B, C三个文件中的任何两个,就能

用diff和patch这对工具生成另外一个文件。这就是diff和patch的妙处。

补丁Patch是天才程序员、Perl的发明者Larry Wall发明的,它应高效地交流程序源代码之需求而生,随着以Linux为
代表的开发源代码运行的蓬勃发展,patch这个概念已经成为开放源代码发起者、贡献者和参与者的集体无意识的一部
分。patch只包含了对源代码修改的部分,这对于开放源代码社区的协同开发模式具有重要意义,意味的软件新版本的发布和
对软件的缺陷或改进可以以更小的文件发布,可以减少网络的传输量,方便软件维护者的管理工作。
patch文件有多种格式,不同平台上所支持的格式不尽相同,但最常见的是context格式和unified格式。context
格式被广泛使用,是 patch文件格式事实上的标准。该格式包含了差异部分及其邻近的若干行,邻近就是所谓的上下文,这
些行虽然没有变化,但它们出现在patch文件使得还原patch的程序具备更强的容错性。unified格式常见于GNU的patch实
现,以patch形式发布的linux内核就使用了该格式。
此外,还有其它比较少用的格式,如Normal格式,并排对比模式(side-by-side),ed script和RCS script模式
等。除了并排对比模式方便用户观察文件差异,其它格式大多数是为了兼容旧的patch格式。
二、工具的用法
1、 diff的用法
diff后面可以接两个文件名或两个目录名生成补丁,例如:
diff [option] oldfile newfile
如果是一个目录名加一个文件名,那么只作用在那么个目录下的同名文件。例如:
diff /usr/xu mine
把目录/usr/xu 中名为mine的文件与当前目录中的mine文件进行比较。
Diff常用的option选项有:
l -r 比较目录时,进行递归比较,用于产生整个代码树的patch
l -u 输出统一格式,diff有"传统"和"统一"两种格式,现在一般使用"统一"格式,比较而言,统一格式生成的文
件大,但包含了更多的信息,有利于阅读与定位
l -N 表示如果文件不存在则将其等价为空文件,这个用于产生有文件增加或删除的patch
l -a 补丁中包含二进制文件缺省时,diff向标准输出打印,所以一般都重定向到文件并以patch为后缀,也就是所
谓的补丁文件。关于二进制文件的说明:binary文件可以原始方式存入patch文件。diff可以生成(加-a选
项),patch也可以识别。如果觉得这样的patch文件太难看,解决方法之一是用uuencode处理该binary文件。
如果是两个目录的话,作用于该目录下的所有文件,不递归。如果我们希望递归执行,需要使用-r参数。不加任何参数
生成的diff文件格式是一种简单的格式,这种格式只标出了不一样的行数和内容。我们需要一种更详细的格式,可以标识出不
同之处的上下文环境,这样更有利于提高patch命令的识别能力。这个时候可以用-c开关。可以参考表1 diff的命令行选项
和参数。
diff的命令行选项和参数:
-a 将所有的文件看作文本,既使文件看起来像是二进制的也不例外,并且进行逐行比较【二进制文件必须加上这个参数】
-b 忽略块中空白数目的改变
-B 忽略插入或删除空行造成的改变
-c 产生"上下文"(context)格式的输出
-C[num] 产生"上下文"(context)格式的输出,显示块前后num行的内容,如果不指定num的值,则显示块前后3行的内容
-H 修改diff处理大文件的方式
-i 忽略大小写
-I regexp 忽略插入或删除与正则表达式regexp匹配的行
-l 将输出结果通过pr命令处理加上页码
-p 显示出现块的C函数
-q 只报告文件是否不同;不输出差别
-r 比较目录时,进行递归比较,用于产生整个代码树的patch
-s 报告两个文件相同(默认的行为是不报告相同的文件)
-t 输出时tab扩展为空白
-u 产生"统一"(unified)格式的输出
-U[num] 产生"统一"(unified)格式的输出,显示块前后num行的内容,如果不指定num的值,则显示块前后3行的内容
-v 打印diff的版本号
-w 逐行比较时忽略空白
-W cols 如果产生并排格式的输出(参见-y),让输出的每一列有cols个字符宽
-x pattern 当比较目录时,忽略匹配模式pattern的任何文件和子目录
-y 产生并排格式的输出

-N 表示如果文件不存在则将其等价为空文件,这个用于产生有文件增加或删除的patch

建议diff制作patch时参数至少要加上 -uNr  或者-uNra

举例:
void main() { printf("hello the world!\n"); }
void main() { printf("HELLO THE WORLD!\n"); }
使用以下命令生成补丁文件hello.patch:
$diff -u hello.c hello-new.c > hello.patch
diff可以对整个目录进行比较,生成补丁文件 例如有hello-1.0 和hello-1.1两个目录,其中hello-1.1为hello-
1.0的更新命令:
$diff -ruNa hello-1.0 hello-1.1 > hello-1.1.patch
2、 patch的用法
Patch用途:根据原文件和补丁文件生成目标文件。举例来说:
patch A C 就能得到B, 这一步叫做对A打上了B的补丁,这个补丁的名字叫做C。经过这一步,你的文件A就变成了文件
B。如果你打完补丁之后想恢复到A怎么办呢?
patch -R B C 就可以重新还原到A了。所以不用担心会失去A的问题。
其实patch在具体使用的时候是不用指定原文件的,因为补丁文件中都已经记载了原文件的路径和名称。patch足够聪明
可以认出原文件的路径和名称来。但是有时候会有点小问题:
比如一般对两个目录diff的时候可能已经包含了原目录的名字,但是我们打补丁的时候会进入到目录中再使用patch,这
个时候就需要你告诉 patch命令怎么处理补丁文件中的路径。可以利用-pn开关,告诉patch命令忽略的路径分隔符的个数。
举例如下:
A文件在 DIR_A下,修改后的B文件在DIR_B下,一般DIR_A和DIR_B在同一级目录DIR_P。我们为了对整个目录下的所
有文件一次性diff,我们一般会到DIR_A和DIR_B的父目录DIR_P下执行以下命令:
 
diff -rc DIR_A DIR_B > C
 
这个时候补丁文件C中会记录了原始文件的路径为 DIR_A/A
现在另一个用户得到了A文件和C文件,其中A文件所在的目录也是DIR_A。一般,他会比较喜欢在DIR_A目录下面进
行patch操作,它会执行
 
patch < C
 
但是这个时候patch分析C文件中的记录,认为原始文件是./DIR_A/A,但实际上是./A,此时patch会找不到原始文
件。为了避免这种情况我们可以使用-p1参数如下
 
patch -p1 < C
 
此时,patch会忽略掉第1个”/”之前的内容,认为原始文件是 ./A,这样就正确了。
patch附带有一个很好的帮助,其中罗列了很多选项,但是99%的时间只要两个选项就能满足我们的需要:
 
patch -p1 < [patchfile]
 
patch -R < [patchfile] (used to undo a patch)
 
-p1选项代表patchfile中文件名左边目录的层数,顶层目录在不同的机器上有所不同。要使用这个选项,就要把你的
patch放在要被打补丁的目录下,然后在这个目录中运行path -p1 < [patchfile]。
当然,被比较的文件或目录也可以从标准输入获得。如果用”-”表示file1或file2,则表示标准输入。
实例:
cat build.xml | diff -y -W 100 - build-1.10.xml
以每列100个字符的宽度并排对比输出build.xml和build-1.10.xml之间的差异到屏幕(标准输出)
diff -c web.xml web2.xml > web.xml.diff
产生web2.xml相对于web.xml的修改的上下文格式补丁文件到web.xml.diff中去
diff -crN src src_XFIRE > xfire-patch.diff
产生代码树src_XIRE相对于代码树src的上下文补丁文件到xfire-patch.diff中去,在src_XFIRE中新增的文件的内
容也会被包含在补丁中。
打补丁可以使用命令行工具patch。它的基本用法是:
patch -pnum < 补丁文件
打补丁时将工作目录切换到需要打补丁源代码顶层目录(注意:运行patch所在的目录应该与用diff生成补丁的时
候一致)。
3、 如何然后确定p后面的数字?
该数字表示需要去掉的补丁文件中目录的层数,该数字和补丁创建时候工作目录和代码目录的相对位置有关,一般补丁的
作者会在补丁文档中指明。如果没有指定,可以通过观察补丁文件中列出的文件完整路径和代码树中该文件所在相对路径得
出。
4、 如果patch失败
如果patch成功,缺省是不建备份文件的(注:FreeBSD下的patch工具缺省是保存备份),如果你需要,可以加上 b 开
关。这样把修改前的文件以“原文件名.orig”的名字做备份。如果你喜欢其它后缀名,也可以用“b 后缀”来指定。
  如果patch失败,patch会把成功的patch行给patch上,同时(无条件)生成备份文件和一个.rej文件,并生成原文件
的备份“原文件名.orig”,这里“-b”选项可以指定原文件的备份“原文件名.orig”的后缀名。.rej文件里是没有成功提交
的patch行,需要手工patch上去。这种情况在原码升级的时候有可能会发生。

2016-05-28 10:00:14 q751197694 阅读数 613

1, 打补丁之前需要准备好原始文件和补丁文件,例如给linux系统打补丁需要准备好linux-2.6.22.6.tar.bz2(原始文件)和linux-2.6.22.6_jz2440.patch(补丁文件),

2, 将这两个文件放到linux系统的一个文件夹下如/work/system目录下

3, 解压原文件  tar xjf linux-2.6.22.6.tar.bz2

4, 进入解压后的源文件文件夹   cd linux-2.6.22.6

5, 打补丁  patch -p1 < ../linux-2.6.22.6_jz2440.patch

6, 将打好补丁的文件压缩后再移动到Windows下 tar cjf linux-2.6.22.6_jz2440.tar.bz2

linux-2.6.22.6

7, 再进入源文件的解压目录 cdlinux-2.6.22.6

8, 配置 cp  config_ok .config

9, 编译创建uImage      make uImage

2017-05-19 22:12:32 yangguoyu8023 阅读数 432

制作补丁:

    新的uboot文件夹:mv u-boot-2012.04.01 u-boot-2012.04.01_100ask
    解压旧的uboot:tar xjf u-boot-2012.04.01.bz2
    制作补丁
    diff -urN linux-3.4.2 linux-3.4.2_alsa > linux-3.4.2_alsa.patch

打补丁:

    patch -p1 < ../linux-3.4.2_100ask.patch 
    cp config_ok .config
    make uImage
2017-04-10 17:08:27 pkusail 阅读数 1571

本文通过自身实践,介绍了在Linux下为内核打补丁的简单实例。



Linux下安装高版本补丁到低版本的步骤大体分为以下几步:

1、选取补丁

2、构建补丁

3、编译并处理编译错误

4、安装并验证补丁


环境

本文为Ubuntu 14.04版本,64位系统。

内核版本4.1.38。


内核安装补丁过程

1、选取补丁

补丁出处:

       理论上讲,各大开源网站(如githubgoogleandroid源码目录)的每次commit记录都可以作为补丁添加到我们的内核中,但是由于开源网站上分支众多、每个分支的代码更改次数也相当多,工作量巨大,所以我们需要针对性的寻找我们感兴趣并且比较重要的补丁。

       

选取原则:

一般来说,打补丁的困难程度取决于以下因素:

-补丁提交时间是否与我们的内核版本相近程度

-改动的文件数量

-改动的文件是否跨越了较多的模块

-涉及的模块改动是否频繁

-代码更改行数


本文选取补丁名称:“ipc/mqueue: Implement lockless pipelined wakeups”和“sched: Implement lockless wake-queues”

这两个补丁都是Linux4.2的重大补丁,涉及到了进程的唤醒切换,以提高系统的性能。


补丁“ipc/mqueue: Implement lockless pipelined wakeups”如下:


补丁“sched: Implement lockless wake-queues”如下:



2、构建补丁

选取好补丁之后,需要根据两个patch对补丁的代码进行分析,找出其他补丁中与之相关的代码。

手动挑选出相关代码之后,将相关代码复制到源码相关处,因为版本和分支不同的原因,多数情况下文件的行数是无

法对应的,所以需要手工查找对应代码,对Linux的源码进行更改,完成系统的升级。


根据补丁“ipc/mqueue: Implement lockless pipelined wakeups”完成对mqueue.c源代码的更改。



根据补丁“sched: Implement lockless wake-queues”完成对sched.h源代码的更改



根据补丁“sched: Implement lockless wake-queues”完成对core.c源代码的更改



3、编译并处理编译错误

生成新的内核源码后对新的内核源码进行编译


使用#make modules和#make modules_install,对模块进行编译,并安装到标准的模块目录中。


对新的内核源码进行编译后的安装


4、安装并验证补丁

完成新内核源码的编译后,安装好新的内核之后进入对补丁的验证阶段。


验证补丁确实生效之后开始进行性能测试:我们选用sysbench对cpu性能进行压力测试。

Sysbench简介:

     sysbench是一款开源的多线程性能测试工具,可以执行CPU/内存/线程/IO/数据库等方面的性能测试SysBench运行指定数目的线程并行处理请求。测试CPU性能时,是SysBench中最简单的测试模式。测试内容为素数计算-test=cpu,参数指定测试内容为cpu--cpu-max-primes=20000 run指定计算到的最大素数。每个线程并发执行直到有一个线程达到最大素数或超过指定的总时间


安装补丁之前,CPU性能测试结果如下:


安装补丁之后,CPU性能测试结果如下:


对比安装补丁前后的对比可以发现明显的性能提升。


linux 升级补丁

阅读数 561

没有更多推荐了,返回首页