$ cp arch/arm/configs/s5pc100_defconfig .config
这里拷贝arch/arm/configs/s5pc100_defconfig到 .config文件是选取跟我们开发板相关的代码。因为Linux支持的平台非常非常多,不仅仅是ARM处理器,当然我们编译的时候只需要编译跟我们平台相关的代码就可以了,平台相关的不需要编译,那么就有个问题,Linux系统中的源代码文件有一万多以个,面对这么庞大的文件数量,我们如何去选择呢?
其实,我们担心的问题也是写操作系统的那哥们早就担心过的问题了,只不过人家已经把这个问题帮我们解决了,我们只需进行很简单的操作,就可以选择出我们要编译的代码,具体的方法就是把相应平台的_deconfig直接拷贝到顶层目录的.config文件中,这样.config文件中就记录了我们要移植平台的平台信息,因为在配置内核时,系统会把所有的配置信息都保存在顶层目录的.config文件中。注意在第一次,进行make menuconfig时,系统会根据我们选取的平台信息自动选取相关的代码和模块,因此我们只需要进入然后再退出,选择保存配置信息就行了,系统会把这些跟我们移植平台相关的所有配置信息全部保存在顶层目录的.config文件中。
四、配置内核
$make menuconfig
注意:第一次进去,不做任何操作,直接推出,在推出时提示是否保存配置信息,一定要保存配置信息,点击“YES”。这样我们的.config中就已经保存了我们开发平台的信息。
在这个环节,我们需要关心一个问题,make menuconfig时,系统到低都做了哪些事情?为什么会出现图形化的界面?图形化的界面中的相关内容是从哪里来的?
图形化的界面当然是由一个特殊的图形库来实现的,还记得第一次make menuconfig时,系统并没有出现图形化的界面,而是报错了,并且提示我们缺少 ncurses-devel ,此时只需要按照要求安装一个libncurses5-dev就行了,sudo apt-get install libncurses5-dev,有了这个图形化库的支持,我们才能够正常显示图形化界面。
好了,图形化界面的问题解决了,那还有另外一个问题就是图形化界面里面的内容是从哪里来的?要回答这个问题,我们就要提一下Linux内核的设计思想了,Linux 内核是以模块的方式来组织这个操作系统的,那么,为什么要用模块的方式来组织呢?模块的概念又是什么呢?在此来一一回答这个问题。
Linux2.6内核的源码树目录下一般都会有两个文件:Kconfig和Makefile。分布在各目录下的Kconfig构成了一个分布式的内核配置数据库,每个Kconfig分别描述了所属目录源文件相关的内核配置菜单。每个目录都会存放功能相对独立的信息,在每个目录中会存放各个不同的模块信息,比如在/dev/char/目录下就存放了所有字符设备的驱动程序,而这些程序代码在内核中是以模块的形式存在的,也就是说当系统需要这个驱动的时候,会把这个驱动以模块的方式编译到系统的内核中,编译分为静态编译和动态编译,静态编译内核体积比动态编译的体积要大,前面已经说了每个目录下面都会有一个Kconfig的文件,我们还会问,这个文件中都存放了什么信息?前面说了,每个目录的Kconfig文件描述了所属目录源文件相关的内核配置菜单,有其特殊的语法格式,图形化界面的文字正是从这个文件中读取出来的,如果把这个文件中的相应目录文件的信息全部删除,那么在图形化界面中将看不到该模块的信息,因此也不能进行模块的配置。
在内核配置make menuconfig(或xconfig等)时,系统会自动从Kconfig中读出配置菜单,用户配置完后保存到.config(在顶层目录下生成)中。在内核编译时,主Makefile调用这个.config,(.config的重要性就体现在,它保存了我们的所有的配置信息,是我们选取源代码并且进行编译源代码的最终依据!!!)就知道了用户对内核的配置情况。上面的内容说明:Kconfig就是对应着内核的配置菜单。假如要想添加新的驱动到内核的源码中,可以通过修改Kconfig来增加对我们驱动的配置菜单,这样就有途径选择我们的驱动,假如想使这个驱动被编译,还要修改该驱动所在目录下的Makefile。因此,一般添加新的驱动时需要修改的文件有两种,即:Kconfig 和相应目录的Makefile(注意不只是两个),系统移植的重要内容就是给内核添加和删除相应的模块,因此主要修改的内核文件就是Kconfig 和相应目录的Makefile这两个文件。
五、编译内核
$make zImage
通过上述操作我们能够在 arch/arm/boot 目录下生成一个 zImage 文件,这就是经过压缩的内核镜像。
内核的编译过程是非常复杂的,注意这里的编译是静态编译,此时会执行顶层目录下的Makefile中的zImage命令,在执行的过程中,会根据当前目录的.config文件去选择编译源代码。编译内核的具体步骤比较复杂,有时间会另写文章详细描述。
六、通过tftp网络服务下载测试内核
setenv bootcmd tftp 20008000(内存地址) zImage\;go 20008000
setenv bootargs nfs nfsroot=192.168.1.199(虚拟机的ip):/source/rootfs ip=192.168.1.200(开发板的ip)init=/linuxrc(第一个要启动的用户进程) ttySAC0,115200(设置中断为串口1,波特率为:115200)
保存环境变量,复位开发板,测试是否能够正常启动(注意:在此之前应设置好需要nfs挂载的文件系统,最后才能看到效果).内核测试和启动过程也是比较复杂的,在后续的文章中会详细介绍。
第四部分:根文件系统的介绍
由本文的第一张图:Flash存储中存放文件的分布图可知,文件系统的制作和移植是系统移植的最后一道工序了,在这里首先要提几个问题:
1.什么是文件系统?
2.如何实现文件系统?
3.常用的文件系统有哪些?为什么需要这些文件系统?
下面来一一回答这些问题:
文件系统我们在日常生活中则很少听说,但是它确实存在,只是名字不叫文件系统罢了,一般叫资料库。资料库里面的文件众多,我们如何快速准确的找到我们要的那份文件呢?资料库采用了分类索引的方法来实现快速查找。类似于我们学校图书馆的管理方式,一楼可能是哲学类,二楼是社科类的,三楼是电子类的,四楼是计算机类的…………等等,我们把这种进行了分类索引的资料库叫文件系统。
对于计算机而言,文件其实就是资料数据,只能存储在物理介质上面,比如:硬盘,但是我们人不可能自己读取物理介质上的文件,或者自己把文件写入物理介质,物理介质上文件的读写只能采用程序来完成,为了方便实现,程序又被分成了物理介质驱动程序、内容存储程序和文件内容存储程序。物理介质驱动程序专门用于从物理介质上存取数据;内容存储程序用于把文件内容和文件属性信息打包;文件内容存储程序用于把用户输入形成文件内容,或者取得文件内容显示出来。
我们可以把一个文件系统(倒树)分解成多个文件系统(倒树)分别存放到存储介质上,比如:一个存储到光盘里,一个存储到硬盘中,在使用时,我们把光盘里的文件系统的根目录挂到硬盘文件系统的一个目录下面,这样访问这个目录就相当于是访问光盘的根目录了,找到了根目录,我们也就可以访问整个光盘上的文件系统了。
“在Linux系统中一切皆是文件”这句话是我们学习Linux系统的时候常常听到的一句话。虽然有些夸张,但是它揭示了文件系统对于Linux系统的重要性;实际上文件系统对于所有的操作系统都很重要,因为它们把大部分的硬件设备和软件数据以文件的形式进行管理。Linux系统对设备和数据的管理框架图如下:
【图3】文件系统实现
[说明]
A.VFS(virtualfilesystem)是虚拟文件系统,它管理特殊文件(虚拟文件)、磁盘文件和设备文件
B.fs_operations结构是由一系列文件操作接口函数组成,由文件系统层来完成,为VFS提供文件操作;
C.在文件系统层,磁盘文件要实现各种文件系统(如:ext2),设备文件要实现各种抽象的设备驱动
D.在设备驱动层,磁盘驱动要实现各种磁盘的驱动程序,其他设备驱动要实现具体的设备驱动
E.物理层就是设备自身
由于存储介质有很多种,所以没有办法用一种统一的格式存放文件系统到各种不同的存储介质上,而是需要多种不同的存储格式来适应各种存储介质的特性,以求达到存取效率和空间利用率的最优化,这样就需要对每种存储格式制定一个规范,这写规范就叫文件系统类型。常见的文件系统类型有:
1.Dos
FAT16
2.windows
FAT16、FAT32、NTFS
3.Linux
Minix、ext、ext2 、ext3 、ISO9660 、jffs2, yaffs, yaffs2、cramfs, romfs, ramdisk, rootfs、proc、sysfs、usbfs、devpts、 tmpfs & ramfs、 NFS
常用的存储介质理论上都可以用于存储Linux支持的文件系统;因为我们这里只研究嵌入式系统,而嵌入式系统由于体积和移动特性的限制,不能采用磁盘和光盘,所以只能采用flash类的存储设备、内存和虚拟存储设备作为文件系统的存储介质;
flash芯片的驱动程序是由系统来提供,所以它的存取特点完全是flash自身的特点,这时最好有更加适合flash的文件系统——Jffs、Yaffs、Cramfs和Romfs。这些文件系统都是嵌入式Linux系统中常用的文件系统,可以根据特点来选择使用它们,特点如下:
共同点
基于MTD驱动
Jffs
A.针对NOR Flash的实现
B.基于哈希表的日志型文件系统
C.采取损耗平衡技术,每次写入时都会尽量使写入的位置均匀分布
D.可读写,支持数据压缩
E.崩溃/掉电安全保护
F.当文件系统已满或接近满时,因为垃圾收集的关系,运行速度大大放慢
Yaffs
A.针对Nand Flash的实现
B.日志型文件系统
C.采取损耗平衡技术,每次写入时都会尽量使写入的位置均匀分布
D.可读写,不支持数据压缩
E.挂载时间短,占用内存小
F.自带Nandflash驱动,可以不使用VFS和MTD
Cramfs
A.单页压缩,支持随机访问,压缩比高达2:1
B.速度快,效率高
C.只读,有利于保护文件系统免受破坏,提高了系统的可靠性,但是无法对其内容进行扩充
Romfs
A.简单的、紧凑的、只读的文件系统
B.顺序存放数据,因而支持应用程序以XIP(execute In Place,片内运行)方式运行,在系统运行时,节省RAM空间
特有的文件系统类型:Ramdisk文件系统
在Linux系统中,内存经常用于存储文件系统,这种叫做Ramdisk,Ramdisk有两种,一种是完全把内存看成物理存储介质,利用内存模拟磁盘,运用磁盘的文件系统类型;另一种只是在内存中存储了文件系统逻辑结构,运用tmpfs&ramfs文件系统类型:
tmpfs & ramfs
1.概述
用物理内存模拟磁盘分区,挂载这种分区后,就可以跟读写磁盘文件一样读写这里面的文件,但是操作速度要比磁盘文件快得多;所以一般应用在下面几个方面:
1)读写速度要求快的文件应该放在这种文件系统中
2)磁盘分区为flash的情况下,把需要经常读写的文件放在这种文件系统中,然后定期写回flash
3)系统中的临时文件,如/tmp、/var目录下的文件应该放在这种文件系统中
4)/dev设备文件(因为设备文件随驱动和设备的加载和卸载而变化),应该放在这种文件系统中
2.特点
1)由于数据都存放在物理内存中,所以系统重启后,这个文件系统中的数据会全部丢失
2)ramfs在没有指定最大的大小值情况下,会自动增长,直到用掉系统中所有的物理内存为止,这时会导致系统的崩溃,建议挂载时最好限定其最大的大小值
3)tmpfs如果指定了大小值,自动增长至大小值后,系统会限定它的大小;这个文件系统占用的物理内存页可以背置换到swap分区,但是ramfs不行