红联Linux门户
Linux帮助

kernel compiler and gcc

发布时间:2007-07-08 00:24:46来源:红联作者:Enbrain
为了正确的合理地设置内核编译配置选项,从而只编译系统需要的功能的代码,一般主要有下面四个考虑:

l 自己定制编译的内核运行更快(具有更少的代码)。

2 系统将拥有更多的内存(内核部分将不会被交换到虚拟内存中)。

3 不需要的功能编译进入内核可能会增加被系统攻击者利用的漏洞。

4 将某种功能编译为模块方式会比编译到内核内的方式速度要慢一些。

内核编译模式

要增加对某部分功能的支持,比如网络之类,可以把相应部分编译到内核中(build-in),也可以把该部分编译成模块(module),动态调用。如果编译到内核中,在内核启动时就可以自动支持相应部分的功能,这样的优点是方便、速度快,机器一启动,你就可以使用这部分功能了;缺点是会使内核变得庞大起来,不管你是否需要这部分功能,它都会存在,这就是Windows惯用的招数,建议经常使用的部分直接编译到内核中,比如网卡。如果编译成模块,就会生成对应的.o文件,在使用的时候可以动态加载,优点是不会使内核过分庞大,缺点是你得自己来调用这些模块。

编译内核的基本工作:
在/usr/src目录下解开linux kernel packet

cd /usr/include
rm -rf asm linux scsi
ln -s /usr/src/linux/include/asm-i386 asm
ln -s /usr/src/linux/include/linux linux
ln -s /usr/src/linux/include/scsi scsi

make config
make dep
make clean
make bzImage

当我们开始编译的时候,总是能看到一些奇怪的错误,这是为什么呢?是因为在BSD的环境下,
有许多的宏(Macro)没有定义,比如说__linux__, __i386__, linux。那么我们打开
/usr/src/linux/Makefile文件,并在编译器的参数中加入 -D__linux__, -D__i386__, -Dlinux。

CC =$(CROSS_COMPILE)cc -D__KERNEL__ -D__linux__ -Dlinux -D__i386__ -I$(HPATH)

呵呵,大部分的问题已经解决了。但是可别忘记linux kernel中还包含一部分的8086代码,并且
所有的obj文件需要链接。这个时候我们需要as,as86,ld,ld86和一个名叫libbfd-2.9.5.0.22.so
的库文件,我们将执行文件复制到/home/camp,将库文件复制到/usr/lib中。

再试一次 make bzImage,呵呵,我们的new kernel顺利的生成落。

对于linux新手来说,编译内核相对有一些难度,甚至不知道如何入手,我通过在网上收集这方面的资料,最终编译成功.现在
我归纳了一下,写出这一篇还算比较详细的步骤,希望能对各位新手有一些
帮助。

1、安装内核
如果内核已经安装(/usr/src/目录有linux子目录),跳过
如果没有安装,在光驱中放入linux安装光盘,找到kernel-source-2.xx.xx.rpm文件(xx代表数字,表示内核的版本号),
比如RedHat linux的RPMS目录是/RedHat/RPMS/目录,然后使用命令rpm -ivh kernel-source-2.xx.xx.rpm安装内核
如果没有安装盘,可以去各linux厂家站点或者www.linuxhq.comwww.kernel.org下载。

2、清除从前编译内核时残留的.o 文件和不必要的关联
cd /usr/src/linux
make mrproper

3、配置内核,修改相关参数,请参考其他资料
在图形界面下,make xconfig;字符界面下,make menuconfig
在内核配置菜单中正确设置个内核选项,保存退出

4、正确设置关联文件
make dep

5、编译内核
对于大内核(比如需要SCSI支持),make bzImage
对于小内核,make zImage

6、编译模块
make modules

7、安装模块
make modules_install

8、使用新内核

方法一:
把/usr/src/linux/arch/i386/boot/目录内新生成的内核文件bzImage/zImage拷贝到/boot目录,
然后修改/etc/lilo.conf文件,加一个启动选项,使用新内核bzImage/zImage启动。格式如下:
boot=/dev/hda
map=/boot/map
install=/boot/boot.b
prompt
timeout=50
linear
default=linux-new ### 告诉lilo缺省使用新内核启动linux ###
append="mem=256M"

image=/boot/vmlinuz-2.2.14-5.0
label=linux
read-only
root=/dev/hda5

image=/boot/bzImage(zImage)
label=linux-new
read-only
root=/dev/hda5

保留旧有的启动选项可以保证新内核不能引导的情况,还可以进入linux进行其他操作。

保存退出后,不要忘记了最重要的一步,运行/sbin/lilo,使修改生效


方法二:使用GRUB(修改grub.conf文件)

(1)更换内核:A、mv /usr/src/linuxX.X.X/system.map /boot/system.map

B、mv /usr/src/linuxX.X.X/arch/i386/boot/bzImage /boot/vmlinuz

(2)修改引导管理程序Grub,/etc/grub.conf

内容如下:

#boot =/dev/had

default =0

timeout =10

splashimage =(hd0, 0)/grub/splash.xpm.gz

title Red Hat Linux(2.4.20-8)

root(hd0, 0)

kernel /vmlinuz -2.4.20-8 ro root =LABEL =/

initrd /initrd-2.4.20-8.img

9、重新生成ram磁盘
如果您的系统中的/etc/lilo.conf没有使用了ram磁盘选项initrd,略过
如果您的系统中的/etc/lilo.conf使用了ram磁盘选项initrd,
使用mkinitrd initrd-内核版本号 内核版本号命令重新生成ram磁盘文件,例如我的Redhat 6.2:
mkinitrd initrd-2.2.14-5.0 2.2.14-5.0
之后把/etc/lilo.conf中的initrd指向新生成的initrd-2.2.14-5.0文件:
initrd=/boot/initrd-2.2.14-5.0

ram磁盘能使系统性能尽可能的优化,具体参考/usr/src/linux/Documents/initrd.txt文件

10、重新启动,OK!



2004年4月20日最新版本的GCC编译器3.4.0发布了。目前,GCC可以用来编译C/C++、FORTRAN、JAVA、OBJC、ADA等语言的程序,可根据需要选择安装支持的语言。GCC 3.4.0比以前版本更好地支持了C++标准。本文以在Redhat Linux上安装GCC3.4.0为例,介绍了GCC的安装过程。

安装之前,系统中必须要有cc或者gcc等编译器,并且是可用的,或者用环境变量CC指定系统上的编译器。如果系统上没有编译器,不能安装源代码形式的GCC 3.4.0。如果是这种情况,可以在网上找一个与你系统相适应的如RPM等二进制形式的GCC软件包来安装使用。本文介绍的是以源代码形式提供的GCC软件包的安装过程,软件包本身和其安装过程同样适用于其它Linux和Unix系统。

系统上原来的GCC编译器可能是把gcc等命令文件、库文件、头文件等分别存放到系统中的不同目录下的。与此不同,现在GCC建议我们将一个版本的GCC安装在一个单独的目录下。这样做的好处是将来不需要它的时候可以方便地删除整个目录即可(因为GCC没有uninstall功能);缺点是在安装完成后要做一些设置工作才能使编译器工作正常。在本文中我采用这个方案安装GCC 3.4.0,并且在安装完成后,仍然能够使用原来低版本的GCC编译器,即一个系统上可以同时存在并使用多个版本的GCC编译器。

按照本文提供的步骤和设置选项,即使以前没有安装过GCC,也可以在系统上安装上一个可工作的新版本的GCC编译器。

1. 下载

在GCC网站上(http://gcc.gnu.org/)或者通过网上搜索可以查找到下载资源。目前GCC的最新版本为 3.4.0。可供下载的文件一般有两种形式:gcc-3.4.0.tar.gz和gcc-3.4.0.tar.bz2,只是压缩格式不一样,内容完全一致,下载其中一种即可。

2. 解压缩

根据压缩格式,选择下面相应的一种方式解包(以下的“%”表示命令行提示符):

% tar xzvf gcc-3.4.0.tar.gz
或者
% bzcat gcc-3.4.0.tar.bz2 | tar xvf -

新生成的gcc-3.4.0这个目录被称为源目录,用${srcdir}表示它。以后在出现${srcdir}的地方,应该用真实的路径来替换它。用pwd命令可以查看当前路径。

在${srcdir}/INSTALL目录下有详细的GCC安装说明,可用浏览器打开index.html阅读。

3. 建立目标目录

目标目录(用${objdir}表示)是用来存放编译结果的地方。GCC建议编译后的文件不要放在源目录${srcdir]中(虽然这样做也可以),最好单独存放在另外一个目录中,而且不能是${srcdir}的子目录。

例如,可以这样建立一个叫 gcc-build 的目标目录(与源目录${srcdir}是同级目录):

% mkdir gcc-build
% cd gcc-build

以下的操作主要是在目标目录 ${objdir} 下进行。

4. 配置

配置的目的是决定将GCC编译器安装到什么地方(${destdir}),支持什么语言以及指定其它一些选项等。其中,${destdir}不能与${objdir}或${srcdir}目录相同。

配置是通过执行${srcdir}下的configure来完成的。其命令格式为(记得用你的真实路径替换${destdir}):

% ${srcdir}/configure --prefix=${destdir} [其它选项]

例如,如果想将GCC 3.4.0安装到/usr/local/gcc-3.4.0目录下,则${destdir}就表示这个路径。

在我的机器上,我是这样配置的:

% ../gcc-3.4.0/configure --prefix=/usr/local/gcc-3.4.0 --enable-threads=posix --disable-checking --enable--long-long --host=i386-redhat-linux --with-system-zlib --enable-languages=c,c++,java

将GCC安装在/usr/local/gcc-3.4.0目录下,支持C/C++和JAVA语言,其它选项参见GCC提供的帮助说明。

5. 编译

% make

这是一个漫长的过程。在我的机器上(P4-1.6),这个过程用了50多分钟。

6. 安装

执行下面的命令将编译好的库文件等拷贝到${destdir}目录中(根据你设定的路径,可能需要管理员的权限):

% make install

至此,GCC 3.4.0安装过程就完成了。

6. 其它设置

GCC 3.4.0的所有文件,包括命令文件(如gcc、g++)、库文件等都在${destdir}目录下分别存放,如命令文件放在bin目录下、库文件在lib下、头文件在include下等。由于命令文件和库文件所在的目录还没有包含在相应的搜索路径内,所以必须要作适当的设置之后编译器才能顺利地找到并使用它们。

6.1 gcc、g++、gcj的设置

要想使用GCC 3.4.0的gcc等命令,简单的方法就是把它的路径${destdir}/bin放在环境变量PATH中。我不用这种方式,而是用符号连接的方式实现,这样做的好处是我仍然可以使用系统上原来的旧版本的GCC编译器。

首先,查看原来的gcc所在的路径:

% which gcc

在我的系统上,上述命令显示:/usr/bin/gcc。因此,原来的gcc命令在/usr/bin目录下。我们可以把GCC 3.4.0中的gcc、g++、gcj等命令在/usr/bin目录下分别做一个符号连接:

% cd /usr/bin
% ln -s ${destdir}/bin/gcc gcc34
% ln -s ${destdir}/bin/g++ g++34
% ln -s ${destdir}/bin/gcj gcj34

这样,就可以分别使用gcc34、g++34、gcj34来调用GCC 3.4.0的gcc、g++、gcj完成对C、C++、JAVA程序的编译了。同时,仍然能够使用旧版本的GCC编译器中的gcc、g++等命令。

6.2 库路径的设置

将${destdir}/lib路径添加到环境变量LD_LIBRARY_PATH中,最好添加到系统的配置文件中,这样就不必要每次都设置这个环境变量了。

例如,如果GCC 3.4.0安装在/usr/local/gcc-3.4.0目录下,在RH Linux下可以直接在命令行上执行或者在文件/etc/profile中添加下面一句:

setenv LD_LIBRARY_PATH /usr/local/gcc-3.4.0/lib:$LD_LIBRARY_PATH

7. 测试

用新的编译命令(gcc34、g++34等)编译你以前的C、C++程序,检验新安装的GCC编译器是否能正常工作。

8. 根据需要,可以删除或者保留${srcdir}和${objdir}目录。

4#make dep (一到两分钟)
在确定要编译哪些东东之后(make *config),这个要确定依赖性,这个东东,手工也可以完成的,只是….怕您要把什么东东都放下,然后花上十天半个月的来搞,还把您忙的焦头烂额,还会出错,不过我们用这条指令就可以完成了,也就不用麻烦您那么忙着搞了,呵呵,这个确定依赖性以后,然后就要清除一些东东了…
5#make clean (少于一分钟)
清除一些不必要的文件,那些乱七八糟的东东是可能会导致您在编译过程中出现错误的哦,一定要做哦…
6#make bzImage(15分钟左右)-
哦,这个可是最最最重要的啦.这个就是生成您的新核心了,不要告诉我您不知道核心是什么啊,也就是kernel啦,所有的系统硬件软件交互都靠它了哦..

其实可以是make zImage的,但是你要确保您所编译的这个新内核在640K之下,您就可以使用make zImage,如果比640K大,那就要用make bzImage,您要说没编译出来咋知道多大呢?我的看法是建议用bzImage,因为我编译出来的内核一般都是800~900K左右. …我是菜鸟,本帖子也是为我一样的菜鸟所写,所以. ..咱们就默认make bzImage…
还要注意哦,这段时间你是没法做事的,你会看见屏幕上一行一行的字往下跑,不用担心哦,你可以选择把这些标准输出上的东东都重定向到/dev/null去哦,这样您就看不到这些东东了,当然,你也可以把它放在背景执行啊,在运行要开始的时候在后面加上一个&符号,这个表示是后台运行…如果您怕这些会对您编译内核有什么影响(其实没什么影响哦),那您干脆就这样,按Alt+F2,直接打开另一个虚拟终端,在那里边做事,等到编译完的时候。机器会咚的一声通知您的哦,您要真不想等的话,就去玩会吧,听听歌什么的,过会再回来,这里可是考验您耐心的时候哦,如果这您都没耐心,那后面还有个耗时的步骤哦,还是忍忍吧,为了不让系统浪费资源,你还是忍忍哦,成功后您一定会很高兴的…
假如您的内核现在已经编译好了,当然越小越好哦J,这时候系统会有个提示编译后的bzImage放到哪里去了,提示最后几行,已经告诉了您的新编译出的核心位置啊,一般都在这里哦(我这里是RedHat9),/usr/src/linux-2.4.22/arch/i386/boot/,这时候您要做的就是把它放到/boot目录底下去哦,不然系统可没法启动的 …
#cp /usr/src/linux-2.4.22/arch/i386/boot/bzImage /boot/vmlinuz-2.4.22
(这里其实已经把bzImage更名为vmlinuz-2.4.22,呆会在/boot/grub/grub.conf里就指定这个新内核)

7#make modules(耗费时间取决于您所选择编译为modules的数量)
哇哇,又一个耗费时间的步骤来了,您还是找点什么做做吧,估计也要好久哦,大概20分钟吧,这个步骤就是把您在make menuconfig里边所选择为M的东东,全部编译成模块并放在/usr/src/linux-2.4.22/下…如果你选择的M比较多的话,还是…去玩会吧,家务没做啊?功课没做啊什么的?不过如果您比较喜欢把所有东东都编进内核的话,那就不需要多长时间,少选一些为M,这样很快就可以完成,我的只用了一分钟就完成了,不过如果您有很多不知道而选择默认的话,那恐怕就要好花时间了. ..
8#make modules_install
文章评论

共有 0 条评论