LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 871|回复: 5

怎样给kernel打补丁?

[复制链接]
发表于 2005-1-11 12:51:50 | 显示全部楼层 |阅读模式
我在论坛里看到大家说可以给特定的内核打补丁不知怎样做,请教!!!
发表于 2005-1-11 14:39:01 | 显示全部楼层
一般情况下 是你把patch文件考到你的内核目录 然后运行
   patch -p1 < <patch file name here>

上面的那个 -p1参数不是每个补丁都有的 下载的补丁 一般都有说明的
你也可以使用 man patch 或者info patch 来查看的 patch的参数
 楼主| 发表于 2005-1-11 17:21:31 | 显示全部楼层
谢谢!!我用过那个命令但不好用,你能说的详细点吗??谢谢!!
发表于 2005-1-12 10:10:43 | 显示全部楼层
patch 的正规用法是
patch [options] [originalfile [patchfile]]
不过通常 当你把你的patch文件拷贝到需要patch的目录(/usr/src/linux)下时
你只需要使用
       patch -pnum <patchfile
      
patch有很多参数 重用的有:(这些都是从 man patch中拷贝出来的,没有完全拷贝出来)
-b  or  --backup
          Make  backup files.  That is, when patching a file, rename or copy the original instead of removing it.  When backing
          up a file that does not exist, an empty, unreadable backup file is created as a placeholder to represent the nonexis?
          tent file.  See the -V or --version-control option for details about how backup file names are determined.

       --backup-if-mismatch
          Back  up a file if the patch does not match the file exactly and if backups are not otherwise requested.  This is the
          default unless patch is conforming to POSIX.

       --no-backup-if-mismatch
          Do not back up a file if the patch does not match the file exactly and if backups are not otherwise requested.   This
          is the default if patch is conforming to POSIX.

       -B pref  or  --prefix=pref
          Prefix  pref  to  a  file  name  when generating its simple backup file name.  For example, with -B /junk/ the simple
          backup file name for src/patch/util.c is /junk/src/patch/util.c.

       --binary
          Read and write all files in binary mode, except for standard output and /dev/tty.   This  option  has  no  effect  on
          POSIX-conforming systems.  On systems like DOS where this option makes a difference, the patch should be generated by
          diff -a --binary.

       -c  or  --context
          Interpret the patch file as a ordinary context diff.

       -d dir  or  --directory=dir
          Change to the directory dir immediately, before doing anything else.

       -D define  or  --ifdef=define
          Use the #ifdef ... #endif construct to mark changes, with define as the differentiating symbol.

       --dry-run
          Print the results of applying the patches without actually changing any files.

       -e  or  --ed
          Interpret the patch file as an ed script.

       -E  or  --remove-empty-files
          Remove output files that are empty after the patches have been applied.  Normally this option is  unnecessary,  since
          patch can examine the time stamps on the header to determine whether a file should exist after patching.  However, if
          the input is not a context diff or if patch is conforming to POSIX, patch does not remove empty patched files  unless
          this option is given.  When patch removes a file, it also attempts to remove any empty ancestor directories.

       -f  or  --force
          Assume that the user knows exactly what he or she is doing, and do not ask any questions.  Skip patches whose headers
          do not say which file is to be patched; patch files even though they have the wrong version for the Prereq:  line  in
          the  patch;  and assume that patches are not reversed even if they look like they are.  This option does not suppress
          commentary; use -s for that.

       -F num  or  --fuzz=num
          Set the maximum fuzz factor.  This option only applies to diffs that have context, and causes patch to ignore  up  to
          that  many  lines  in  looking  for places to install a hunk.  Note that a larger fuzz factor increases the odds of a
          faulty patch.  The default fuzz factor is 2, and it may not be set to more than the number of lines of context in the
          context diff, ordinarily 3.

       -g num  or  --get=num
          This option controls patch's actions when a file is under RCS or SCCS control, and does not exist or is read-only and
          matches the default version, or when a file is under ClearCase control and does not exist.  If num is positive, patch
          gets  (or  checks out) the file from the revision control system; if zero, patch ignores RCS, ClearCase, and SCCS and
          does not get the file; and if negative, patch asks the user whether to get the  file.   The  default  value  of  this
          option is given by the value of the PATCH_GET environment variable if it is set; if not, the default value is zero if
          patch is conforming to POSIX, negative otherwise.

       --help
          Print a summary of options and exit.

       -i patchfile  or  --input=patchfile
          Read the patch from patchfile.  If patchfile is -, read from standard input, the default.

       -l  or  --ignore-whitespace
          Match patterns loosely, in case tabs or spaces have been munged in your files.  Any sequence of one or more blanks in
          the  patch  file matches any sequence in the original file, and sequences of blanks at the ends of lines are ignored.
          Normal characters must still match exactly.  Each line of the context must still match a line in the original file.

       -n  or  --normal
          Interpret the patch file as a normal diff.

       -N  or  --forward
          Ignore patches that seem to be reversed or already applied.  See also -R.

       -o outfile  or  --output=outfile
          Send output to outfile instead of patching files in place.

       -pnum  or  --strip=num
          Strip the smallest prefix containing num leading slashes from each file name found in the patch file.  A sequence  of
          one  or more adjacent slashes is counted as a single slash.  This controls how file names found in the patch file are
          treated, in case you keep your files in a different directory than the person who sent out the patch.   For  example,
          supposing the file name in the patch file was

             /u/howard/src/blurfl/blurfl.c

          setting -p0 gives the entire file name unmodified, -p1 gives

             u/howard/src/blurfl/blurfl.c

          without the leading slash, -p4 gives

             blurfl/blurfl.c

          and  not  specifying -p at all just gives you blurfl.c.  Whatever you end up with is looked for either in the current
          directory, or the directory specified by the -d option.

       --posix
          Conform more strictly to the POSIX standard, as follows.

           ?Take the first existing file from the list (old, new, index) when intuiting file names from diff headers.

           ?Do not remove files that are empty after patching.

           ?Do not ask whether to get files from RCS, ClearCase, or SCCS.

           ?Require that all options precede the files in the command line.

           ?Do not backup files when there is a mismatch.

       --quoting-style=word
          Use style word to quote output names.  The word should be one of the following:

          literal
                 Output names as-is.

          shell  Quote names for the shell if they contain shell metacharacters or would cause ambiguous output.

          shell-always
                 Quote names for the shell, even if they would normally not require quoting.

          c      Quote names as for a C language string.

          escape Quote as with c except omit the surrounding double-quote characters.

          You can specify the default value of the --quoting-style option with the environment variable QUOTING_STYLE.  If that
          environment variable is not set, the default value is shell.

       -r rejectfile  or  --reject-file=rejectfile
          Put rejects into rejectfile instead of the default .rej file.

       -R  or  --reverse
          Assume  that  this patch was created with the old and new files swapped.  (Yes, I'm afraid that does happen occasion?
          ally, human nature being what it is.)  patch attempts to swap each hunk around before applying it.  Rejects come  out
          in  the  swapped format.  The -R option does not work with ed diff scripts because there is too little information to
          reconstruct the reverse operation.

          If the first hunk of a patch fails, patch reverses the hunk to see if it can be applied that way.  If it can, you are
          asked  if  you want to have the -R option set.  If it can't, the patch continues to be applied normally.  (Note: this
          method cannot detect a reversed patch if it is a normal diff and if the first command is an append  (i.e.  it  should
          have  been  a  delete)  since appends always succeed, due to the fact that a null context matches anywhere.  Luckily,
          most patches add or change lines rather than delete them, so most reversed normal diffs begin with  a  delete,  which
          fails, triggering the heuristic.)

       -s  or  --silent  or  --quiet
          Work silently, unless an error occurs.

       -t  or  --batch
          Suppress questions like -f, but make some different assumptions: skip patches whose headers do not contain file names
          (the same as -f); skip patches for which the file has the wrong version for the Prereq: line in the patch; and assume
          that patches are reversed if they look like they are.

       -T  or  --set-time
          Set  the modification and access times of patched files from time stamps given in context diff headers, assuming that
          the context diff headers use local time.  This option is not recommended, because patches  using  local  time  cannot
          easily  be  used  by  people  in other time zones, and because local time stamps are ambiguous when local clocks move
          backwards during daylight-saving time adjustments.  Instead of using this option, generate patches with UTC  and  use
          the -Z or --set-utc option instead.

       -u  or  --unified
          Interpret the patch file as a unified context diff.

       -v  or  --version
          Print out patch's revision header and patch level, and exit.

这些我也没有都用过,我只用过 N 、i和pnum这种形式的

N代表的是忽略那些颠倒的或者已经应用过的补丁

i代表从补丁文件中读取补丁
(可以参看这个 我的英文不是很好 这次cet6又挂了 :( 就不翻译了
-i patchfile  or  --input=patchfile
          Read the patch from patchfile.  If patchfile is -, read from standard input, the default.)
pnum这种 其中的num就是参数的意思 代表补丁所要修改文件名的深度 (这么翻译可能是错误的,下面的原文 你自己看吧还有例子:))         
-pnum  or  --strip=num
          Strip the smallest prefix containing num leading slashes from each file name found in the patch file.  A sequence  of
          one  or more adjacent slashes is counted as a single slash.  This controls how file names found in the patch file are
          treated, in case you keep your files in a different directory than the person who sent out the patch.   For  example,
          supposing the file name in the patch file was

             /u/howard/src/blurfl/blurfl.c

          setting -p0 gives the entire file name unmodified, -p1 gives

             u/howard/src/blurfl/blurfl.c

          without the leading slash, -p4 gives

             blurfl/blurfl.c

          and  not  specifying -p at all just gives you blurfl.c.  Whatever you end up with is looked for either in the current
          directory, or the directory specified by the -d option.         
         
下面是几个例子

patch -Np1 -i ../gcc-3.3.2-no_fixincludes-1.patch
patch -Np1 -i ../gcc-3.3.2-specs-1.patch

-i 后面接的是上级目录中的 补丁文件 gcc-3.3.2-no_fixincludes-1.patch

我最近经常使用的补丁是MTD的补丁

patch -p1 << mtd-2.2.17.patch

<< 的作用和 - i是相同的 都是表示补丁文件
发表于 2005-1-12 10:17:27 | 显示全部楼层
其实内核的补丁还有其它的形式
例如 MTD新版本的补丁 都是脚本的形式 配合patch命令给出的
下面就把那个脚本给出来 给你参考一下



#!/bin/sh
#
#  我把注释都删掉了 节省地方
# Preset variables
FILESYSTEMS="no"
BK="no"
VERSION=0
PATCHLEVEL=0
SUBLEVEL=0
ZLIBPATCH="no"
RSLIBPATCH="no"
DOCPATCH="no"
CONFIG="Config.in"
LNCP="ln -sf"
METHOD="Link"
#上面的部分是对一些变量的定义 下面还有很多的变量 定义 我都删掉了 如果你要看的话 可以自己去下载一个
#地址是 ftp://ftp.uk.linux.org/pub/people/dwmw2/mtd/cvs/

# Display usage of this script 这个是很明显的了 显示参数
usage () {
        echo "usage:  $0 [-c] [-j] kernelpath"
        echo "   -c  -- copy files to kernel tree instead of building links"
        echo "   -j  -- include jffs2 filesystem"
        echo "   -b  -- Check files out for write from BK"
        exit 1
}

# Function to patch kernel source
patchit () {
for DIR in $PATCH_DIRS
do
        echo $DIR
        mkdir -p $DIR
        cd $TOPDIR/$DIR
        FILES=`ls $PATCH_FILES 2>/dev/null`
        if [ "$BK" = "yes" -a -d $LINUXDIR/$DIR/SCCS ]; then
            pushd $LINUXDIR/$DIR
            rm -f $FILES
            bk co -ql $FILES
            popd
        fi
        for FILE in $FILES
        do
                # If there's a Makefile.common it goes in place of Makefile
                if [ "$FILE" = "Makefile" -a -r $TOPDIR/$DIR/Makefile.common ]; then
                    if test $PATCHLEVEL -lt 5; then
                        rm -f $LINUXDIR/$DIR/Makefile.common 2>/dev/null
                        $LNCP $TOPDIR/$DIR/Makefile.common $LINUXDIR/$DIR/Makefile.common
                        SRCFILE=Makefile.24
                    else
                        SRCFILE=Makefile.common
                    fi
                else
                    SRCFILE=$FILE
                fi
                rm -f $LINUXDIR/$DIR/$FILE 2>/dev/null
                $LNCP $TOPDIR/$DIR/$SRCFILE $LINUXDIR/$DIR/$FILE
        done
        cd $LINUXDIR
done
}



# Start of script

# Get commandline options
while getopts cjb opt
do
    case "$opt" in
      j)  FILESYSTEMS=yes;;
      c)  LNCP="cp -f"; METHOD="Copy";;
      b)  BK=yes;;
      \?)
          usage;
    esac
done
shift `expr $OPTIND - 1`
LINUXDIR=$1

if [ -z $LINUXDIR ]; then
    usage;
fi

if [ ! -f $LINUXDIR/Makefile -a "$BK" = "yes" ]; then
    pushd $LINUXDIR
    bk co Makefile
    popd
fi

# Check if kerneldir contains a Makefile
if [ ! -f $LINUXDIR/Makefile ]
then
        echo "Directory $LINUXDIR does not exist or is not a kernel source directory";
        exit 1;
fi

# Get kernel version  判断内核的版本号 这个很关键的 你有些补丁 可能不能打的原因 就是内核的 版本号不对
VERSION=`grep -s VERSION <$LINUXDIR/Makefile | head -n 1 | sed s/'VERSION = '//`
PATCHLEVEL=`grep -s PATCHLEVEL <$LINUXDIR/Makefile | head -n 1 | sed s/'PATCHLEVEL = '//`
SUBLEVEL=`grep -s SUBLEVEL <$LINUXDIR/Makefile | head -n 1 | sed s/'SUBLEVEL = '//`

# Can we handle this ?
if test $VERSION -ne 2 -o $PATCHLEVEL -lt 4
then
        echo "Cannot patch kernel version $VERSION.$PATCHLEVEL.$SUBLEVEL";
        exit 1;
fi

# Use Kconfig instead of Config.in for Kernels >= 2.5
if test $PATCHLEVEL -gt 4
then
        CONFIG="Kconfig";
fi
MTD_FILES="$MTD_FILES $CONFIG"

# Have we to use ZLIB PATCH ?
if [ "$FILESYSTEMS" = "yes" ]
then
        PATCHDONE=`grep -s zlib_deflate $LINUXDIR/lib/Makefile | head -n 1`
        if test $PATCHLEVEL -eq 4 -a $SUBLEVEL -lt 20
        then
                if [ "$PATCHDONE" = "" ]
                then
                        ZLIBPATCH=yes;
                fi
        fi
fi


#这中间我也去掉很大一段 内容和我保留的基本差不多 上面是判断需不需要打补丁 下面就开始打补丁

echo "atching Documentation"
if [ "$DOCPATCH" = "yes" ]
then
    patch -p1 -i $TOPDIR/$DOC_DIRS/Makefile.diff
fi

PATCH_DIRS=$DOC_DIRS
PATCH_FILES=$DOC_FILES
patchit;


echo "atching done"

# some BUG() definitions were moved to asm/bug.h in the 2.5 kernels
#  so fake having one to avoid build errors.
if test $PATCHLEVEL -lt 5; then
        if [ ! -r $LINUXDIR/include/asm/bug.h ]; then
                touch $LINUXDIR/include/asm/bug.h
        fi
fi

if test $PATCHLEVEL -lt 5
then
        # FIXME: SED/AWK experts should know how to do it automagic
        echo "lease update Documentation/Configure.help from $TOPDIR/Documentation/Configure.help"
fi


个人认为 这个脚本的主要作用 就是判断内核的版本号 然后 进行patch
发表于 2005-1-12 10:28:35 | 显示全部楼层
patch 使用的文件是和diff有联系的
你可以做几个小试验的
下面是我做的一个
你可以参考一下 有什么不对的 还需要版上的高手指正。

[root@localhost /root]# echo old >old
[root@localhost /root]# echo new >new
[root@localhost /root]# diff -u old new >patch
[root@localhost /root]# mv new new.bak
[root@localhost /root]# patch -Np1 -i patch
missing header for unified diff at line 3 of patch
can't find file to patch at input line 3
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|--- old        Wed Jan 12 10:27:17 2005
|+++ new        Wed Jan 12 10:27:27 2005
--------------------------
File to patch: old
patching file old
[root@localhost /root]# cat old
new

这其中diff的参数什么的 你上网上 找找 有教程的
不过我忘记在哪里 就自己写了这个破东西 凑合看着
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表