linux下补丁制作及打补丁实例【转】
转自:http://www.latelee.org/using-gnu-linux/diff-and-patch-on-linux.html
搞ARM有一段时日了,期间看了不少开发板的手册,手册的内容多数为教我们如何使用开发板,而不是教我们如何开发。手册中少不了显示linux下的命令,不过对这些命令有几点看法:
1、很多操作都使用了绝对路径,我想大约是为了表示这个路径的关系吧,不然的话,对于新手来说,来回几个cd,就搞不清楚在哪个目录了,这点表示赞同。不过对于我来说,实在不会如此操作;
2、统一使用root用户,因为许多人都使用虚拟机的linux作主机系统,所以想用哪个用户都无所谓,然而在实际开发中却不是这样。因此这点我就不赞同了。linux的权限意识非常强的,如果试过多人工作于同一台服务器的话,就能体会到了。不过话又说回来,对于新手来说,用root可能十分便利,因为不会存在不能访问哪个文件、哪个设备的问题,畅通无阻。最近,boss用root用户在rhel中编译qtopia,出现了使用g++错误的问题:
g++: error trying to exec ‘cc1plus': execvp: No such file or directory
我们想了很久,得到一个非权威的解释:rhel不允许root来编译qtopia,用普通用户无此问题。
本文背景:
1、练习制作补丁和打补丁;
2、以以前的程序代码lib-test为例,演示制作补丁和打补丁过程。
lib-test示例见http://www.latelee.org/programming-under-linux/multi-makefile-for-app.html。
为了不造成误解,引起误导,本文的假设如下:
1、原工程目录为lib-test-org,修改后的工程目录为lib-test-new,两个目录均在cst目录下:
[latelee@FightNow cst]$ pwd
/home/latelee/cst
2、本文提到的“原始文件”及“原始工程目录”等等,是指未经修改过的工程目录、源代码包等,比如在网上下载qtopia-2.2.0的原始代码包、U-Boot原始代码包、Linux内核原始代码包。
3、由于这里只是测试,因此建立了lib-test-new,并在这个目录下修改文件。
4、实际应用中,一般会提供原始代码包及补丁文件。
示例
修改地方如下:
1、在三个头文件中添加如下类似信息:
/**
* @file foo.h
* @author Late Lee <http://www.latelee.org>
* @date Thu Apr 7 2011
*
* @brief none
*
*
*/
2、修改main.c,将头文件包括的双引号(“”)改为尖括号(<>),此外添加一些版权信息及编译命令等等。
3、修改主目录下的Makefile,主要添加:
%.o: %.c
$(CC) $(CFLAGS) -c $^ -I ./configs
即由-I选项指定头文件位置(因此可以在代码中使用尖括号)。
4、其它修改若干。
注:上述修改仅为示例,以实际修改为准。
示例过程:
1、制作补丁
在cst目录下(即在两个工程目录的同一目录下)使用diff命令制作补丁:
[latelee@FightNow cst]$ diff -urN lib-test-org/ lib-test-new/ > lib-test.patch
(注:-r表示递归搜索子目录,更多选项,请man diff。)
这样就在该目录下生成了一个叫lib-test.patch的补丁文件。
这里分析一下patch文件,以第一块为例:
diff -urN lib-test-org/configs/backtrace.h lib-test-new/configs/backtrace.h
— lib-test-org/configs/backtrace.h 2011-04-07 09:04:06.000000000 +0800
+++ lib-test-new/configs/backtrace.h 2011-04-07 08:22:55.000000000 +0800
@@ -1,3 +1,13 @@
+/**
+ * @file backtrace.h
+ * @author Late Lee <http://www.latelee.org>
+ * @date Thu Apr 7 2011
+ *
+ * @brief none
+ *
+ *
+ */
+
#ifndef _BACKTRACE_H
#define _BACKTRACE_H
这里分三部分来分析。
第一部分即第1行,文中以粗体字体标示,是制作补丁所使用的命令,后面的是两个工程目录的文件。
第二部分为第2、3行,“—”表示原始文件,“+++”表示修改过的文件。
剩下的是第三部分,“@@ -1,3 +1,13 @@”中的“-1,3”表示原始文件的第1行到第3行,“+1,13”表示修改过的文件的第1行到第13行。两者之差的内容即为修改的内容,其中减号(“-”)表示删除,加号(“+”)表示添加。
下面看一下backtrace.h文件。
backtrace.h完整的原始代码如下(注意该文件的第1行到第3行内容):
1 #ifndef _BACKTRACE_H
2 #define _BACKTRACE_H
3
4 /* Even complicated programs rather seldom have a nesting
5 * level of more than, say, 50 and with 200 possible entries
6 * probably all programs should be covered. — from glibc manual
7 */
8 /* here, we let it be 30 */
9 #define NEST 30
10 void print_trace(int sig);
11 void print_trace_fd(int sig);
12 void print_trace_file(int sig);
13
14 #endif /* _BACKTRACE_H */
修改后的代码如下(注意该文件的第1行到第13行内容):
1 /**
2 * @file backtrace.h
3 * @author Late Lee
4 * @date Thu Apr 7 2011
5 *
6 * @brief none
7 *
8 *
9 */
10
11 #ifndef _BACKTRACE_H
12 #define _BACKTRACE_H
13
14 /* Even complicated programs rather seldom have a nesting
15 * level of more than, say, 50 and with 200 possible entries
16 * probably all programs should be covered. — from glibc manual
17 */
18 /* here, we let it be 30 */
19 #define NEST 30
20 void print_trace(int sig);
21 void print_trace_fd(int sig);
22 void print_trace_file(int sig);
23
24 #endif /* _BACKTRACE_H */
应该看到了区别了吧?因此,所谓打补丁的大约意思可以这么说:
将原来的backtrace.h文件的第1行到第3行内容用“下面”的内容代替,行数从第1行到第13行。
其中的“下面”就是指那些“+”、“-”的内容了。
2、打补丁
进入lib-test-org目录下,使用patch命令打补丁:
[latelee@FightNow lib-test-org]$ patch -p1 < ../lib-test.patch
patching file configs/backtrace.h
patching file configs/bar.h
patching file configs/foo.h
patching file main.c
patching file Makefile
patching file nomain.c
一般地,都将patch文件放到与原始工程目录同一级目录中。
在man patch中有一句话:but usually just patch -pnum <patchfile
实际中常用的是-p1,网上说法是忽略第一个目录,看了一下man手册,准确说法是忽略第一个斜杠(“/”),比如/u/howard/src/blurfl/blurfl.c,如果是-p1的话,表示u/howard/src/blurfl/blurfl.c,用-p4的话,表示blurfl/blurfl.c,等等。
以上述patch片段的第一行为例:
diff -urN lib-test-org/configs/backtrace.h lib-test-new/configs/backtrace.h
如果用-p1,则表示configs/backtrace.h,这个是相对于工程目录路径,无论是在lib-test-org,还是lib-test-xxx中,也不管这个lib-test-org在哪个目录,路径依然不改变(当然,我们的前提是两者是同一事物,比如内核树、u-boot)。
上面的提示信息表示正在给哪个文件打补丁。打完补丁后,两个目录的内容就一致了。不信的话,可以再次用diff命令测试一下:
[latelee@FightNow cst]$ ls -l lib-test.patch
-rw-r–r– 1 latelee root 4137 04-07 09:05 lib-test.patch
[latelee@FightNow cst]$ diff -urN lib-test-org/ lib-test-new/ > lib-test-new.patch
[latelee@FightNow cst]$ ls -l lib-test-new.patch
-rw-r–r– 1 latelee root 0 04-07 09:07 lib-test-new.patch
可以看到,lib-test-new.patch大小为0,证明两个目录内容无差别。
本文语法高亮工具由迟思堂工作室(www.latelee.org)参考网上资料使用lex工具编写,代码添加行号由awk语句完成。语句如下:
$ awk ‘{printf(“%2d %2sn”, FNR, $0)}’ backtrace.h > test.h
行文过程中并未过度引用网上资料,因此存在非权威解释,术语使用不当等问题,然而却由实践而来,具有实际操作性。
本文固定链接: http://www.latelee.org/using-gnu-linux/diff-and-patch-on-linux.html
linux下补丁制作及打补丁实例【转】的更多相关文章
- Linux 下模拟制作块设备并挂载
Linux 下模拟制作块设备并挂载 作者:Grey 原文地址: 博客园:Linux 下模拟制作块设备并挂载 CSDN:Linux 下模拟制作块设备并挂载 环境 CentOS-7 下载地址:下载 Cen ...
- 在Linux下的找不同-打补丁
Q:为什么要找不同,为什么要打补丁? A: 在Linux应用中,作为DBA,我们知道MySQL跑在Linux系统之上,数据库最重要的追求就是性能,"稳"是重中之重,所以不能动不动就 ...
- linux下如何制作initrd镜像?
1. 准备文件 加入已经准备好了所有文件在/home/initrd-base目录下 2. 制作initrd镜像 cd /home/initrd-base/ ;find . | cpio --quiet ...
- Linux下进程的同步相互排斥实例——生产者消费者
linux下的同步和相互排斥 Linux sync_mutex 看的更舒服点的版本号= = https://github.com/Svtter/MyBlog/blob/master/Linux/pth ...
- Linux下vi替换字符命令操作实例
在Linux下的开发中,经常涉及到对文件里的字符进行处理,当中,对字符的替换操作也是非常的频繁. 本文以一个实际的文件为例,具体介绍了Linux下经常使用的vi替换字符命令,为相关的开发工作提供给了參 ...
- 【转】linux下mkisofs制作光盘映像cdrecord刻录光盘
1.制作光盘映像文件 $mkisofs -R -o /var/tmp/oracle.iso /home/oracle $mkisofs -o myiso.iso /home/oracle/data 补 ...
- Linux下双网卡绑定bond配置实例详解
本文源自:http://blog.itpub.net/31015730/viewspace-2150185/ 一.什么是bond? 网卡bond是通过多张网卡绑定为一个逻辑网卡,实现本地网卡冗余,带宽 ...
- Linux下的awk文本分析命令实例(二)
awk实现求和.平均.最大值和最小值的计算操作 准备和数据文件 [finance@master2-dev ~]$ cat data.txt 求和 [finance@master2-dev ~]$ ca ...
- Linux下的awk文本分析命令实例(一)
1. 入门实例1.1 显示最近登录的5个帐号: [root@localhost ~]# | awk '{print $1}' root root root root reboot 1.2 如果只是显 ...
随机推荐
- Jmeter—添加断言 判断接口响应数据是否符合预期
发出请求之后,通过添加断言可以判断响应数据是否是我们的预期结果. 1 在Jmeter中发送一个状态返回200的http请求(参数故意输入错误).结果肯定是不是返回200啦. 但结果树中http请求的图 ...
- 【刷题】BZOJ 3524 [Poi2014]Couriers
Description 给一个长度为n的序列a.1≤a[i]≤n. m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2.如果存在,输出这个数,否则输出0 ...
- java中poi进行execl导出
首先贴出最终导出的execl截图吧: 前台界面如下: 点击导出时,为其按钮的onclick事件添加exportDate()函数: function exportDate(){ var begin_Da ...
- 【NOI 2018】冒泡排序(组合数学)
题意大概是给定一个长度为$n$的排列$p$,求有多少长度为$n$的排列满足冒泡排序的交换次数为$\frac{1}{2} \sum\limits_{i = 1}^{n}|i - p_{i}|$. 可以发 ...
- 使用cmstp绕过应用程序白名单
默认情况下,AppLocker允许在文件夹中执行二进制文件,这是可以绕过它的主要原因.已经发现,这样的二进制文件可以很容易地用于绕过AppLocker和UAC.与Microsoft相关的二进制文件之一 ...
- Java虚拟机加载类
Java虚拟机是如何加载Java类的 Java虚拟机加载Java类总共需要经过3步:加载-----链接-----初始化.Java语言的类型可以分为两大类:基本类型和引用类型.基本类型是有Java虚拟机 ...
- bzoj3203【sdoi2013】保护出题人
题目描述 输入格式 第一行两个空格隔开的正整数n和d,分别表示关数和相邻僵尸间的距离.接下来n行每行两个空格隔开的正整数,第i + 1行为Ai和 Xi,分别表示相比上一关在僵尸队列排头增加血量为Ai ...
- JDBC详解(一)
一.相关概念介绍 1.1.数据库驱动 这里驱动的概念和平时听到的那种驱动的概念是一样的,比如平时购买的声卡,网卡直接插到计算机上面是不能用的,必须要安装相应的驱动程序之后才能够使用声卡和网卡,同样道理 ...
- 从 php 源码看 php 中的对象
从一个简单的例子说起: class Person { public $name; public $age; public function __construct($name, $age) { $th ...
- 经典面试题目C语言
题一,堆和栈的区别是? 题二,Volatile与Register的区别是? 题三,ARM里的大端格式和小端格式分别是什么意思? 题一答案: (1)存储内容不同 栈:在函数调用时,栈中存放的是函数中 ...