信息提示
您的同一ip请求过于频繁,如果希望继续访问,请输入验证码:
Copyright 1998 – 2010 Tencent. All Rights Reserved.主题:HOWTOdoLin何谓f00f_bug?uxkerneldevelopment 作者:wantin6 时间:2006-08-07 22:53
标题: 作者:ronghuaiyang 时间:2009-05-15 10:34
您好,linux_mig_release.pdf 下载不了了,我想您能不能发一份给我,我的邮箱:
[email]rxh@mail.ustc.edu.cn[/email]
标题: 作者:c e 时间:2009-05-16 05:47
看不懂 不过支持了
标题: 作者:c e 时间:2009-05-16 06:05
不知道你说什么,为了钱
标题:HOWTOdoLin何谓f00f_bug?uxkerneldevelopment 作者:wantin6 时间:2006-08-07 22:53
HackingtheLinuxKernelNetworkStack(译本)
基于S3C2410的Linux全线移植文档
超高兴,我们团队自己的文档。
已上传到附件中 (edit by platinum)
欢迎转载此pdf文档,如有不明之处可以向文档当中各部分负责团队成员发邮件。
目录:
第一部分 前言
第二部分 系统启动bootloader的编写(ADS)
第三部分 GNU交叉工具链
第四部分 u-boot的移植
第五部分 linux 2.6内核的移植
第六部分 应用程序的移植
第七部分 Nand flash驱动的编写与移植
[ 本帖最后由 dozec 于 2006-7-26 15:10 编辑 ]
附件:
linux_mig_release.pdf (2006-7-26 10:00, 1.09 M)
该附件被下载次数 175
__________________________________
ARM-内核-存储
Q:17541461
BLOG:[url=http://blog.csdn.net/dozec/]http://blog.csdn.net/dozec/[/url]
MAIL:[url=mailto:dozec@mail.csdn.net]dozec@mail.csdn.net[/url](有事发MAIL吧) 看了platinum兄弟写的在2.4内核下给iptables添加模块,想在2.6的内核下也试试,经过一天半的努力,并参考platinum兄弟的文章,
终于成功,写下来跟CU的兄弟们分享,我的系统为fedora2+linux-2.6.5-1.358
1,***kernel源码
[root@jiecho]# yum i tall kernel-source
2,下载iptables-1.3.3.tar.bz2和patch-o-matic-ng-20050810.tar.bz2并解包,为了方便,我们都放在/usr/src下,
并把kernel和iptables做符号链接.
[root@jiecho]# cd /usr/src
[root@jiecho]# wget [url=ftp://ftp.be.netfilter.org/pub/netfilter/iptables/iptables-1.3.3.tar.bz2]ftp://ftp.be.netfilter.org/pub/netfilter/iptables/iptables-1.3.3.tar.bz2[/url]
[root@jiecho]# wget [url=ftp://ftp.be.netfilter.org/pub/netfilter/patch-o-matic-ng/ a hot/patch-o-matic-ng-20050810.tar.bz2]ftp://ftp.be.netfilter.org/pub/netfilter/patch-o-matic-ng/ a hot/patch-o-matic-ng-20050810.tar.bz2[/url]
[root@jiecho]# tar -jxvf iptables-1.3.3.tar.bz2
[root@jiecho]# tar -jxvf patch-o-matic-ng-20050810.tar.bz2
[root@jiecho]# ln -s linux-2.6.5-1.358 linux
[root@jiecho]# ln -s iptables-1.3.3 iptables
3,给netfilter打补丁,选择你要的模块,为了测试我就选择了i 2p和time
[root@jiecho]# cd /usr/src/linux
[root@jiecho]# make mrproper
[root@jiecho]# make menuconfig
什么不做,保存退出,然后把Makefile改一下
[root@jiecho]# vi Makefile
把EXTR***ERSION = -1.358custom更改为EXTR***ERSION = -1.358
保持跟uname -a 的版本一致(可详细参考platinum兄弟的文章)
[root@jiecho]# cd /usr/src/patch-o-matic-ng-20050810
[root@jiecho]# ./runme i 2p
[root@jiecho]# ./runme time
因为事先做好了符号链接,等问你kernel和iptables的位置的时候直接回车就行,
提示你是否添加i 2p和time模块是就y确定,至此,netfilter的补丁打完了,如果你需要别的模块可以根据需要加上.
4,编译kernel的modules
[root@jiecho]# cd /usr/src/linux
[root@jiecho]# make menuconfig
在Device Drivers->;Networking su ort->;Networking optio ->;Network packet filtering (replaces ipchai )
->;IP: Netfilter Configuration中把下面的两项M选中.
; TIME match su ort ; IPP2P match su ort
然后保存退出
4,编译***模块
下面就是最重要的步骤了,因为我们的原则是节省时间,不重新编译内核,而只编译其中的模块,
这点2.4的内核跟2.6的内核有所不同,郁闷了我一整天,2.4内核的模块是以*.o形式的,而2.6内核是以*.ko形式的,
这有个改变的方法,参考:[url]http://blog.chinaunix.net/article.php?articleId=40742&am logId=2662[/url]
[root@jiecho]# make modules HOSTCC cripts/basic/fixdep HOSTCC cripts/basic/ lit-include HOSTCC cripts/basic/docproc HOSTCC cripts/conmakehash HOSTCC cripts/kallsyms CC cripts/empty.o HOSTCC cripts/mk_elfconfig MKELF cripts/elfconfig.h HOSTCC cripts/file2alias.o HOSTCC cripts/modpost.o HOSTCC cripts/sumversion.o HOSTLD cripts/modpost HOSTCC cripts/ mtologo HOSTCC cripts/bin2c 到这里就可以ctrl+c中止了,因为我们不是要编译所有的模块,这样太浪费时间,而仅仅是netfilter的模块, 但是如果你直接执行make modules SUBDIRS=net/ipv4/netfilter就会出错,这就是2.4和2.6的区别, 我们先生成了scripts目录下的一系列需要的文件后就可以make modules SUBDIRS=net/ipv4/netfilter, 并用modpost等等把*.o文件生成为*.ko文件.
[root@jiecho]# make modules SUBDIRS=net/ipv4/netfilter
编译完成netfilter的模块后拷贝编译完成的模块
[root@jiecho]# cp /usr/src/linux/net/ipv4/netfilter/ipt_i 2p.ko /lib/modules/2.6.5-1.358/kernel/net/ipv4/netfilter/
[root@jiecho]# cp /usr/src/linux/net/ipv4/netfilter/ipt_time.ko /lib/modules/2.6.5-1.358/kernel/net/ipv4/netfilter/
[root@jiecho]# chmod +x /lib/modules/2.6.5-1.358/kernel/net/ipv4/netfilter/ipt_i 2p.ko
[root@jiecho]# chmod +x /lib/modules/2.6.5-1.358/kernel/net/ipv4/netfilter/ipt_time.ko
[root@jiecho]# depmod -a
5,编译iptables
[root@jiecho]# cd /usr/src/iptables
参照INSTALL文件我们进行编译***
[root@jiecho]# make KERNEL_DIR=/usr/src/linux
会有错误编译不过
/usr/src/linux/include/linux/config.h:6:2: [root@jiecho]#error including kernel header in user ace; use the glibc headers i tead!
我google了半天也没有找到是什么原因,就自己动手解决
[root@jiecho]# vi /usr/src/linux/include/linux/config.h把下面的三行注释掉
//#ifndef __KERNEL__
//#error including kernel header in user ace; use the glibc headers i tead!
//#endif
然后重新编译***
make KERNEL_DIR=/usr/src/linux
make i tall KERNEL_DIR=/usr/src/linux
完成***以后测试一下
[root@jiecho]# iptables -V
[root@jiecho]# modprobe ipt_time
[root@jiecho]# modprobe ipt_i 2p
[root@jiecho]# lsmod
ipt_time 2432 0
ipt_i 2 7552 0
ipt_REJECT 4736 1
ipt_state 1536 1
ip_co track 24968 1 ipt_state
iptable_filter 2048 1
ip_table 13440 5 ipt_time,ipt_i 2p,ipt_REJECT,ipt_state,iptable_filter
battery 6924 0
ipv6 184288 10
3c59x 30376 0
binfmt_misc 7176 1
nls_utf8 1536 4
ntf 81516 4
dm_mod 33184 0
uhci_hcd 23708 0
butto 4504 0
asus_acpi 8472 0
ac 3340 0
ext3 102376 4
jbd 40216 1 ext3
测试iptables
[root@jiecho]# iptables -A FORWARD -m i 2p --edk --kazaa --bit -j DROP
[root@jiecho]# iptables -A INPUT -m time --timestart 8:00 --timestop 18:00 --days Mon,Tue,Wed,Thu,Fri
[root@jiecho]# iptalbes -L 是不是中断处理程序就永远不能继续执行了? 俗话说:"功夫不负有心人",通过编译Linux内核时才能真正体会到.曾经也失败过无数次,放弃过一段时间编译.最后通过自己不断的实践和在网上收集这方面资料,终于在前不久编译成功了.把我在网上收集的资料和自己编译的过程整理了一下,拿来和大家分享一下,希望能给有这方面需要的同仁以帮助,好让大家少走弯路.
言归正传:
环境:VMware5.0 for windows(在新建虚拟机向导的"虚拟机磁盘类型"本人选的是IDE)
内核版本:kernel2.6.13(原内核是字符模式,不包括xwindow模式)
原来的系统是redhat9.0,内核2.4.20-8,编译的内核2.6.13,仅供参考.
共分为四部分:编译前准备->;编译配置->;编译过程->;运行内核的常见问题
一 编译前准备
1)下载一份内核源代码,我下的版本是linux-2.6.13.tar.gz,你可在如下地址下载它或者是更新的版本.
[url=http://www.kernel.org/pub/linux/kernel/v2.6/]http://www.kernel.org/pub/linux/kernel/v2.6/[/url]
2) 下载最新版本的module-init-tools( "module-init-tools-3.0.tar.gz" and "modutils-2.4.21-23.src.rpm")
[url=http://www.kernel.org/pub/linux/]http://www.kernel.org/pub/linux/[/url] ... it-tools-3.0.tar.gz
[url=http://www.kernel.org/pub/linux/]http://www.kernel.org/pub/linux/[/url] ... s-2.4.21-23.src.rpm
3)***modutils-2.4.21-23.src.rpm. 你可能会看到"user rusty and group rusty not existing"的警告. 没关系,你只需强制***就是了.如果你不对Redhat 9和Redhat 8做这几步, 你将会在"make modules_i tall"这一步时出现问题.
#rpm -e --node modutils (强行卸载原有的modutilsRPM包)
#rpm -ivh modutils-2.4.21-23.src.rpm (把源代码包***到了/usr/src/redhat目录下)
#cd /usr/src/redhat/SPECS (进入规范文件目录下)
#rpmbuild -- modutils. ec (生成二进制的RPM包)
#cd ../RPMS/i386 (转入刚生成的二进制的RPM包所在位置)
#rpm -ivh modutils*.rpm (刚生成两个[modutils-2.4.21-23.i386.rpm与modutils-debuginfo-2.4.21.23.i386.rpm]二进制的RPM包,一起***吧!)
4)***module-init-tools. 它会替代depmod [/ in/depmod]和其他工具.
tar -zxvf module-init-tools-3.0.tar.gz
cd module-init-tools-3.0
./configure --prefix=/ in
make i tall
./generate-modprobe.conf /etc/modprobe.conf
5)解压缩内核源代码.把下载的源代码包放到目录/usr/src下,然后
cd /usr/src
tar –zvxf linux-2.6.13.tar.gz
ln –s linux-2.6.13 linux
cd linux
6)make mrproper
该命令确保源代码目录下没有不正确的.o文件以及文件的互相依赖。由于我们使用刚下载的完整的
源程序包进行编译,所以本步可以省略。而如果你多次使用了这些源程序编译内核,那么最好要先运行
一下这个命令
犎繁/usr/include/目录下的asm、linux和scsi等链接是指向要升级的内核源代码的。它们分别链向源代码目录下的真正的、该计算机体系结构(对于PC机来说,使用的体系结构是i386)所需要的真正的
include子目录。如:asm指向/usr/src/linux/include/asm-i386等。若没有这些链接,就需要手工创建
,按照下面的步骤进行:
# cd /usr/include/
# rm -r 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
这是配置非常重要的一部分。删除掉/usr/include下的asm、linux和scsi链接后,再创建新的链接
指向新内核源代码目录下的同名的目录。这些头文件目录包含着保证内核在系统上正确编译所需要的重
要的头文件。现在你应该明白为什么我们上面又在/usr/src下"多余"地创建了个名为linux的链接了吧?
*******************************************************************
编译linux2.6.14的仁兄们注意了,如果是按本人的帖子上的步骤,请将以上第7)步
去掉,否则运行make menuconfig会出现以下错误
HOSTCC cripts/basic/ lit-include
In file included from /usr/include/linux/errno.h:4, from /usr/include/bits/errno.h:25, from /usr/include/errno.h:36, from scripts/basic/ lit-include.c:26:
/usr/include/asm/errno.h:4:31: asm-generic/errno.h: 没有那个文件或目录
make[1]: *** [scripts/basic/ lit-include] Error 1
make: *** [scripts_basic] Error 2
*************************************************************
二 编译配置
在这一部分涉及几个重要模块的配置请,特别注意.一般用"make menuconfig"命令来配置内核.
进入图形模式
#startx
接下来的内核配置过程比较烦琐,但是配置的适当与否与日后Linux的运行直接相关,有必要了解一下一
些主要的且经常用到的选项的设置。
牐犈渲媚诤丝梢愿据需要与爱好使用下面命令中的一个:
#make config(基于文本的最为传统的配置界面,不推荐使用)
#make menuconfig(基于文本选单的配置界面,字符终端下推荐使用)
#make xconfig(基于图形窗口模式的配置界面,Xwindow下推荐使用)
#make oldconfig(如果只想在原来内核配置的基础上修改一些小地方,会省去不少麻烦)
牐犝馊个命令中,make xconfig的界面最为友好,如果你可以使用Xwindow,那么就推荐你使用这个命
牐犎绻你不能使用Xwindow,那么就使用make menuconfig好了。界面虽然比上面一个差点,总比make
config的要好多了。
牐犙≡裣嘤Φ呐渲檬保有三种选择,它们分别代表的含义如下:
Y--将该功能编译进内核
N--不将该功能编译进内核,也不编成模块
M--将该功能编译成可以在需要时动态插入到内核中的模块
牐犎绻使用的是make xconfig,使用鼠标就可以选择对应的选项。如果使用的是make menuconfig,则
需要使用空格键进行选取。你会发现在每一个选项前都有个括号, 但有的是中括号有的是尖括号,还有
一种圆括号。 用空格键选择时可以发现,中括号里要么是空,要么是"*",而尖括号里可以是空,"*"和
"M"这表示前者对应的项要么不要,要么编译到内核里;后者则多一样选择,可以编译成模块。而圆括号
的内容是要你在所提供的几个选项中选择一项。
牐犜诒嘁肽诤说墓程中,最烦杂的事情就是这步配置工作了,很多新手都不清楚到底该如何选取这些
选项。实际上在配置时,大部分选项可以使用其缺省值,只有小部分需要根据用户不同的需要选择。选
择的原则是将与内核其它部分关系较远且不经常使用的部分功能代码编译成为可加载模块,有利于减小
内核的长度,减小内核消耗的内存,简化该功能相应的环境改变时对内核的影响;不需要的功能就不要
选;与内核关心紧密而且经常使用的部分功能代码直接编译到内核中。下面就让我们对常用的选项分别
加以介绍。
8.1. Code maturity level optio 牐牬码成熟等级。此处只有一项:prompt for development and/or incomplete code/drivers,如果
你要试验现在仍处于实验阶段的功能,比如khttpd、IPv6等,就必须把该项选择为Y了;否则可以把它选
择为N。
牐8.2. Loadable module su ort
牐牰阅?榈闹С帧U饫锩嬗腥项:
牐燛nable loadable module su ort:除非你准备把所有需要的内容都编译到内核里面,否则该项应
该是必选的。
牐燬et version information on all module symbols:可以不选它。
牐燢ernel module loader:让内核在启动时有自己装入必需模块的能力,建议选上。
8.3. Proce or type and features
牐燙PU类型。内容蛮多的,不一一介绍了,有关的几个如下:
牐燩roce or family:根据你自己的情况选择CPU类型。
牐燞igh Memory Su ort:大容量内存的支持。可以支持到4G、64G,一般可以不选。
牐燤ath emulation:协处理器仿真。协处理器是在386时代的宠儿,现在早已不用了。
牐燤TTR su ort:MTTR支持。可不选。
牐燬ymmetric multi-proce ing su ort:对称多处理支持。除非你富到有多个CPU,否则就不用选了
牐8.4. General setup
牐犝饫锸嵌宰钇胀ǖ囊恍┦粜越行设置。这部分内容非常多,一般使用缺省设置就可以了。下面介绍
一下经常使用的一些选项:
牐燦etworking su ort:网络支持。必须,没有网卡也建议你选上。
牐燩CI su ort:PCI支持。如果使用了PCI的卡,当然必选。
牐燩CI acce mode:PCI存取模式。可供选择的有BIOS、Direct和Any,选Any吧。
牐燬u ort for hot-pluggabel devices:热插拔设备支持。支持的不是太好,可不选。
牐燩CMCIA/CardBus su ort:PCMCIA/CardBus支持。有PCMCIA就必选了。
牐燬ystem V IPC
牐燘SD Proce Accounting
牐燬ysctl su ort:以上三项是有关进程处理/IPC调用的,主要就是System V和BSD两种风格。如果你
不是使用BSD,就按照缺省吧。
牐燩ower Management su ort:电源管理支持。
牐燗dvanced Power Management BIOS su ort:高级电源管理BIOD支持。
牐8.5. Memory Technology Device(MTD)
牐燤TD设备支持。可不选。
牐8.6. Parallel port su ort
牐牬口支持。如果不打算使用串口,就别选了。
牐8.7. Plug and Play configuration
牐牸床寮从弥С帧K淙籐inux对即插即用目前支持的不如Windows好,但是还是选上吧,这样你可以拔
下鼠标之类的体验一下Linux下即插即用的感觉。
牐8.8. Block devices
牐牽樯璞钢С帧U飧鼍偷谜攵宰约旱那榭隼囱×耍简单说明一下吧:
牐燦ormal PC flo y disk su ort:普通PC软盘支持。这个应该必选。
牐燲T hard disk su ort:
牐燙ompaq SMART2 su ort:
牐燤ulex DAC960/DAC1100 PCI RAID Controller su ort:RAID镜像用的。
牐燣oo ack device su ort:
牐燦etwork block device su ort:网络块设备支持。如果想访问网上邻居的东西,就选上。
牐燣ogical volume manager(LVM)su ort:逻辑卷管理支持。
牐燤ultiple devices driver su ort:多设备驱动支持。
牐燫AM disk su ort:RAM盘支持。
牐8.9. Networking optio 牐犕络选项。这里配置的是网络协议。内容太多了,不一一介绍了,自己看吧,如果你对网络协议有
所了解的话,应该可以看懂的。如果懒得看,使用缺省选项(肯定要选中TCP/IP networking哦)就可以
了。让我们看看,TCP/IP、ATM、IPX、DECnet、A letalk……支持的协议好多哦,IPv6也支持了,Qos
and/or fair queueing(服务质量公平调度)也支持了,还有kHTTPd,不过这些都还在实验阶段。
牐8.10. Telephony Su ort
牐牭缁爸С帧U飧鍪鞘裁炊东?让我查查帮助,原来是Linux下可以支持***卡,这样你就可以在IP上
使用普通的***提供语音服务了。记住,***卡可和modem没有任何关系哦。
牐8.11. ATA/IDE/MFM/RLL su ort
牐犝飧鍪怯泄馗髦纸涌诘挠才/光驱/磁带/软盘支持的,内容太多了,使用缺省的选项吧,如果你使用
了比较特殊的设备,比如PCMCIA等,就到里面自己找相应的选项吧。
,比如PCMCIA等,就到里面自己找相应的选项吧。
8.12. SCSI su ort
牐燬CSI设备的支持。我没有SCSI的设备,所以根本就不用选,如果你用了SCSI的硬盘/光驱/磁带等设
备,自己找好了。
牐8.13. IEEE 1394(FireWire)su ort
牐犝飧鍪鞘裁矗康桶姹镜拿挥屑过,看看帮助再说。原来是要Fireware硬件来提高串行总线的性能,
我没有,不选了。
牐8.14. I2O device su ort
牐犝飧鲆膊磺宄,帮助里说是这个需要I2O接口适配器才能支持的,在智能I ut/Output(I2O)体系
接口中使用,又是要硬件,不选了。
牐8.15. Network device su ort
牐犕络设备支持。上面选好协议了,现在该选设备了,可想而知,内容肯定多得很。还好还好,里面
大概分类了,有ARCnet设备、Ethernet(10 or 100 Mbit)、Ethernet(1000Mbit)、Wirele LAN
(non-hamradio)、Token Ring device、Wan interfaces、PCMCIA network device su ort几大类。
我用的是10/100M的以太网,看来只需要选则这个了。还是10/100M的以太网设备熟悉,内容虽然多,一
眼就可以看到我所用的RealTeck RTL-8139 PCI Fast Ethernet Adapter su ort,为了免得麻烦,编译
到内核里面好了,不选M了,选Y。耐心点,一般说来你都能找到自己用的网卡。如果没有,你只好自己
到厂商那里去要驱动了。
牐8.16. Amateur Radio su ort
牐犛忠桓霾欢的,应该是配置业余无线广播的吧,没有,不要了。
牐8.17. IrDA(infrared)su ort
牐犝飧鲆红外支持,免了。
牐8.18. ISDN su ystem
牐犎绻你使用ISDN上网,这个就必不可少了。自己看着办好了。
牐8.19. Old CD-ROM drivers(not SCSI、not IDE)
牐犠龅目烧嬷艿剑原来那些非SCSI/IDE口的光驱谁还在用啊,自己选吧,反正我是用的IDE的CD-ROM,
不选这个。
牐8.20. Character devices
牐犠址设备。这个内容又太多了,先使用缺省设置,需要的话自己就修改。把大类介绍一下吧:
牐營2C su ort:I2C是Phili 极力推动的微控制应用中使用的低速串行总线协议。如果你要选择下面
的Video For Linux,该项必选。
牐燤ice:鼠标。现在可以支持总线、串口、PS/2、C&am T 82C710 mouse port、PC110 digitizer pad,
自己根据需要选择。
牐燡oysticks:手柄。即使在Linux下把手柄驱动起来意义也不是太大,游戏太少了。
牐燱atchdog Cards:虽然称为Cards,这个可以用纯软件来实现,当然也有硬件的。如果你把这个选中
,那么就会在你的/dev下创建一个名为watchdog的文件,它可以记录你的系统的运行情况,一直到系统
重新启动的1分钟左右。有了这个文件,你就可以恢复系统到重启前的状态了。
牐燰ideo For Linux:支持有关的音频/视频卡。
牐燜tape, the flo y tape device driver:
牐燩CMCIA character device su ort:
牐8.21. File systems
牐犖募系统。内容又太多了,老法子,在缺省选项的基础上进行修改。介绍以下几项:
牐燪uota su ort:Quota可以限制每个用户可以使用的硬盘空间的上限,在多用户共同使用一台主机
的情况中十分有效。
牐燚OS FAT fs su ort:DOS FAT文件格式的支持,可以支持FAT16、FAT32。
牐營SO 9660 CD-ROM file system su ort:光盘使用的就是ISO 9660的文件格式。
牐燦TFS file system su ort:ntfs是NT使用的文件格式。
牐/proc file system su ort:/proc文件系统是Linux提供给用户和系统进行交互的通道,建议选上
,否则有些功能没法正确执行。
牐牷褂辛硗馊个大类都规到这儿了:Network File Systems(网络文件系统)、Partition Types(分
区类型)、Native Language Su ort(本地语言支持)。值得一提的是Network File Systems里面的两
种:NFS和SMB分别是Linux和Windows相互以网络邻居的形式访问对方所使用的文件系统,根据需要加以
选择。
牐8.22. Co ole drivers
牐牽刂铺ㄇ动。一般使用VGA text co ole就可以了,标准的80*25的文本控制台。
牐8.23. Sound
牐犐卡驱动。如果你能在列表中找到声卡驱动那自然最好,否则就试试OSS了。
牐8.24. USB su rot
牐燯SB支持。很多USB设备,比如鼠标、调制解调器、打印机、扫描仪等,在Linux都可以得到支持,根
据需要自行选择。
牐8.25. Kernel hacking
牐犈渲昧苏飧觯即使在系统崩溃时,你也可以进行一定的工作了。普通用户是用不着这个功能的。
牐犠芩闩渲猛炅耍现在存盘退出,当然你也可以把现在的配置文件保存起来,这样下次再配置的时候就省力气了。
三 编译过程牐
在繁杂的配置工作完成以后,下面你就可以自己到杯茶耐心等候了。与编译有关的命令有如下几个:
#make clean --删除不必要的模块和文件
#make bzImage --开始编译系统内核
#make modules --开始编译外挂模块
#make modules_i tall --***编译完成的模块
下面是生成配置
#make i tall
这里如果出现 "NO MODULE BUSLOGIC FOUND",解决方法
第1种方法:
编辑文件 /etc/modules.conf
将"alias scsi hostadapter BusLogic"这行注释掉,
即#alias scsi hostadapter BusLogic
保存 /etc/modules.conf,退出
# make i tall
第2种方法:
手动添加启动项
#depmod -a
#cp /usr/src/linux/System.map /boot/System.map-2.6.13
#cp /usr/src/linux/arch/i386/bzImage /boot/vmlinuz-2.6.13
四 运行内核的常见问题
1. 编译完后不启动,报以下错误:
VFS: Ca ot open root device "LABEL=/" or 0.0
>; Please a end a correct "root=" boot option
>; kernel panic: VFS: Unable to mount root fs
如果是上面的错误,请确认你把如下选项配置进kernel
(1) 如果/使用了EXT3 文件系统,在内核中要加入EXT3的支持
(2)如果是IDE的硬盘必须要IDE的驱动加载
(3)在block devices--RAM disk su ort 中选取 Initial disk(initrd) su ort,有时在mount / 之前
需要加载一些模块,这些modules 被做到一个镜像文件中--kernel-ver.img 中,这个文件位于/boot.举个例子,如果EXT3 的是以模块加载的话,在mount / 时就需要用到它,所以系统就在initrd.kernel-ver.img 中寻找它.
使用命令 mkinitrd initrd.kernel-ver.img kernel-ver 可以生成initrd.kernel-ver.img
2. 系统启动过程中加载iptables时报错的处理方法
修改/etc/rc.sysinit文件:
将其中所有的/proc/ksyms替换为/proc/kallsyms。
将其中所有的/proc/sys/kernel/modprobe 替换为/ in/modprobe
在文件中mount -f /proc这一句下添加mount -f /sys
在文件中的action $"Mounting proc filesystem: " mount -n -t proc /proc /proc 这一句的下面添加 action $"Mounting sysfs filesystem: " mount -n -t sysfs /sys /sys
修改/etc/fstab文件:
加入none /sys sysfs defaults 0 0
修改/etc/init.d/halt文件:
将halt_get_remaining函数内的awk '$2 ~ /^\/$|^\/proc|^\/dev/{next}改为
awk '$2 ~ /^\/$|^\/proc|^\/sys|^\/dev/{next}
创建目录:
mkdir /sys
然后重启机器,模块的问题应该解决的差不多了。
到这里编译工作顺利结束了.以上是本人在编译内核过程中遇到的问题以及解决方法,有些问题没有遇到,就没有写进去,希望大家给予补充指正,充分弘扬Linux精神!!!
3.RPM问题
进入编译好的内核后,与RPM相关的命令有些不能使用,并出现下列错误:
rpmdb: unable to join the environment
error: db4 error(11) from dbenv->open: Resource temporarily unavailable
error: ca ot open Packages index using db3 - Resource temporarily unavailable (11)
error: ca ot open Packages database in /var/lib/rpm
no packages
解决方法是执行“export LD_ASSUME_KERNEL=2.2.25”命令,也可以将其写入/etc/bashrc。
注本文引用文章:
(1)[url=http://www.linuxfa .org/nuke/mo]http://www.linuxfa .org/nuke/mo[/url] ... ewtopic&am t=80658
(2)[url=http://www.icwin.net/ShowArtitle.a ?art_id=10&am cat_id=16]http://www.icwin.net/ShowArtitle.a ?art_id=10&am cat_id=16[/url]
(3)[url=http://www.linuxfa .org/nuke/mo]http://www.linuxfa .org/nuke/mo[/url] ... topic&am =4409655
[ 本帖最后由 e2agle 于 2006-3-28 16:14 编辑 ] 下载地址
ed2k://|file|Base_SPB155.md5|418|099FDAFDC400AF42FB67BC5BF0F48709|h=5Y6IRQQV4GZALBQ6WM6K2TJ4TWKC7PTR|/
ed2k://|file|Base_SPB155_lice e.lic|4417|9B199204E91D2EDDB92F735BF4252867|h=5QZV3ZHIWSXFEU6X4BOCFBFMEQDSVEAT|/
ed2k://|file|Base_SPB155_lnx86_1of5.tar|385138176|D910778AE0ECC61737302C76E6057ABC|h=MC5HMZP2PW3OJBJTWEAHFVUHTOYHVVEK|/
ed2k://|file|Base_SPB155_lnx86_2of5.tar|559300096|523E2131409905281E6B5258FACBBA15|h=N2Q4V4FWNYBC3QOETLZRBQQO6GHOTOTT|/
ed2k://|file|Base_SPB155_lnx86_3of5.tar|562261504|F50832E3CFFE58B7FB63393DADECC171|h=MQ6HHIDBHRHEJOOEGK6DZVK4GYGVISSS|/
ed2k://|file|Base_SPB155_lnx86_4of5.tar|556144640|0CDBFA4E44044B5092FD814414EE6D5C|h=6IULH7ZJI4GQPAKNOY4DYOQD74PLNKNE|/
ed2k://|file|Base_SPB155_lnx86_5of5.tar|18953728|EEA2EF952BAC328A44807836CDB7555B|h=ZRNRPB43LVWHPGQJXSY64TPK5HGY3Z7D|/
_________________
SPB15.5的***(libc要有低于2.3.5的版本)
cd cdrom1/E024_SPB155_ln86_1of5
./SETUP.SH
Specify path of i tall directory [OR type [RETURN] to exit]: 输入/opt/ 出现 Directory /opt/ does not exist. Create? [y/n]: y
Do you want to use I tallScape [y/n]:n
Specify path of i tall directory [OR type [RETURN] to exit]: 回车
cd /opt/ /i tall/bin.lnx86
./softload
开始***
选1-1-2-cdrom1/E024_SPB155_ln86_1of5
Please pre y (yes) or n (no) : no 选
4) Cadence Catalog
再选a
再选y
Your package selectio require SPB155 lnx86 P/N 356-73303-0102 CDROM # 2.
1) 2) 3) SPB155 lnx86 P/N 356-73303-0102 CDROM # 2 already mounted on /home/chenqs/cdrom1/E024_SPB155_ln86_1of5, continue. 4) Change CD-ROM mount point. m) Main Menu
Type your choice: 选责4出现
You must now identify where the CD-ROM is mounted. 1) Local (mounted to this machine)
在选1出现
Specify the CD-ROM mount point 1) /cdrom 2) Other
选2写入你2盘的位置就ok了。装好后
cd /opt/ /i tall
ln -s tools.lnx86 tools
以候运行
空格 .空格 bashrc就可以了
allegro &am allegro_design_entry_HDL &am rojmgr &am 用于起动程序.
Cadence.Allegro.v13.6 之后就改名叫PSD了,后来又改名叫SPB.
fc4 的tar和***不兼容会出The following tar errors were detected:
装过程是
./SETUP.SH
1)装载可供使用的产品
你必须现在识别CD-ROM在什么地方被***。 1)本地(***到这台机器) 2)远程(***到另一个机器) m)主要的菜单 h)帮助 打出你的选择: [ 1 ]
规定CD-ROM***点 1) / cdrom 2)其它 m)主要的菜单 )以前的菜单 h)帮助 打出你的选择: [ 2 ]
从CD#1摘录***信息。
你想要察看自述文件吗?
请压y (是)或者n (没有): n
***信息是在什么地方? 1) (难以获得的选择)工作秩序 2)电子邮件文件 3)磁带 4)计算机辅助设计目录 5)文件目录 h)帮助 )以前的菜单 q)退出 打出你的选择: [ 4 ]
a)所有上述
n)没有上述
p)以前的菜单
打出你的选择( a,n,p,1-3,2 5 9 ... ):a
你不有选择任何产品。
正确的这吗? [ y与n ]请压y (是)或者n (没有):
你的选择是正确的吗? [ y与n ]
请压y (是)或者n (没有) :y
产生详尽的设施数据...
确定可供使用的盘空间
确定需要的盘空间
如果出SL-13是:***选择的不足的盘空间。
装好后
ln -s tools.lnx86 tools
/opt/ /tools/pcb/bin/allegro.exe
我的bashrc如下
# Cadence PSD environment icq 111290069
export CDS_INST_DIR=/opt/ export CDS_LIC_FILE=$CDS_INST_DIR/share/cadence.lice e
export CDS_DIR=$CDS_INST_DIR
export CONCEPT_INST_DIR=$CDS_DIR
export CDS_SITE=$CDS_DIR/share/local/
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CONCEPT_INST_DIR/tools/lib
export CDSDOC_PROJECT=/CDS_INST_DIR/doc
PATH=/opt/ /tools/jre/bin:$CONCEPT_INST_DIR/tools/bin:$CONCEPT_INST_DIR/tools/pcb/bin:$CONCEPT_INST_DIR/tools/fet/bin:$PATH
由于接触和使用较早等原因,国内的Protel用户为数众多,他们在选择Cadence高速PCB解决方案的同时,都面临着如何将手头的Protel设计移植到Cadence PCB设计软件中的问题。
转到linux下做PCB
由于接触和使用较早等原因,国内的Protel用户为数众多,他们在选择Cadence高速PCB解决方案的同时,都面临着如何将手头的Protel设计移植到Cadence PCB设计软件中的问题。
在这个过程当中碰到的问题大致可分为两种:一是设计不很复杂,设计师只想借助Cadence CCT的强大自动布线功能完成布线工作;二是设计复杂,设计师需要借助信噪分析工具来对设计进行信噪仿真,设置线网的布线拓扑结构等工作。
对于第一种情况,要做的转化工作比较简单,可以使用Protel或Cadence提供的Protel到CCT的转换工具来完成这一工作。对于第二种情况,要做的工作相对复杂一些,下面将这种转化的方法作一简单的介绍。
[email]chenqs@clo.com.cn[/email]
Cadence信噪分析工具的分析对象是Cadence Allegro的brd文件,而Allegro可以读入合乎其要求的第三方网表,Protel输出的Telexis格式的网表满足Allegro对第三方网表的要求,这样就可以将Protel文件注入Allegro。
这里有两点请读者注意。首先,Allegro第三方网表在$PACKAGE段不允许有“.”;其次,在Protel中,我们用BasName[0:N]的形式表示总线,用BasName[x]表示总线中的一根信号,Allegro第三方网表中总线中的一根信号的表示形式为Bas NameX,读者可以通过直接修改Protel输出的Telexis网表的方法解决这些问题。
Allegro在注入第三方网表时还需要每种类型器件的设备描述文件Device.txt文件,它的格式如下:
Package: package type
Cla : cla type
Pincount: total pi umber
Pinused: ...
其中常用的是PACKAGE,CLASS,PINCOUNT这几项。PACKAGE描述了器件的封装,但Allegro在注入网表时会用网表中的PACKAGE项而忽略设备描述文件中的这一项。CLASS确定器件的类型,以便信噪分折,Cadence将器件分为IC,IO,DISCRETE三类。PINCOUNT说明器件的管脚数目。对于大多数器件,Device.txt文件中包含有这三项就足够了。
有了第三方网表和设备描述文件,我们就可以将Protel中原理图设计以网表的形式代入到Cadence PCB设计软件中,接下来,设计师就可以借助Cadence PCB软件在高速高密度PCB设计方面的强大功能完成自己的设计。
如果已经在Protel作了PCB布局的工作,Allegro的script功能可以将Protcl中的布局在Allegro中重现出来。在Protel中,设计师可以输出一个Place &am Pick文件,这个文件中包含了每个器件的位置、旋转角度和放在PCB顶层还是底层等信息,可以通过这个文件很方便的生成一个Allegro的script文件,在Allegro中执行这个script就能够重现Protel中的布局了,下面给出了完成Place &am Pick文件到Allegro Script文件转化的C++代码,笔者使用这段代码,仅用了数分钟就将一个用户有800多个器件的PCB板布局在Allegro重现出来。
FILE *fp1, *fp2;
::AfxMe ageBox("hello");
fp1=fopen("pick.txt", "rt");
if (fp1==NULL) ::AfxMe ageBox("Can not open the file!!!");
fp2=fopen("place.txt","wt");
if (fp2==NULL) ::AfxMe ageBox("Can not create the file!!!");
char refdes[5], Pattern[5];
float midx,midy,refx,refy,padx,pady,rotatio char tb[1];
char tmp='"';
fprintf(fp2,"%s ", "# Allegro script");
fprintf(fp2,"%s ", "version 13.6");
fprintf(fp2,"%s ", "place refdes");
while (!feof(fp1)) {
fscanf(fp1,"%s", refdes);
fscanf(fp1,"%s", Pattern);
fscanf(fp1,"%f", &am midx);
fscanf(fp1,"%f", &am midy);
fscanf(fp1,"%f", &am refx);
fscanf(fp1,"%f", &am refy);
fscanf(fp1,"%f", &am adx);
fscanf(fp1,"%f", &am ady);
fscanf(fp1,"%s", tb);
fscanf(fp1,"%f", &am rotation);
fprintf(fp2, "fillin %c%s%c ",tmp,refdes,tmp);
if (rotation!=0) {
fprintf(fp2, "rotate ");
fprintf(fp2, "iangle %f ", rotation);
char yy=tb[0];
if (yy!='T') fprintf(fp2, "pop mirror ");
fprintf(fp2, "pick %f %f ", padx,pady);
fprintf(fp2, "next ");
fprintf(fp2, "done");
fclose(fp1);
fclose(fp2);
以上简单介绍了Protel到 SPB152转化的方法,希望能对读者的设计工作有所帮助。'
[[i] 本帖最后由 wheel 于 2006-7-7 12:19 编辑 [/i]]
__________________________________
郵政編碼:100054
地址:中國 北京市宣武區廣安門南街48號中彩大廈
5层509室
010-80900674 没人理?
[url=http://www.wudilong.com/ /forumdi lay.php?fid=53&am id=GFOpqM]http://www.wudilong.com/ /forumdi lay.php?fid=53&am id=GFOpqM[/url]
__________________________________
郵政編碼:100054
地址:中國 北京市宣武區廣安門南街48號中彩大廈
5层509室
010-80900674 呵呵,终于搞完了,把它发到一个贴子中来,做了一些修改……其中还有一些错误,希望大家指正,偶好修改!!!
——————————————————————————————————
《我也来学做嵌入式Linux系统V0.1》
作者:九贱
E-mail:kendo999@sohu.com
个人站点:[url=http://www.skynet.org.cn]www.skynet.org.cn[/url]
___________________________________________________
第一章 前言
本文的目的,是讲述嵌入式Linux系统的建立、开发的一般过程。制作一个小型的Linux的系统,可以移植至其它硬盘、软盘、优盘、flash rom……
关于作者 九贱,E名kendo,喜欢网络入侵技术、防火墙、入侵检测技术及网络技术,对Linux也颇感兴趣,想认识有共同爱好的朋友。最近闲暇,把一些学过的东西写下来,总结总结,以作备忘这需。已完成的有《网络入侵检测设计与Snort2.2源码分析》和这篇《我也来学做嵌入式Linux》。正在进行中的有《Windows防火墙技术实现大全》和《Linux防火墙实现及源码分析》。大家可以在CU上,或者是到我的小站[url=http://www.skynet.org.cn]www.skynet.org.cn[/url]上与我交流
做一个嵌入式Linux系统究竟要做哪些工作 做一个嵌入式Linux系统究竟需要做哪些工作?也就是本文究竟要讲述哪些内容?我先介绍一个脉络,可以做为我们后面工作的一个总的提纲:
第一步、建立交叉编译环境 没有交叉开发经验的读者,可能一时很难接受这个概念。首先,要明白两个概念:一般我们工作的机器,称为开发机、主机;我们制作好的系统将要放到某台机器,如手机或另一台PC机,这台机我们称为目标主机。
我们一般开发机上已经有一套开发工具,我们称之为原生开发套件,我们一般就是用它们来写程序,那么,那什么又是交叉编译环境呢?其实一点也不神秘,也就是在开发机上再***一套开发工具,这套开发工具编译出来的程序,如内核、系统工作或者我们自己的程序,是放在目标主机上运行的。
那么或许有初学者会问,直接用原生开发工具为目标主机编译程序不就完了?至少我当初是这么想的。一般来说,我们的开发机都是X86平台,原生开发套件开发的工具,也针对X86平台,而我们的目标主机可能是PowerPC、IXP、MIPS……所以,我们的交叉编译环境是针对某一类具体平台的。
一般来讲,交叉开发环境需要二进制工具程序、编译器、C链接库,嵌入式开发常用的这三类软件是:
Binutils
当然,GNU包含的工具套件不仅于此,你还要以根据实际需要,进行选择
第二步、编译内核 开发工具是针对某一类硬件平台,内核同样也是。这一步,我们需要用第一步中建立的工具,对内核进行编译,对于有内核编译经验的人来说,这是非常简单的;
第三步、建立根文件系统 也就是建立我们平常看到的bin、dev、proc……这一大堆目录,以及一些必备的文件;另外,我们还需要为我们的目标系统***一些常用的工具软件,如ls、ifconfig……当然,一个办法是找到这些工具的源代码,用第一步建立的交叉编译工具来编译,但是这些软件一是数量多,二是某些体积较大,不适合嵌入式系统,这一步,我们一般都是用busybox来完成的,包括系统引导软件init; 最后,我们为系统还需要建立初始化的引导文件,如inittab……
第四步、启动系统 在这一步,我们把建立好的目标、文件、程序、内核及模块全部拷贝到目标机存储器上,如硬盘。然后为系统***bootloader,对于嵌入式系统,有许多引导程序可供我们使用。不过它们许多都有硬件平台的限制。当然,如果你是工作在X86,可以直接用lilo来引导,事实上,本文就是采用的lilo。 做到这一步,将目标存储设备挂上目标机,如果顺利,就可以启动系统了。 当然,针对某些特别的平台,不能像硬盘这样拷贝了,需要读卡器、烧录……但是基本的方法是相通的!
第五步、优化和个性化系统 通过前四步,我们已经得到了一个可以正常工作的系统。在这一步里,就是发挥你想像的时候了……
本文的工作环境
项目根目录/home/kendo/project ------>;我将它指定至PATH:$PRJROOT
子目录及说明
目录 内容
bootloader 目标板的引导加载程序,如lilo等
build-tool 建立交叉编译平台的工具源码
debug 调试工具及所有相关包
doc 项目中用到的所有文档
image 编译好的内核映像,以及根文件系统
kernel 各个版本的Linux内核源码
rootf 制作好的根文件系统
sysa 目标板将要用到的系统应用系统,比如thttpd,udhcpd等
tm 存放临时文件
tool 编译好的跨平台开发工具链以及C链接库
工作的脚本
#!/usr/bin
export PROJECT=skynet
export PRJROOT=/home/${PROJECT}
export TARGET=i386-linux
export PREFIX=${PRJROOT}/tools
export TARGET_PREFIX=${PREFIX}/${TARGET}
export PATH=${PREFIX}/bin:/bin:/ in:/usr/bin:/usr/ in
cd $PRJROOT
第二章 建立交叉编译环境
在CU中发表的另一篇同名的贴子里,我讲述了一个全手工创建交叉编译环境的方法。目前,创建交叉编译环境,包括建立根文件,一般来讲,有两种方法:
手功创建
可以得到最大程序的个性化定制,缺点是过程繁杂,特别是极易出错,注意这个“极”字,包括有经验的开发人员;
自动创建
无它,方便而。
因为前一篇文章中,已经讲述了全手工创建交叉编译环境的一般性方法,本文就不打算再重复这个步骤了,感兴趣的朋友,可以再去搜索那篇贴子,提醒一点的就是,在准备工具链的时候,要注意各个工具版本之间的搭配、每个工具需要哪些补丁,我建议你在google上针对这两项搜索一下,准备一个清单,否则……
本章要讲述的是自动创建交叉编译环境的方法。目标,针对商业硬件平台,厂家都会为你提供一个开发包,我用过XX厂家的IXP425和MIPS的,非常地方便,记得我第一次接触嵌入式开发,拿着这个开发包自动化创建交叉编译环境、编译内核、建立根文件系统、创建Ram Disk,我反复做了三四次,结果还不知道自己究竟做了些什么,呵呵,够傻吧……
所以,建议没有这方面经验的读者,还是首先尝试一下手工创建的方法吧,而本章接下来的内容,是送给曾经被它深深伤害而不想再次去亲历这项工作而又想提高交率而又在通用平台上工作没有商业开发包的朋友。
建立交叉开发工具链
准备工具:
buildroot-0.9.27.tar.tar
只需要一个软件?对,其它的不用准备了,buildroot事实上是一个脚本与补丁的集合,其它需要用到的软件,如gcc、uClibc,你只需在buildroot中指明相应的版本,它会自动去给你下载。
事实上,buildroot到网上去下载所需的所有工作是需要时间的,除非你的带宽足够,否则下载软件时间或许会占去80%,而我在做这项工作之间,所需的工作链全部都在我本地硬盘上,我解压开buildroot后,新建dl文件夹,将所有工具源码的压缩包拷贝进去,呵呵,buildroot就不用去网上下载了。
我的软件清单:
Linux-libc-headers-2.4.27.tar.bz2
Gcc-3.3.4.tar.bz2
binutils 2.15.91.0.2.tar.bz2
uClibc 0.9.27.tar.bz2
genext2fs_1.3.orig.tar.gz
ccache-2.3.tar.gz
将它拷贝到${PRJROOT}/build-tools下,解压
[root@skynet build-tools]# tar jxvf buildroot-0.9.27.tar.tar
[root@skynet build-tools]#cd buildroot
配置它:
[root@skynet build-tools]#make menuconfig
Target Architecture (i386) --->; 选择硬件平台,我的是i386
Build optio --->; 编译选项
这个选项下重要的是(${PRJROOT}/tools) Toolchain and header file location?编译好的工具链放在哪儿?
如果你像我一样,所有工具包都在本地,不需它到网上自动下载,可以把wget command选项清空;
Toolchain Optio --->; 工具链选项
--- Kernel Header Optio 头文件它会自动去下载,不过应该保证与你将要用的内核是同一个版本;
[] Use the daily a hot of uClibc? 使用最近的uClibc的 a hot
Binutils Version (binutils 2.15.91.0.2) ---> Binutils的版本
GCC compiler Version (gcc 3.4.2) ---> gcc 版本
Build/i tall c++ compiler and li tdc++?
[ ] Build/i tall java compiler and libgcj? 支持的语言,我没有选择java
[ ] Enable ccache su ort? 启用ccache的支持,它用于编译时头文件的缓存处理,用它来编译程序,第一次会有点慢,但是以后的速度可就很理想了,呵呵……
--- Gdb Optio 根据你的需要,选择gdb的支持
Package Selection for the target --->;
这一项我没有选择任意一项,因为我打算根文件系统及busybox 等工具链创建成工,手工来做。
Target Optio ---> 文件系统类型,根据实际需要选,我用的ext2;
配置完成后,编译它:
[root@skynet build-tools]#make
这一项工作是非常花时间的,我的工具包全部在本地,也花去我一小时十三分的时间,如果全要下载,我估计网速正常也要多花一两个钟头。
经过漫长的等待(事实上并不漫长,去打了几把游戏,很快过去了):
make[1]: Leaving directory `/home/skynet/build-tools/buildroot/build_i386/genext2fs-1.3'
touch -c /home/skynet/build-tools/buildroot/build_i386/genext2fs-1.3/genext2fs
[url=mailto:#-@find]#-@find[/url] /home/skynet/build-tools/buildroot/build_i386/root/lib -type f -name \*.so\* | xargs /home/skynet/tools/bin/i386-linux-uclibc-strip --remove-section=.comment --remove-section=.note --strip-u eeded 2>;/dev/null || true;
/home/skynet/build-tools/buildroot/build_i386/genext2fs-1.3/genext2fs -i 503 -b 1056 \ -d /home/skynet/build-tools/buildroot/build_i386/root -q -D target/default/device_table.txt /home/skynet/build-tools/buildroot/root_fs_i386.ext2
大功告成!!!
清点战利品
让我来看看它究竟做了哪些事情吧:
[root@skynet skynet]# cd tools
[root@skynet tools]# ls
bi in-ccache i386-linux i386-linux-uclibc include info li libexec ma usr
bin:所有的编译工具,如gcc,都在这儿了,只是加了些指定的前缀;
bin-ccache:如果在Toolchain optaion中没有选择对ccache的支持,就没有这一项了;
i386-linux:链接文件;实际指向include
i386-linux-uclibc:uclibc的相关工具;
include:供交叉开发工具使用的头文件;
info:gcc 的info文件;
lib:供交叉开发工具使用的链接库文件;
现在可以把编译工具所在目录XXX/bin添加至PATH了
测试工具链
如果你现在写一个程序,用i386-linux-gcc来编译,运行的程序会告诉你:
./test: linked agai t GNU libc
因为程序运行库会寻到默认的/lib:/usr/lib上面去,而我们目前的uclibc的库并不在那里(虽然对于目标机来讲,这是没有错的),所以,也只能暂时静态编译,试试它能否工作了。当然,你也可以在建好根文件系统后,试试用chroot……
第三章 编译内核
本章的工作,是为目标机建立一个合适的内核,对于建立内核,我想有两点值得考虑的:
1、功能上的选择,应该能够满足需要的情况下,尽量地小;
2、小不是最终目的,稳定才是;
所以,最好编译内核前有一份目标机硬件平台清单以及所需功能清单,这样,才能更合理地裁减内核。
准备工具
Linux内核源码,我选用的是Linux-2.4.27.tar.bz2
编译内核
将Linux-2.4.27.tar.bz2拷贝至${PRJROOT}/kernel,解压
#cd linux-2.4.27
//配置
# make ARCH=i386 CROSS_COMPILE=i386-linux- menuconfig
//建立源码的依存关系
# make ARCH=i386 CROSS_COMPILE=i386-linux- clean dep
//建立内核映像
# make ARCH=i386 CROSS_COMPILE=i386-linux- bzImage
ARCH指明了硬件平台,CROSS_COMPILE指明了这是交叉编译,且编译器的名称为i386-linux-XXX,这里没有为编译器指明路径,是因为我前面已将其加入至环境变量PATH。
又是一个漫长的等待……
OK,编译完成,673K,稍微大了点,要移到其它平台,或许得想办法做到512以下才好,回头来想办法做这个工作。
***内核
内核编译好后,将内核及配置文件拷贝至${PRJROOT}/images下。
# cp arch/i386/boot/bzImage ${PRJROOT}/images/bzImage-2.4.27-rmk5
# cp vmlinux ${PRJROOT}/images/vmlinux-2.4.27-rmk5
# cp System.map ${PRJROOT}/images/System-2.4.27-rmk5
# cp .config ${PRJROOT}/images/2.4.27-rmk5
我采用了后缀名的方式重命名,以便管理多个不同版本的内核,当然,你也可以不用这样,单独为每个版本的内核在images下新建对应文件夹也是可行的。
***内核模块
完整内核的编译后,剩下的工作就是建立及***模块了,因为我的内核并没有选择模块的支持(这样扩展性差了一点,但是对于我的系统来说,功能基本上定死了,这样影响也不太大),所以,剩下的步骤也省去了,如果你还需要模块的支持,应该:
//建立模块
#make ARCH=i386 CROSS_COMPILE=i386-linux- modules
//***内核模块至${PRJROOT}/images
#make ARCH=i386 CROSS_COMPILE= i386-linux- \
>;INSTALL_MOD_PATH=${PRJROOT}/images/modules-2.4.18-rmk5 \
>;modules_i tall
最后一步是为模块建立依存关系,不能使用原生的depmod来建立,而需要使用交叉编译工具。需要用到busybox中的depmod.pl脚本,很可惜,我在busybox1.0.0中,并没有找到这个脚本,所以,还是借用了busybox0.63中scripts中的depmod.pl。
将depmod.pl拷贝至${PREFIX}/bin目录中,也就是交叉编译工具链的bin目录。
#depmod.pl \
>;-k ./vmlinux –F ./System.map \
>;-b ${PRJROOT}/images/modules-2.4.27-rmk5/lib/modules >; \
>;${PRJROOT}/images/modules-2.4.27-rmk5/lib/modules/2.4.27-rmk5/modules.dep
注:后面讨论移植内核和模块内容时,我只会提到内核的拷贝,因为我的系统并没有模块的支持。如果你需要使用模块,只需按相同方法将其拷贝至相应目录即可。
附,内核编译清单
附,内核选择:
内核编译记录:
Code maturity level optio 不选
Loadable module su ort 不选
Proce or type and feature 根据实际,选择处理器类型
General setu --->;
Networking su ort
PCI su ort
(Any) PCI acce mode
PCI device name database
System V IPC
Sysctl su ort
(ELF) Kernel core (/proc/kcore) format
Kernel su ort for ELF binaries
Power Management su ort
Memory Technology Devices (MTD) ---> MTD设备,我用CF卡,不选
Parallel port su ort ---> 不选
Plug and Play configuratio ---> 我的系统用不着即插即用,不选
Block device --->;
Loo ack device su ort RAM disk su ort (4096) Default RAM disk size (NEW) Initial RAM disk (initrd) su ort Multi-device su ort (RAID and LVM) ---> 不选
Networking optio --->; 基本上都选了
ATA/IDE/MFM/RLL su ort ---> 用了默认的
Telephony Su ort ---> 不选
SCSI su ort --->; 不选
Fusion MPT device su ort --->; 不选
I2O device su ort ---> 不选
Network device su ort ---> 根据实际情况选择
Amateur Radio su ort --->; 不选 IrDA (infrared) su ort ---> 不选
ISDN su ystem ---> 不选
Old CD-ROM drivers (not SCSI, not IDE) ---> 不选
I ut core su ort ---> 不选
Character device ---> Virtual terminal Su ort for co ole on virtual terminal
Standard/generic (8250/16550 and compatible UARTs) serial su ort Su ort for co ole on serial port
Multimedia device --->; 不选
File system --->;
Kernel automounter version 4 su ort (also su orts v3)
Virtual memory file system su ort (former shm fs)
/proc file system su ort
Second extended fs su ort
Co ole driver --->;
VGA text co ole 调试时接显示器用
剩下三个都不要
Sound --->;
USB su ort ---> Kernel hacking ---> 第四章 建立根文件系统
1、建立目录
构建工作空间时,rootfs文件夹用来存放根文件系统,
#cd rootfs
根据根文件系统的基本结构,建立各个对应的目录:
# mkdir bin dev etc lib proc in tmp usr var root home
# chmod 1777 tmp
# mkdir usr/bin usr/lib usr/ in
dev etc li roc i tm usr var
# mkdir var/lib var/lock var/log var/run var/tmp
# chmod 1777 var/tmp
对于单用户系统来说,root和home并不是必须的。
准备好根文件系统的骨架后,把前面建立的文件***到对应的目录中去。
2、拷贝链接库
把uclibc的库文件拷贝到刚才建立的lib文件夹中:
# cd ${PREFIX}/lib
[root@skynet lib]# cp *-*.so ${PRJROOT}/rootfs/lib
[root@skynet lib]# cp -d *.so.[*0-9] ${PRJROOT}/rootfs/lib
3、 拷贝内核映像和内核模块
因为没有模块,所以拷贝模块就省了,
新建boot目录,把刚才建立好的内核拷贝过来
# cd /home/kendo/control-project/daq-module/rootfs/
# mkdir boot
# cd ${PRJROOT}/images
# cp bzImages-2.4.18-rmk5 /home/kendo/control-project/daq-module/rootfs/boot
4、 建立/dev下边的设备文件
在linux中,所有的的设备文件都存放在/dev中,使用mknod命令创建基本的设备文件。
mknod命令需要root权限,不过偶本身就是用的root用户,本来是新建了一个用户专门用于嵌入式制作的,不过后来忘记用了……
# mknod -m 600 mem c 1 1 # mknod -m 666 null c 1 3
# mknod -m 666 zero c 1 5
# mknod -m 644 random c 1 8
# mknod -m 600 tty0 c 4 0
# mknod -m 600 tty1 c 4 1
# mknod -m 600 ttyS0 c 4 64
# mknod -m 666 tty c 5 0
# mknod -m 600 co ole c 5 1
基本的设备文件建立好后,再创建必要的符号链接:
# ln -s /proc/self/fd fd
# ln -s fd/0 stdin
# ln -s fd/1 stdout
# ln -s fd/2 stderr
co ole fd mem ull random tderr tdi tdout tty tty0 tty1 ttyS0 zero
设备文件也可以不用手动创建,听说RedHat /dev下的脚本MAKEDEV 可以实现这一功能,不过没有试过……
基本上差不多了,不过打算用硬盘/CF卡来做存储设备,还需要为它们建立相关文件,因为我的CF在目标机器上是CF-to-IDE,可以把它们等同来对待,先看看Redhat 下边had的相关属性:
# ls -l /dev/hda
brw-rw---- 1 root disk 3, 0 Jan 30 2003 /dev/hda
# ls -l /dev/hda1
brw-rw---- 1 root disk 3, 1 Jan 30 2003 /dev/hda1
对比一下,可以看出,had类型是b,即块设备,主编号为3,次编号从0递增,根限位是
rw-rw----,即660,所以:
# mknod -m 660 hda b 3 0
# mknod -m 660 hda1 b 3 1
# mknod -m 660 hda2 b 3 2
# mknod -m 660 hda3 b 3 3
5、添加基本的应用程序
未来系统的应用程序,基本上可以分为三类:
基本系统工具,如ls、ifconfig这些……
一些服务程序,管理工具,如WEB、Telnet……
自己开发的应用程序
这里先添加基本的系统工具,有想过把这些工具的代码下载下来交叉编译,不过实在是麻烦,用BusyBox,又精简又好用……
将busybox-1.00.tar.gz下载至sysa 目录下,解压:
#tar zxvf busybox-1.00.tar.gz
#cd busybox-1.00
//进入配置菜单
#make TARGET_ARCH=i386 CROSS=i386-linux- PREFIX=${PRJROOT}/rootfs menuconfig
//建立依存关系
#make TARGET_ARCH=i386 CROSS= i386-linux- PREFIX=${PRJROOT}/rootfs dep
//编译
#make TARGET_ARCH=i386 CROSS= i386-linux- PREFIX=${PRJROOT}/rootfs
//***
#make TARGET_ARCH=i386 CROSS= i386-linux- PREFIX=${PRJROOT}/rootfs i tall
# cd ${PRJROOT}/rootfs/bin
addgrou usybox chow delgrou echo kill l mv ping rm leep
adduser chgr c deluser gre l mkdir etstat rmdir umount
ash chmod date dmesg hostname logi mount idof pwd h vi
一下子多了这么多命令……
配置busybox的说明:
A、如果编译时选择了:
Runtime SUID/SGID configuration via /etc/busybox.conf
系统每次运行命令时,都会出现“Using fallback suid method ”
可以将它去掉,不过我还是在/etc为其建了一个文件busybox.conf搞定;
B、 Do you want to build BusyBox with a Cro Compiler? (i386-linux-gcc) Cro Compiler prefix
这个指明交叉编译器名称(其实在编译时的命令行已指定过了……)
C、***选项下的(${PRJROOT}/rootfs) BusyBox i tallation prefix,这个指明了编译好后的工具的***目录。
D、静态编译好还是动态编译好?即是否选择
[ ] Build BusyBox as a static binary (no shared li )
动态编译的最大好处是节省了宝贵空间,一般来说都是用动态编译,不过我以前动态编译出过问题(其实是库的问题,不关busybox的事),出于惯性,我选择了静态编译,为此多付出了107KB的空间。
E、其它命令,根据需要,自行权衡。
6、系统初始化文件
内核启动时,最后一个初始化动作就是启动init程序,当然,大多数发行套件的Linux都使用了与System V init相仿的init,可以在网上下载System V init套件,下载下来交叉编译。另外,我也找到一篇写得非常不错的讲解如何编写初始化文件的文件, d-init,回头附在后面。不过,对于嵌入式系统来讲,BusyBox init可能更为合适,在第6步中选择命令的时候,应该把init编译进去。
#cd ${PRJROOT}/rootfs/etc
#vi inittab
我的inittal文件如下:
#指定初始化文件
::sysinit:/etc/init.d/rcS #打开一个串口,波特率为9600 ::re awn:/ in/getty 9600 ttyS0
#启动时执行的shell
::re awn:/bin/sh
#重启时动作
::restart:/ in/init
#关机时动作,卸载所有文件系统
::shutdown:/bin/umount -a –r
保存退出;
再来编写rcS脚本:
#mkdir ${PRJROOT}/rootfs/etc/init.d
#cd ${PRJROOT}/rootfs/etc/init.d
#vi rcS
我的脚本如下:
#!/bin/sh
#Set Path
PATH=/ in:/bin
export PATH
syslogd -m 60
#i tall /proc
mount -n -t proc none /proc
#rei tall root file system by read/write mode(need: /etc/fstab)
mount -n -o remount,rw /
#rei tall /proc
mount -n -o remount,rw -t proc none /proc
#set lo ip addre ifconfig lo 127.0.0.1
#set eth0 ip addre #当然,这样子做只是权宜之计,最后做的应该是在这一步引导网络启动脚本,像RedHat
#那样,自动读取所有指定的配置文件来启动
ifconfig eth0 192.168.0.68 netmask 255.255.255.0
#set route
#同样的,最终这里应该是运行启动路由的脚本,读取路由配置文件
route add default gw 192.168.0.1
#还差一个运行服务程序的脚本,哪位有现成的么?
#网卡/路由/服务这三步,事实上可以合在一步,在rcS这一步中,做一个循环,运行指定启动目录下的所有脚,先将就着这么做吧,确保系统能够正常启动了,再来写这个脚本。
#set hostname
hostname MyLinux
保存退出。
编写fstab文件
#vi fstab
我的fstab很简单:
/dev/hda1 / ext2 defaults 1 1
none /proc proc defaults 0 0
第五章 让MyLinux能够启动
前一章,我们把编译好的内核、应用程序、配置文件都拷贝至rootfs目录对应的子目录中去了,这一步,就是把这些文件移植至目标机的存储器。这里,我是先另外拿一块硬盘,挂在我的开发机上做的测试,因为我的本本用来写文档,PC机用来做开发机,已经没有另外的机器了……但是本章只是讲述一个一般性的过程,并不影响你直接在目标主机上的工作。
因为以后目标机识别硬盘序号都是hda,而我现在直接挂上去,则会是hdb、hdc……这样,***lilo时有点麻烦(虽然也可以实现)。所以我想了另一个办法:
把新硬盘挂在IDE0的primary上,进入linux后,会被认为是had;
原来主机的装Redhat的硬盘,我将它从IDE0的primary上变到了IDE1 的primary,因为它的lilo早已装好,基本上不影响系统的使用;
分区和格式化
BIOS中改为从第二个硬盘启动;也就是从我原来开发机启动,新的硬盘被识别成了had。
#fdisk /dev/hda
用d参数删除已存在的所有分区
用n参数新建一个分区,也是就/dev/hda1
格式化
#mkfs.ext2 /dev/hda1
***bootloader
因为我是X86平台,所以直接用了lilo,如果你是其这平台,当然,有许多优秀的bootloader供你选择,你只需查看其相应的说明就可以了。 编译lilo配置文件,我的配置文件名为target.lilo.conf,置于${PRJROOT}/rootfs/etc目录。内容如下所示:
boot=/dev/hda
disk=/dev/hda bios=0x80
image=/boot/bzImage-2.4.18-rmk5 label=Linux root=/dev/hda1
a end="root=/dev/hda1" read-only
//新建文件夹,为mount做新准备
#mkdir /mnt/cf
//把目标硬盘mount上来
#mount –t ext2 /dev/hdc1 /mnt/cf
回到rootfs
#cd ${PRJROOT}/rootfs
拷贝所有文件至目标硬盘
#cp –r * /mnt/cf
这样,我们所有的文件都被***至目标硬盘了,当然,它还不能引导,因为没有bootloader。使用如下命令:
# lilo -r /mnt/cf -C etc/target.lilo.conf
Warning: LBA32 addre ing a umed
Added Linux *
-r :改变根目标为/mnt/cf ,这样配置文件其实就是/mnt/cf/etc/target.lilo.conf,也就是我们先前建立的文件。
当然,完成这一步,需要lilo22.3及以后版本,如果你的版本太旧,比如Redhat9.0自带的,就会出现下面的信息:
#lilo –r /mnt/cf –C etc/target.lilo.conf
Fatal: open /boot/boot.b: No such file or directory
这时,你需要升级你的lilo,或者重新***一个。
启动系统
#umount /mnt/cf
#reboot
将BIOS改为从IDE0启动,也就是目标硬盘。如果一切顺利,你将顺利进入一个属于你的系统。
回头再来看看我们的工作空间吧
[root@skynet lib]# df /dev/hda1
Filesystem 1K-block Used Available Use% Mounted on
/dev/hda1 3953036 1628 3750600 1% /mnt/cf
总共花去了我1628KB的空间,看来是没有办法放到软盘里边去了^o^,不过一味求小,并不是我的目标。
[root@skynet skynet]# ls ${PRJROOT}
bootloader build-tool debug doc image kernel rootf ysa tm tools
这几个目录中的文件,呵呵,与本文一开头规划的一样
[root@skynet skynet]# ls build-tools/
buildroot uildroot-0.9.27.tar.tar
包含了buildroot源码及压缩包,事实上buildroot下边还包括了GNU其它工具的源码、编译文件等诸多内容,是我们最重要的一个文件夹,不过到现在它已经没有多大用处了,如果你喜欢,可以将它删除掉(不建议)。
[root@skynet skynet]# ls images
2.4.18-rmk5 zImage-2.4.18-rmk5 System-2.4.18-rmk5 vmlinux-2.4.18-rmk5
内核映像及配置文件等,如果你有模块,因为还有相应的目录
[root@skynet skynet]# ls kernel/
linux-2.4.27 linux-2.4.27.tar.bz2
内核源码及压缩包
[root@skynet skynet]# ls rootfs/ bi oot dev etc home li linuxrc roc root i tm usr var
制作好的根文件系统,重中之重,注意备份……
[root@skynet skynet]# ls sysa /
busybox-1.00 usybox-1.00.tar.gz
busybox-1.00源码包,或许你还要继续添加/删除一些命令……
[root@skynet skynet]# ls tools
bi i386-linux i386-linux-uclibc include info li man
这个也很重要,我们制作好的交叉开发工具链。如果你要继续开发程序,这个目录重要性就很高了。
其它目录暂时是空的。
第六章 完善MyLinux
关于进一步的调试,你可以在开发机上使用chroot /mnt/cf /bin/sh这样的命令,以使我们在目标根文件系统上工作。
支持多用户
因为我在编译busybox时,已经将它的多用户那一大堆命令编译了进来。现在关键是的要为其建立相应的文件;
进入原来的开发机,进入rootfs目录,切换根目录
#chroot rootfs/ /bin/sh
A、 建立/etc/pa wd文件,我的文件内容如下:
root:x:0:0:root:/root:/bin/bash
B、 建立/etc/group文件,我的文件内容如下:
root:x:0:
bin:x:1:
sys:x:2:
kmem:x:3:
tty:x:4:
tape:x:5:
daemon:x:6:
disk:x:7:
C、 为root建立密码
#pa wd root
试试用addgroup/addusr……这堆命令。然后重启,从目标硬盘上启动;从co ole口,9600登陆试试(因为我在inittab中启用了ttyS0,我未来的目标机,是没有显卡的,需要从co ole口或SSH进去管理)
MyLinux login: root
Pa word:
BusyBox v1.00 (2004.10.10-04:43+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.
成功了……
增加WEB Server
Busybox里边有httpd选项,不过我编译时并没有选择,所以还是自己来***。我使用的软件是thttpd-2.25b.tar.gz,将它移至sysa 目录下。
[root@skynet sysa ]# tar zxvf thttpd-2.25b.tar.gz
[root@skynet sysa ]# cd thttpd-2.25b
//配置
[root@skynet thttpd-2.25b]# CC=i386-linux-gcc ./configure --host=$TARGET
i386-linux-gcc -static htpa wd.o -o htpa wd -lcrypt
make[1]: warning: Clock skew detected. Your build may be incomplete.
make[1]: Leaving directory `/home/skynet/sysa /thttpd-2.25b/extras'
//拷贝至根文件目录
[root@skynet thttpd-2.25b]# cp thttpd ${PRJROOT}/rootfs/usr/ in
//trip处理
[root@skynet thttpd-2.25b]# i386-linux-strip ${PRJROOT}/rootfs/usr/ in/thttpd
剩下的,就发挥各人的想像吧……
[ 本帖最后由 platinum 于 2005-11-9 09:03 编辑 ] PDF版本及后续PDF更新版本,你可以在
[url=http://www.skynet.org.cn/viewthread.php?tid=82]http://www.skynet.org.cn/viewthread.php?tid=82[/url]
下载。
不过好像下载要先注册(我没找到如何取消这一限制)! 1.准备:
下载2.6内核linux-2.6.2-rc2.tar.gz
[url=http://www.kernel.org/pub/linux/kernel/v2.6/testing/linux-2.6.2-rc2.tar.gz]http://www.kernel.org/pub/linux/kernel/v2.6/testing/linux-2.6.2-rc2.tar.gz[/url]
不需要下载[url=http://www.kernel.org/pub/linux/kernel/v2.6/testing/patch-2.6.2-rc2.gz]http://www.kernel.org/pub/linux/kernel/v2.6/testing/patch-2.6.2-rc2.gz[/url]
这个补丁是给以前的内核版本升级到2.6.2-rc2用的
2.本人系统为redhat8.0
解压到目录/usr/src
#cp linux-2.6.2-rc2.tar.gz /usr/src
#cd /usr/src
#tar -zxvf linux-2.6.2-rc2.tar.gz
建立链接文件
#cd /usr/src
#ln –s linux-2.6.2-rc2 linux-2.6
#ln –s linux-2.6 linux
检查原代码
#cd /usr/src/linux
#make mrproper
这步是为确保原代码目录下没有不正确的.o文件及文件的相互依赖。
配置核心选项
#make menuconfig
基本上保持默认选项就可以了,但是要注意的是必须把ext2和ext3文件系统支持编进内核,否则升级内核重新启动是会有错误:
Kernel panic: No init found. Try pa ing init= option to kernel
ext2和ext3文件系统配置为:
File systems -
; Second extended fs su ort
Ext2 extended attributes
Ext2 POSIX Acce Control Lists
Ext2 Security Labels
; Ext3 journalling file system su ort
Ext3 extended attributes
Ext3 POSIX Acce Control Lists
Ext3 Security Labels
JBB (ext3) debugging su ort
编译内核
确保所有文件都处于最新的版本状态下
#make clean
编译模块
#make modules
***模块
#make modules_i tall
此时在/lib/modules下出现新内核模块文件夹2.6.2-rc2
使用新内核
#cp System.map /boot/System.map-2.6.2-rc2
#rm /boot/System.map
#ln –s /boot/System.map-2.6.2-rc2 /boot/System.map
#cp arch/i386/boot/bzImage /boot/vmlinuz-2.6.2-rc2
#rm /boot/vmlinuz
#ln –s /boot/vmlinuz-2.6.2-rc2 /boot/vmlinuz
#new-kernel-pkg –i tall –mkinitrd –depmod 2.6.2-rc2
执行完new-kernel-pkg命令后在/boot下生成新印象文件initrd-2.6.2-rc2,同时/etc/grub.conf中增加了新核心的启动项,
例如:
Tilte linux (2.6.20-rc2)
Root(hd0,0)
Kernel /boot/vmlinuz-2.6.2-rc2 ro root=LABEL=/
Initrd /boot/initrd-2.6.2-rc2
将kernel项中的root=LABEL=/ 改成 root=/dev/hda7 (/dev/hda7是本人linux的根分区),否则重启动后会有错误:
Kernel panic: No init found. Try pa ing init= option to kernel
#reboot
重启后Grub中出现2.6内核的启动项,现在就用新的核心试试吧。 国庆快到了,送给大家一篇文章作礼物吧,也作为在chinaunix这个大家庭中我曾得到过许多热心朋友的大力支持的回报,下文是我工作中总结的文档,有些核心参数的调节是为***oracle数据库而使用,无此方面应用的朋友可以跳过。
欢迎转载,但请注明出处。 一、备份重要文件
备份以下这些文件可以在系统发生错误或崩溃时,能较快速的恢复系统原来的状态。
1、备份内核和启动文件
# tar cvzf oot.tar.gz oot
2、备份系统函数头文件
# cd /usr/include
# tar cvzf linux.tar.gz linux
3、备份模块中的库文件
# cd /lib/modules
# tar cvzf 2.4.7-10.tar.gz 2.4.7-10
# tar cvzf 2.4.7-10debug.tar.gz 2.4.7-10debug
4、备份linux源码
# cd /usr/src
# tar cvzf linux-2.4.7-10.tar.gz linux-2.4.7-10
# tar cvzf linux-2.4.7-10debug.tar.gz linux-2.4.7-10debug
5、备份重要配置目录
# tar cvzf etc.tar.gz etc
二、修改核心参数(PGC2000需要)
1、修改与共享内存相关的核心参数
# cd /usr/include/linux
# vi hm.h
把 #define SHMMAX 0X2000000 /*max shared seg size(bytes)*/
改为#define SHMMAX 0Xa0000000 /*max shared seg size(bytes)*/
2、修改与信号量相关的核心参数
# cd /usr/include/linux
# vi sem.h
把 #define SEMOPM 32 /*
改为#define SEMOPM 900 /*
3、修改与消息队列有关的核心参数
# cd /usr/include/linux
# vi msg.h
找到以下三行(注释忽略):
#define MSGMNI 16
#define MSGMAX 8192
#define MSGMNB 16384
将其修改为:
#define MSGMNI 128
#define MSGMAX 131072
#define MSGMNB 20000000
4、按上面方法同样修改/usr/src/linux-2.4.7-10/include/linux下的shm.h、sem.h和msg.***件。
三、下载释放核心源代码
如果只是修改编译内核,这一步可以省去。当我们从Internet站点上下载了新的内核文件(如linux-2.4.7-12.tar.gz),这步是必须的。
1、用tar命令释放内核源代码
# cd /usr/src
# tar zxvf linux-2.4.7-12.tar.gz
文件释放成功后,在/usr/src目录下会生成一个linux子目录。其中包括了源代码。
2、将/usr/include/asm、/usr/inlude/linux、/usr/include/scsi链接到/usr/src/linux/include目录下的对应目录中。
# cd /usr/include
# rm -Rf asm linux
# 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
四、配置内核
1、删除源代码目录中残留的.o文件和其它从属文件。
# cd /usr/src/linux-2.4
# make mrproper
2、启动内核配置程序
# cd /usr/src/linux-2.4
# make xconfig
3、配置内核
Linux的内核配置程序提供了一系列配置选项。对于每一个配置选项,用户可以回答"y"、"m"或"n"。其中"y"表示将相应特性的支持或设备驱动程序编译进内核;"m"表示将相应特性的支持或设备驱动程序编译成可加载模块,在需要时,可由系统或用户自行加入到内核中去;"n"表示内核不提供相应特性或驱动程序的支持。不合理的配置可能造成内核编译失败。
五、编译内核
1、建立编译时所需的从属文件
# cd /usr/src/linux-2.4
# make dep
2、清除内核编译的目标文件
# make clean
3、编译内核
# make bzImage (注意大小写)
内核编译成功后,会在/usr/src/linux/arch/i386/boot目录中生成一个新内核的映像文件bzImage。如果用make zImage编译,内核很大的话,系统会提示你使用make bzImage命令来编译。
六、编译可加载模块
如果用户在配置内核时设置了可加载模块,则需要对这些模块进行编译,以便将来使用i mod命令进行加载。
# make modules
# make modules_i tall
编译成功后,系统会在/lib/modules目录下生成一个2.4.7-10custom子目录,里面存放着新内核的所有可加载模块。
七、启动新内核
1、将新内核和System.map文件拷贝到/boot目录下
# cp /usr/src/linux-2.4/arch/i386/boot/bzImage /boot/vmlinuz-2.4.7-10custom
# cp /usr/src/linux-2.4/System.ma /boot/System.map-2.4.7-10custom
# cd /boot
# rm -f System.ma (删除原来的连接)
# ln -s System.map-2.4.7-10custom System.ma (重新建立连接)
2、配置/etc/lilo.conf文件,在该文件中加入下面几行:
image=/boot/vmlinuz-2.4.7-10custom
label=linux-custom
initrd=/boot/initrd-2.4.7-10.img
read-only
root=/dev/hda3 (参考lilo.conf文件中现有的配置)
并把default=linux改为default=linux-custom
3、使新配置生效
# / in/lilo
4、重新启动系统
# / in/reboot
新内核如果不能正常启动,可以在LILO:提示符下启动旧内核。然后查出故障原因,重新编译新内核即可。
__________________________________
知识是经验的积累,才能是刻苦的忍耐。 针对好多Linux 爱好者对内核很有兴趣却无从下口,本文旨在介绍一种解读linux内核源码的入门方法,而不是解说linux复杂的内核机制;
一.核心源程序的文件组织:
1.Linux核心源程序通常都***在/usr/src/linux下,而且它有一个非常简单的编号约定:任何偶数的核心(例如2.0.30)都是一个稳定地发行的核心,而任何奇数的核心(例如2.1.42)都是一个开发中的核心。本文基于稳定的2.2.5源代码,第二部分的实现平台为 Redhat Linux 6.0。
2.核心源程序的文件按树形结构进行组织,在源程序树的最上层你会看到这样一些目录:
●Arch :arch子目录包括了所有和体系结构相关的核心代码。它的每一个子目录都代表一种支持的体系结构,例如i386就是关于intel cpu及与之相兼容体系结构的子目录。PC机一般都基于此目录;
●Include: include子目录包括编译核心所需要的大部分头文件。与平台无关的头文件在 include/linux
子目录下,与 intel cpu相关的头文件在include/asm-i386子目录下,而include/scsi目录则是有关 scsi设备的头文件目录;
●Init: 这个目录包含核心的初始化代码(注:不是系统的引导代码),包含两个文件main.c和Version.c,这是研究核心如何工作的一个非常好的起点。
●Mm :这个目录包括所有独立于 cpu 体系结构的内存管理代码,如页式存储管理内存的分配和释放等;而和体系结构相关的内存管理代码则位于arch/*/mm/,例如arch/i386/mm/Fault.c
●Kernel:主要的核心代码,此目录下的文件实现了大多数linux系统的内核函数,其中最重要的文件当属 sched.c;同样,和体系结构相关的代码在arch/*/kernel中;
●Drivers: 放置系统所有的设备驱动程序;每种驱动程序又各占用一个子目录:如,/block 下为块设备驱动程序,比如ide(ide.c)。如果你希望查看所有可能包含文件系统的设备是如何初始化的,你可以看drivers/block/genhd.c中的device_setup()。它不仅初始化硬盘,也初始化网络,因为***nfs文件系统的时候需要网络其他: 如, Lib放置核心的库代码; Net,核心与网络相关的代码; Ipc,这个目录包含核心的进程间通讯的代码; Fs ,所有的文件系统代码和各种类型的文件操作代码,它的每一个子目录支持一个文件系统,例如fat和ext2; Scripts, 此目录包含用于配置核心的脚本文件等。一般,在每个目录下,都有一个 .depend 文件和一个 Makefile 文件,这两个文件都是编译时使用的辅助文件,仔细阅读这两个文件对弄清各个文件这间的联系和依托关系很有帮助;而且,在有的目录下还有Readme 文件,它是对该目录下的文件的一些说明,同样有利于我们对内核源码的理解;
二.解读实战:为你的内核增加一个系统调用
虽然,Linux 的内核源码用树形结构组织得非常合理、科学,把功能相关联的文件都放在同一个子目录下,这样使得程序更具可读性。然而,Linux 的内核源码实在是太大而且非常复杂,即便采用了很合理的文件组织方法,在不同目录下的文件之间还是有很多的关联,分析核心的一部分代码通常会要查看其它的几个相关的文件,而且可能这些文件还不在同一个子目录下。体系的庞大复杂和文件之间关联的错综复杂,可能就是很多人对其望而生畏的主要原因。当然,这种令人生畏的劳动所带来的回报也是非常令人着迷的:你不仅可以从中学到很多的计算机的底层的知识(如下面将讲到的系统的引导),体会到整个操作系统体系结构的精妙和在解决某个具体细节问题时,算法的巧妙;而且更重要的是:在源码的分析过程中,你就会被一点一点地、潜移默化地专业化;甚至,只要分析十分之一的代码后,你就会深刻地体会到,什么样的代码才是一个专业的程序员写的,什么样的代码是一个业余爱好者写的。
为了使读者能更好的体会到这一特点,下面举了一个具体的内核分析实例,希望能通过这个实例,使读者对 Linux的内核的组织有些具体的认识,从中读者也可以学到一些对内核的分析方法。
以下即为分析实例:
【一】操作平台:
硬件:cpu intel Pentium II ;
软件:Redhat Linux 6.0; 内核版本2.2.5
【二】相关内核源代码分析:
1.系统的引导和初始化:Linux 系统的引导有好几种方式:常见的有 Lilo, Loadin引导和Linux的自举引导(bootsect-loader),而后者所对应源程序为arch/i386/boot/bootsect.S,它为实模式的汇编程序,限于篇幅在此不做分析;无论是哪种引导方式,最后都要跳转到 arch/i386/Kernel/setup.S, setup.S主要是进行时模式下的初始化,为系统进入保护模式做准备;此后,系统执行 arch/i386/kernel/head.S (对经压缩后存放的内核要先执行 arch/i386/boot/compre ed/head.S); head.S 中定义的一段汇编程序setup_idt ,它负责建立一张256项的 idt 表(Interrupt Descriptor Table),此表保存着所有自陷和中断的入口地址;其中包括系统调用总控程序 system_call 的入口地址;当然,除此之外,head.S还要做一些其他的初始化工作;
2.系统初始化后运行的第一个内核程序asmlinkage void __init start_kernel(void) 定义在 /usr/src/linux/init/main.c中,它通过调用usr/src/linux/arch/i386/kernel/tra .c 中的一个函数 void __init trap_init(void) 把各自陷和中断服务程序的入口地址设置到 idt 表中,其中系统调用总控程序 system_cal就是中断服务程序之一;void __init trap_init(void) 函数则通过调用一个宏 set_system_gate(SYSCALL_VECTOR,&am ystem_call); 把系统调用总控程序的入口挂在中断0x80上; 其中SYSCALL_VECTOR是定义在 /usr/src/linux/arch/i386/kernel/irq.h中的一个常量0x80; 而 system_call 即为中断总控程序的入口地址;中断总控程序用汇编语言定义在/usr/src/linux/arch/i386/kernel/entry.S中;
3.中断总控程序主要负责保存处理机执行系统调用前的状态,检验当前调用是否合法, 并根据系统调用向量,使处理机跳转到保存在 sys_call_table 表中的相应系统服务例程的入口; 从系统服务例程返回后恢复处理机状态退回用户程序; 而系统调用向量则定义在/usr/src/linux/include/asm-386/unistd.h 中 ys_call_table 表定义在 /usr/src/linux/arch/i386 kernel/entry.S 中; 同时在 /usr/src/linux/include/asm-386/unistd.h 中也定义了系统调用的用户编程接口;
4.由此可见 , linux 的系统调用也象 dos 系统的 int 21h 中断服务, 它把0x80 中断作为总的入口, 然后转到保存在 sys_call_table 表中的各种中断服务例程的入口地址 , 形成各种不同的中断服务; 由以上源代码分析可知, 要增加一个系统调用就必须在 sys_call_table 表中增加一项 , 并在其中保存好自己的系统服务例程的入口地址,然后重新编译内核,当然,系统服务例程是必不可少的。 由此可知在此版linux内核源程序;中,与系统调用相关的源程序文件就包括以下这些:
1.arch/i386/boot/bootsect.S
2.arch/i386/Kernel/setup.S
3.arch/i386/boot/compre ed/head.S
4.arch/i386/kernel/head.S
5.init/main.c
6.arch/i386/kernel/tra .c
7.arch/i386/kernel/entry.S
8.arch/i386/kernel/irq.h
9.include/asm-386/unistd.h
当然,这只是涉及到的几个主要文件。而事实上,增加系统调用真正要修改文件只有include/asm-386/unistd.h
和arch/i386/kernel/entry.S两个;
【三】 对内核源码的修改:
1.在kernel/sys.c中增加系统服务例程如下:
asmlinkage int sys_addtotal(int numdata)
int i=0,enddata=0;
while(i
enddata+=i++;
return enddata;
该函数有一个 int 型入口参数 numdata , 并返回从 0 到 numdata 的累加值; 当然也可以把系统服务例程放在一个自己定义的文件或其他文件中,只是要在相应文件中作必要的说明;
2.把 asmlinkage int sys_addtotal( int) 的入口地址加到sys_call_table表中:
arch/i386/kernel/entry.S 中的最后几行源代码修改前为:
... ...
.long SYMBOL_NAME(sys_sendfile)
.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
.long SYMBOL_NAME(sys_vfork) /* 190 */
.rept NR_syscalls-190
.long SYMBOL_NAME(sys_ni_syscall)
修改后为: ... ...
.long SYMBOL_NAME(sys_sendfile)
.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
.long SYMBOL_NAME(sys_vfork) /* 190 */
/* add by I */
.long SYMBOL_NAME(sys_addtotal)
.rept NR_syscalls-191
.long SYMBOL_NAME(sys_ni_syscall)
3. 把增加的 sys_call_table 表项所对应的向量,在include/asm-386/unistd.h 中进行必要申明,以供用户进程和其他系统进程查询或调用:
增加后的部分 /usr/src/linux/include/asm-386/unistd.h 文件如下:
... ...
#define __NR_sendfile 187
#define __NR_getpmsg 188
#define __NR_putpmsg 189
#define __NR_vfork 190
/* add by I */
#define __NR_addtotal 191
4.测试程序(test.c)如下:
#include
#include
_syscall1(int,addtotal,int, num)
int i,j;
printf("lease i ut a number\n"
while(scanf("%d",&am i)==EOF);
if((j=addtotal(i))==-1)
printf("Error occurred in syscall-addtotal();\n"
printf("Total from 0 to %d is %d \n",i,j);
对修改后的新的内核进行编译,并引导它作为新的操作系统,运行几个程序后可以发现一切正常;在新的系统下对测试程序进行编译(*注:由于原内核并未提供此系统调用,所以只有在编译后的新内核下,此测试程序才能可能被编译通过),运行情况如下:
$gcc -o test test.c
$./test
Please i ut a number
Total from 0 to 36 is 666
可见,修改成功;
而且,对相关源码的进一步分析可知,在此版本的内核中,/usr/src/linux/arch/i386/kernel/entry.S
文件中对 sys_call_table 表的设置可以看出,有好几个系统调用的服