2004年10月20日

Linux 操作系统从一开始就对串行口提供了很好的支持,本文就 Linux 下的串行口通讯编程进行简单的介绍。


Linux下串口编程入门


Linux 操作系统从一开始就对串行口提供了很好的支持,本文就 Linux 下的串行口通讯编程进行简单的介绍。

串口简介
串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用。常用的串口是 RS-232-C 接口(又称 EIA RS-232-C)它是在 1970 年由美国电子工业协会(EIA)联合贝尔系统、 调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。它的全名是”数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准”该标准规定采用一个 25 个脚的 DB25 连接器,对连接器的每个引脚的信号内容加以规定,还对各种信号的电平加以规定。传输距离在码元畸变小于 4% 的情况下,传输电缆长度应为 50 英尺。

Linux 操作系统从一开始就对串行口提供了很好的支持,本文就 Linux 下的串行口通讯编程进行简单的介绍,如果要非常深入了解,建议看看本文所参考的《Serial Programming Guide for POSIX Operating Systems》

计算机串口的引脚说明

<><>   
序号 信号名称 符号 流向 功能
2 发送数据 TXD DTE→DCE DTE发送串行数据
3 接收数据 RXD DTE←DCE DTE 接收串行数据
4 请求发送 RTS DTE→DCE DTE 请求 DCE 将线路切换到发送方式
5 允许发送 CTS DTE←DCE DCE 告诉 DTE 线路已接通可以发送数据
6 数据设备准备好 DSR DTE←DCE DCE 准备好
7 信号地         信号公共地
8 载波检测 DCD DTE←DCE 表示 DCE 接收到远程载波
20 数据终端准备好 DTR DTE→DCE DTE 准备好
22 振铃指示 RI DTE←DCE 表示 DCE 与线路接通,出现振铃

串口操作
串口操作需要的头文件

 #include  /*标准输入输出定义*/ #include  /*标准函数库定义*/ #include  /*Unix 标准函数定义*/ #include  #include  #include  /*文件控制定义*/ #include  /*PPSIX 终端控制定义*/ #include  /*错误号定义*/ 

打开串口
在 Linux 下串口文件是位于 /dev 下的

串口一 为 /dev/ttyS0

串口二 为 /dev/ttyS1

打开串口是通过使用标准的文件打开函数操作:

 int fd; /*以读写方式打开串口*/ fd = open( "/dev/ttyS0", O_RDWR); if (-1 == fd){ /* 不能打开串口一*/ perror(" 提示错误!"); } 

设置串口
最基本的设置串口包括波特率设置,效验位和停止位设置。

串口的设置主要是设置 struct termios 结构体的各成员值。

 struct termio { unsigned short c_iflag; /* 输入模式标志 */ unsigned short c_oflag; /* 输出模式标志 */ unsigned short c_cflag; /* 控制模式标志*/ unsigned short c_lflag; /* local mode flags */ unsigned char c_line; /* line discipline */ unsigned char c_cc[NCC]; /* control characters */ }; 

设置这个结构体很复杂,我这里就只说说常见的一些设置:

波特率设置

下面是修改波特率的代码:

 struct termios Opt; tcgetattr(fd, &Opt); cfsetispeed(&Opt,B19200); /*设置为19200Bps*/ cfsetospeed(&Opt,B19200); tcsetattr(fd,TCANOW,&Opt); 

设置波特率的例子函数:

 /** *@brief 设置串口通信速率 *@param fd 类型 int 打开串口的文件句柄 *@param speed 类型 int 串口速度 *@return void */ int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, }; int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, }; void set_speed(int fd, int speed){ int i; int status; struct termios Opt; tcgetattr(fd, &Opt); for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++) { if (speed == name_arr[i]) { tcflush(fd, TCIOFLUSH); cfsetispeed(&Opt, speed_arr[i]); cfsetospeed(&Opt, speed_arr[i]); status = tcsetattr(fd1, TCSANOW, &Opt); if (status != 0) { perror("tcsetattr fd1"); return; } tcflush(fd,TCIOFLUSH); } } } 

效验位和停止位的设置:

无效验 8位 Option.c_cflag &= ~PARENB;
Option.c_cflag &= ~CSTOPB;
Option.c_cflag &= ~CSIZE;
Option.c_cflag |= ~CS8;
奇效验(Odd) 7位 Option.c_cflag |= ~PARENB;
Option.c_cflag &= ~PARODD;
Option.c_cflag &= ~CSTOPB;
Option.c_cflag &= ~CSIZE;
Option.c_cflag |= ~CS7;
偶效验(Even) 7位 Option.c_cflag &= ~PARENB;
Option.c_cflag |= ~PARODD;
Option.c_cflag &= ~CSTOPB;
Option.c_cflag &= ~CSIZE;
Option.c_cflag |= ~CS7;
Space效验 7位 Option.c_cflag &= ~PARENB;
Option.c_cflag &= ~CSTOPB;
Option.c_cflag &= &~CSIZE;
Option.c_cflag |= CS8;

设置效验的函数:

 /** *@brief 设置串口数据位,停止位和效验位 *@param fd 类型 int 打开的串口文件句柄 *@param databits 类型 int 数据位 取值 为 7 或者8 *@param stopbits 类型 int 停止位 取值为 1 或者2 *@param parity 类型 int 效验类型 取值为N,E,O,,S */ int set_Parity(int fd,int databits,int stopbits,int parity) { struct termios options; if ( tcgetattr( fd,&options) != 0) { perror("SetupSerial 1"); return(FALSE); } options.c_cflag &= ~CSIZE; switch (databits) /*设置数据位数*/ { case 7: options.c_cflag |= CS7; break; case 8: options.c_cflag |= CS8; break; default: fprintf(stderr,"Unsupported data size "); return (FALSE); } switch (parity) { case 'n': case 'N': options.c_cflag &= ~PARENB; /* Clear parity enable */ options.c_iflag &= ~INPCK; /* Enable parity checking */ break; case 'o': case 'O': options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/ options.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'e': case 'E': options.c_cflag |= PARENB; /* Enable parity */ options.c_cflag &= ~PARODD; /* 转换为偶效验*/ options.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'S': case 's': /*as no parity*/ options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB;break; default: fprintf(stderr,"Unsupported parity "); return (FALSE); } /* 设置停止位*/ switch (stopbits) { case 1: options.c_cflag &= ~CSTOPB; break; case 2: options.c_cflag |= CSTOPB; break; default: fprintf(stderr,"Unsupported stop bits "); return (FALSE); } /* Set input parity option */ if (parity != 'n') options.c_iflag |= INPCK; tcflush(fd,TCIFLUSH); options.c_cc[VTIME] = 150; /* 设置超时15 seconds*/ options.c_cc[VMIN] = 0; /* Update the options and do it NOW */ if (tcsetattr(fd,TCSANOW,&options) != 0) { perror("SetupSerial 3"); return (FALSE); } return (TRUE); } 

需要注意的是:

如果不是开发终端之类的,只是串口传输数据,而不需要串口来处理,那么使用原始模式(Raw Mode)方式来通讯,设置方式如下:

 options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/ options.c_oflag &= ~OPOST; /*Output*/ 

读写串口
设置好串口之后,读写串口就很容易了,把串口当作文件读写就是。

  • 发送数据
     char buffer[1024];int Length;int nByte;nByte = write(fd, buffer ,Length) 
  • 读取串口数据

    使用文件操作read函数读取,如果设置为原始模式(Raw Mode)传输数据,那么read函数返回的字符数是实际串口收到的字符数。

    可以使用操作文件的函数来实现异步读取,如fcntl,或者select等来操作。

     char buff[1024];int Len;int readByte = read(fd,buff,Len); 

关闭串口
关闭串口就是关闭文件。

 close(fd); 

例子
下面是一个简单的读取串口数据的例子,使用了上面定义的一些函数和头文件

 /**********************************************************************代码说明:使用串口二测试的,发送的数据是字符, 但是没有发送字符串结束符号,所以接收到后,后面加上了结束符号。我测试使用的是单片机发送数据到第二个串口,测试通过。 **********************************************************************/ #define FALSE -1 #define TRUE 0 /*********************************************************************/ int OpenDev(char *Dev) { int fd = open( Dev, O_RDWR ); //| O_NOCTTY | O_NDELAY if (-1 == fd) { perror("Can't Open Serial Port"); return -1; } else return fd; } int main(int argc, char **argv){ int fd; int nread; char buff[512]; char *dev = "/dev/ttyS1"; //串口二 fd = OpenDev(dev); set_speed(fd,19200); if (set_Parity(fd,8,1,'N') == FALSE) { printf("Set Parity Error "); exit (0); } while (1) //循环读取数据 { while((nread = read(fd, buff, 512))>0) { printf(" Len %d ",nread); buff[nread+1] = ''; printf( " %s", buff); } } //close(fd); // exit (0); } 

参考资料

2004年09月23日
[精华] 关于打补丁的一些问题(译文)  

关于打补丁的一些问题
coly译

类unix操作系统有一个很有趣的特性就是源代码级的补丁包。在windows上我们打补丁都是运行一个可执行的程序,然后就可以把补丁打完了,这对于最终用户是非常方便的,但是对我们这些求知欲比较强的Linux fans来说就有点不过瘾了,因为我们不知道里面是怎么做的。而Linux的补丁就有趣多了,我们首先获得程序的源代码和对应的补丁文件,然后给源代码打补丁,产生新的源代码文件。然后再编译这个新的源代码文件,就获得了打过补丁的新程序了。
如果你现在还不懂得如何打补丁,那没有关系,我们就一起来试试,因为在刚开始写这篇文章的时候,我也不会给自己的程序打补丁。

确切的说,这篇文章不是我写的,而是我根据Daniel P. Bovet, Marco Cesati, 和Cosimo Comella写的一篇英文文档翻译并修改得出来的。之所以这么说,我是不想落抄袭之嫌。
言归正传:

解释patch文件
我们可以使用diff命令加参数-ruN来比较两个文件并生成一个补丁文件。这个补丁文件会列出这两个不同版本文件的差异来。我们将通过一个特定例子来解释这个由diff命令生成的补丁文件(patch file)。

假定:我们对检查linux-2.2.13和linux-2.2.14这两个不同的版本的差别很感兴趣。
第一步,我们使用如下命令:

make distclean

这样可以在两个源代码目录中删去所有非文本文件。
然后我们继续第二步:
*****************************************************************************

diff -ruN linux-2.2.13 linux-2.2.14 > /tmp/patch-2.2.14

*****************************************************************************
COMMAND EXECUTION:
-r 是一个递归选项,设置了这个选项,diff会将两个不同版本源代码目录中的所有对应文件全部都进行一次比较,正如你所料,这种比较也是包括子目录中的文件的。
-N 选项表明如果一个文件存在于一个目录中,那么它就必须被认为是在这个目录中的,哪怕这个文件在对应的目录中是一个空文件。(举个例子,如果在老版本中有这么一个文件,但是在新版本中这个文件被去掉了,那么diff仍然会把它记录下来,我们打完补丁以后,在得到的新版本代码中,老版本的那个文件名仍然会存在,但是是一个空文件)
-u 选项指明正在使用的是统一的输出格式。

下面我们查看一下经过重定向后生成的补丁文件/tmp/patch-2.2.14,下面是我们从该文件中摘抄的一部分补丁信息:
*****************************************************************************

diff -ruN linux-2.2.13/arch/i386/kernel/signal.c
linux-2.2.14/arch/i386/kernel/signal.c

这里第一个版本的名字,linux-2.2.13是参考版本(就是旧版本),所有的在linux-2.2.14(新版本)中发现的问题都是和第一个版本相关的。
*****************************************************************************
DIFF HEADER:
diff命令会在补丁文件中记录这两个文件的首次创建时间,如下:
*****************************************************************************
*** linux-2.2.13/arch/i386/kernel/signal.c Tue Jun 8 01:14:20 1999
— linux-2.2.14/arch/i386/kernel/signal.c Sun Jan 23 17:29:25 2000
*****************************************************************************
DIFF BODY:
diff 命令在这两个文件之间发现了3类差异。

a) 添加(addition):
这一行在旧版本的文件中没有,但是被添加到了新版本的文件中。
b) 置换(replacement):
在新版本文件中用连续的几行替换掉了旧版本文件中连续的几行。
c) 删除(deletion):
在旧版本文件中的一行在新版本文件中不再出现。

在每一种情况下,发生变化的行号都会被提示出来。
让我们解释一下diff用来指明这三种情况时使用的符号:
*****************************************************************************
添加(ADDITION):
看补丁文件中如下的行: (相对于arch/i386/kernel/signal.c文件的新旧两个版本)

*** 419,431 ****
— 419,437 —-
? current->exec_domain->signal_invmap[sig]
: sig),
&frame->sig);
+ if (err)
+ goto give_sigsegv;

使用+号指明在“&frame->sig);”这一行后面要加两个新行。这两个新行就是用+符号开头的两行。
*** 419,431 ****向读者指明可以从旧文件的419行到431行来查阅这些变化;同样的,— 419,437 —-向读者指明可以从新文件的419到437行来查阅这些变化。这样一来,新旧一比较,就可以知道哪些地方发生了什么变化。
不过在新版本的diff中,似乎并不是用这种方法来表明新旧文件对应的行号的,而使用@这个符号,对应于上例中的:
*** 419,431 ****
— 419,437 —-
我们看到的新的标识可能是:
@@ -419,431 +419,437 @@
对于这种表示方法,我还不是很懂,如果有哪位朋友比较懂的话,非常欢迎你将这部分内容加进来。
不过,有一点需要说明一下,就是这个行号并不是完全必需的,其实这个行号在给源代码打补丁的时候是没有用的,这里提示出来主要是给开发人员比较分析时使用的。

置换(REPLACEMENT):
看补丁文件中如下的行: (相对于arch/i386/kernel/signal.c文件的新旧两个版本)

***************
*** 367,377 ****
printk(“I/O APIC #%d Version %d at 0x%lX.\n”,
m->mpc_apicid,m->mpc_apicver,
m->mpc_apicaddr);
! /*
! * we use the first one only currently
! */
! if (ioapics == 1)
! mp_ioapic_addr = m->mpc_apicaddr;
}
mpt+=sizeof(*m);
count+=sizeof(*m);

然后后面又紧跟着如下的行:

— 368,376 —-
printk(“I/O APIC #%d Version %d at 0x%lX.\n”,
m->mpc_apicid,m->mpc_apicver,
m->mpc_apicaddr);
! mp_apics [mp_apic_entries] = *m;
! if (++mp_apic_entries > MAX_IO_APICS)
! –mp_apic_entries;
}
mpt+=sizeof(*m);
count+=sizeof(*m);

这里就指明了在旧版本文件中用!符号标识的5行被在新版本文件中用!标识的3行替换了。
由此可见,符号!就意味着替换。但是为什么会有替换,而不是先删除再添加,这里我就不清楚了。还是得请知道的朋友指点一下了。

删除(DELETION):
看补丁文件中如下的行: (相对于drivers/net/Config.in文件的新旧两个版本)
***************
*** 93,100 ****
fi
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate ‘RealTek 8129/8139 (not 8019/8029!) support’ CONFIG_RTL8139
- tristate ‘SiS 900 PCI Fast Ethernet Adapter support’ CONFIG_SIS900
- tristate ‘Packet Engines Yellowfin Gigabit-NIC support’ CONFIG_YELLOWFIN
fi
bool ‘Other ISA cards’ CONFIG_NET_ISA
if [ "$CONFIG_NET_ISA" = "y" ]; then
— 94,99 —-
***************
在旧版本文件中用-符号标识的两行说明这两行在新版本的文件中不会再出现了,也就是说,在新版本的文件中,这两行被删除了。

建立一个自己的补丁

你现在修改并测试了一个新的Linux版本,就称它为Linux-2.4.5kh3,这个版本和你当前使用的称作Linux-2.4.5kh2的“老”版本有一些些不同。

现在你想制作一个可以将Linux-2.4.5kh2升级到Linux-2.4.5kh3的补丁程序。顺便多说句废话,理所当然的这个补丁程序要比Linux内核的源代码小的多。
这个补丁文件一般使用一张软盘就可以装下来,因此这对于升级另一台计算机上的旧的操作系统内核是非常有用的。

本质上制作补丁程序只有两个步骤,如下描述:
a) 在计算机A上产生一个补丁文件(计算机A就是那台既有新内核的源代码又有老内核的源代码的计算机)。并且将这个补丁文件复制到一张软盘上。
b) 在计算机B上读取保存有补丁文件的软盘,并利用补丁文件将计算机B上的旧内核升级为新的内核。

下面我们进行详细的说明。其中第1到第4步描述了怎样制作一个补丁文件,并把它复制到软盘上。第5到第6步描述了怎么样使用补丁文件将旧的操作系统内核升级到新的版本。
*****************************************************************************
第1步:清理两个内核的源代码文件(没有*.o的文件或者.*文件)
*****************************************************************************
我们假定这两个内核的源代码路径分别是:
/usr/src/linux-2.4.5kh2和/usr/src/linux-2.4.5kh3

运行如下命令:
cd /usr/src/linux-2.4.5kh2
make distclean
cd /usr/src/linux-2.4.5kh3
make distclean
*****************************************************************************
第2步:在两个内核源代码版本之间产生一个“context diffs”文件(这个文件指明了两个不同版本源代码之间的所有不同)。
*****************************************************************************
运行如下命令(首先是旧的内核,然后是新的内核):
cd /usr/src
diff -ruN linux-2.4.5kh2 linux-2.4.5kh3 > patch-2.4.5kh3
*****************************************************************************
第3步:检查补丁文件。
*****************************************************************************
运行如下命令查看补丁文件以确定它没有包含任何的垃圾:
less patch-2.4.5kh3
这里所说的垃圾就是非ASCI码的乱码,或控制字符。如果发现补丁文件中存在着不是文本的内容,那就是有垃圾了。这是我们需要重新操作第1至第3步
*****************************************************************************
第4步:将补丁文件复制到一张软盘上。
*****************************************************************************
mount /flp
cp /usr/src/patch-2.4.5kh3 /flp
umount /flp

由于我们的补丁文件一般都很小,所以我们不需要压缩它。现在我们拿着这张带有补丁程序的软盘转移到计算机B前面去。
*****************************************************************************
第5步:从软盘中读取补丁文件。
*****************************************************************************
cd /usr/src
mount /flp
cp /flp/patch-2.4.5kh3 patch-2.4.5kh3
umount /flp
*****************************************************************************
第6步:使用这个补丁文件将旧内核的源代码升级到新内核的版本。
*****************************************************************************
a) 执行奇妙的patch命令:
patch -p0 < patch-2.4.5kh3
patch命令作用在输入的补丁文件patch-2.4.5kh3上,并将对应的老版本的内核源代码中所有的文件和子目录升级到对应的新版本(当然这里的老版本一定要和我们在计算机A上运行diff命令时的那个老版本是一样的)。在我们的例子中,旧的内核源代码版本是Linux-2.4.5kh2。这里参数–p0用来保证文件名不被改变(既不被修改,也不被删除)。
b) 重新命名内核源代码:
mv linux-2.4.5kh2 linux-2.4.5kh3

*****************************************************************************
撤消一个补丁
*****************************************************************************
如果你对新打的补丁不很满意,而你想回复到以前较早的内核版本去,那么我们从上面描述的第6步开始逆顺序操作即可(为什么要采取撤消补丁的方式来回到先前版本的理由很多,我们就不说了):
a) 将内核源代码的版本恢复到先前的名字:

mv linux-2.4.5kh3 linux-2.4.5kh2

b) 执行那条奇妙的patch命令:

patch -RE -p0 < patch-2.4.5kh3
这里,-E选项说明如果发现了空文件,那么就删除它;-R选项说明在补丁文件中的“新”文件和“旧”文件现在要调换过来了(实际上就是给新版本打补丁,让它变成老版本,但是这里是否一定要先更改源代码的目录名我还不明确,需要作实验)。

这里有一个疑问,就是为什么要进行代码目录的改名?

*****************************************************************************
避免make distclean操作
*****************************************************************************
根据文档/usr/src/linux/Documentation/SubmittingPatches所描述的,运行一个没有make distclean的递归diff,使用如下命令:
diff -ruN -X dontdiff linux-2.4.5kh2 linux-2.4.5kh3 > patch.diff
dontdiff是一个可执行文件,它可以从下面这个网址进行下载:
http://www.moses.uklinux.net/patches/dontdiff
但是,就我而言,我还是不知道为什么要这么做,或者说不进行make distclean的目的是什么。如果有那位朋友知道的话,非常感谢你告诉我一声,或者是把这部分内容补充到这份文档中。

制作一个官方的补丁文件
你已经安装了一个新的Linux,我们称它为Linux-2.4.2。但是差不多每个月,都会有新的Linux补丁推出,这些补丁或者修补了一些问题,或者支持了一些新的硬件或其它新的特性。所以,当你安装了Linux-2.4.2几个月以后,就会有新的稳定发行版推出,我们称它为Linux-2.4.5。

我们将要描述的过程解释了你如何最简便的将自己的Linux从2.4.2升级为最新的2.4.5。

关键的窍门在于使用一系列的补丁文件。
*****************************************************************************
第0步:理解官方的Linux补丁文件是如何制作的。
*****************************************************************************

每一个官方的Linux补丁文件都是一个使用diff工具在两个连续的Linux版本中所有文件间产生的diff文件。

作为一个例子,我们假定这个补丁文件是用来将Linux-2.4.2升级到Linux-2.4.5的,这个补丁文件通过如下方法获得:
cd /usr/src/linux-2.4.2
make distclean
cd /usr/src/linux-2.4.3
make distclean
ln -s linux-2.4.2 linux
diff -ruN linux linux-2.4.3 > patch_2.4.3
gzip patch_2.4.3

这些补丁文件按照顺序使用gzip压缩,以节省Linux发行版本站点的下载时间。例如我们生成的补丁文件——patch_2.4.3.gz,就是一个经过压缩的补丁文件。

Linux官方补丁总是认为缺省的源代码子树名字为“Linux”。这种方法可能有点混淆,但是它允许一些(版本)连续的补丁不用修改源代码子树的名字就可以连续的被修改到源代码子树上。(下面我们可以看到)

这些补丁文件的名字都是标准的:
patch_2.4.3 记录着linux-2.4.3 和 linux-2.4.2之间的版本差异。
patch_2.4.4 记录着linux-2.4.4 and linux-2.4.3之间的版本差异。
patch_2.4.5 记录着linux-2.4.5 and linux-2.4.4之间的版本差异。

在我们的例子中,我们正好需要这3个补丁文件,他们的名字是patch_2.4.3.gz、patch_2.4.4.gz和patch_2.4.5.gz,用来将Linux-2.4.2升级到Linux-2.4.5。

*****************************************************************************
第1步:升级Linux源代码目录的名字和Linux符号连接。
*****************************************************************************

假定内核源代码的路径是:/usr/src/linux-2.4.2/
并且所有需要的压缩补丁文件都已经存放在目录/usr/src 中了。
执行下列命令:
cd /usr/src
mv linux-2.4.2 linux-2.4.5
rm linux
ln -s linux-2.4.5 linux

*****************************************************************************
第2步:清理源代码目录(删除中间目标文件和配置文件)。
*****************************************************************************
执行下列命令:
cd linux
make distclean
*****************************************************************************
第3步:解压缩补丁文件。
*****************************************************************************
in our example, execute:

cd /usr/src
gunzip patch-2.4.3.gz
gunzip patch-2.4.4.gz
gunzip patch-2.4.5.gz
*****************************************************************************
第4步:重复执行patch命令。
*****************************************************************************
执行下列命令:
for i in 3 4 5; do
patch -p0 < patch_2-4.$i
done
其中
patch -p0 < patchfile

命令作用在输入的补丁文件上,并将对应的老版本的内核源代码中所有的文件和子目录升级到对应的新版本(在我们的例子中,老版本的内核源代码目录是/usr/src/linux)。在我们的例子中,旧的内核源代码版本是Linux-2.4.5kh2。这里参数–p0用来保证文件名不被改变(既不被修改,也不被删除)。
目标目录是Linux,就是说旧版本的内核源代码经过patch以后,就被升级成了新版本的内核源代码。

http://short.xilubbs.com/