如何给Linux操作系统减肥上
|
减少Linux的系统占用,为应用程序保留更多的资源,减少设备的硬件成本。“你能做到多小?”这个问题通常在嵌入式工程师开始他们的项目时问到。大多数时候,问这个问题的人是想减少RAM和Flash资源,减少设备的单位成本或能源需求。 因为Linux最初是为桌面或服务器系统设计的,默认情况下,它没有为尺寸大小进行过优化,无论如何,Linux正被越来越多地用在嵌入式设备中,要让Linux变小不是一件容易的事情,这里有几个减少系统占用内存的方法。 许多工程师是从减少内核大小开始的,这里有个容易着手的方法,本文将详细介绍如何减少内核的大小,主要通过移除那些在一个典型的嵌入式系统中用不到的代码。 在一个系统中根文件系统(RFS)可能是内存资源最大的消耗者。根文件系统包括了应用程序和c库使用到的基础结构代码。为RFS选择文件系统对最后的大小有非常大的影响,标准是ext3,从一个嵌入式工程师的眼光来看它的效率是非常低的,但那是另一篇文章的主题了。 实际中,如何减小? 即使最小的Linux发行版至少也有两部分:内核和根文件系统。有时,这些部件驻扎在同一个文件中,但是它们仍然分成不同的部件。从内核中移除特征几乎差不多的所有代码,这样一个系统很容易就减少到不到1MB大小。但是,许多用户选择Linux支持网络和不同设备,因此这不是一个现实的做法。 内核 Linux内核非常有趣,尽管在编译时它依赖GCC,但运行时它却不依赖。那些工程师将目光转向Linux初始化RAM磁盘(所谓的initrd),它是内核运行时的附属物。Initrd首先是由内核加载的,程序运行时询问系统需要载入什么模块以便支持设备,这样真实的根文件系统才能被加载。实际上,有两步加载过程,加载initrd后再加载真实的根文件系统,很少发现嵌入式系统中有根文件系统,因为这样在一个系统中会增加灵活性,对这个系统做改动要花费额外的空间或时间,嵌入式系统一般不需要灵活性。但本文稍后将讨论根文件系统。 可载入模块支持 内核载入模块是重新定位运行时内核连接到它自身的代码,典型的可载入模块的例子是允许从用户空间载入驱动到内核中(某些探测进程执行后),以及不关闭系统升级设备驱动。对于大多数嵌入式系统而言,一旦它们处于该范围之外,修改根文件系统要么不现实要么不可能。因此系统设计者直接将模块连接到内核中,移除那些可载入的模块,节约出来的空间对于内核来说是很多的,无论如何,程序管理可载入的模块(如insmod mmodlsmod)和shell脚本载入它们不是必需的。 Linux-tiny补丁 Linux-tiny补丁集已经变得时有时无的项目了,最初是由Matt Mackall在主持。消费电子Linux论坛(CLEF)正在努力恢复这个项目,CLEF开发者WiKi已经给2.6.22.5内核(写本文时的最新版本)发布了补丁,同时,Linux-tiny项目的许多改变已经包括在主线内核中,尽管许多原始的Linux-tiny补丁已经集成到内核中,但实质上节约空间的补丁还没有集成进去。 如: 1、 Fine-grain printk support【细粒度printk支持】:用户可以控制什么文件可以使用printk。工程师将从不使用printk的文件大小中受益。 2、 Change CRC from calculation to use table lookup【改变CRC算法从计算到使用表查询】:以太网数据包需要一个CRC来校验数据包的准确性。这个CRC算法实现使用表查询替换了计算,节约了大约2K。 3、 Network tweaking【网络调整】:几个补丁包减少支持的网络协议,缓存大小和打开的套接字。许多嵌入式设备仅支持少量的协议,不需要有成百上千连接的服务。 4、 No panic reporting【无应急报告】:如果设备有三个状态灯,一系列的连接,用户不能看到,更少的影响,应急信息显示在一个不存在的终端上。如果设备发生内核应急失效,用户只需要重新启动设备即可。 5、 Reduction of inlining【减少直接插入】:直接插入是编译器将代码作为宏拷贝到它调用的每个位置,而不是产生一个函数调用。GCC默认将直接插入任何函数。通过抑制直接插入函数,代码运行稍微慢一点,因为编译器需要为调用和返回产生代码,得到的报酬是对象文件更小了。 Linux-tiny补丁发布成一个tar包,它可以一起应用,也可以一个一个单独应用 尽管Linux-tiny项目涉及到许多的方面,还有几个额外的配置改动可以减少Linux脚印。 1、 移除ext2/3支持,使用另外一个不同的文件系统:ext2/3文件系统通常比较大,大于32K,大部分工程师启用一个Flash文件系统,但是不禁用ext2/3,这样会浪费内存。 2、 移除对sysctl的支持,sysctl允许用户在运行时调整内核参数,在大部分嵌入式设备中,内核配置一旦定了就不需要改动了,使用这个特征会浪费1K。 3、 减少IPC选项,大多数系统没有SysV IPC特性(grep你的msget、msgct、msgsnd和msgrcv代码)和POSIX消息查询(grep mq_*[a-z])一样可以运行,移除它们可以节约18K。 4、 查看你改动的效果 Size命令报告一个对象文件中所有代码和数据的大小,这与ls命令的输入是不同的,ls报告的是在文件系统中的字节数大小。 例如,一个内核用armv51交叉编译器编译报告如下: # armv5l-linux-size vmlinx Text小节是编译器发出的代码,data小节包括全局和其他使用初始静态符号的值,bss小节包括作为初始化的一部分被调零的静态数据。 虽然这个数据有启迪作用,但它没有展示系统消耗的内存部分,也无法通过查询vmlinux得出,但是查看连接在一起的文件,创建vmlinux是接下来最好的事情,为了得到这个信息,使用find命令在内核项目中定位built-in.o文件并计算大小: # find . -name "built-in.o" | xargs armv5l-linux-size 这个技术可以确切地指出占用了大量空间的代码,因此工程师可以首先移除这些代码,当这样做的时候,用户应该在创建之前执行编译清除动作,因为从内核中丢掉一个特征并不意味着那个之前编译好的对象文件将会被删除。 对于那些新添加到Linux内核中的东西,一个常见的问题是如何在内核配置程序中使用一个选项来联合一些built-in.o文件,这可以通过查看目录下的Makefile和Kconfig文件来实现,Makefile将包括象下面这样的一行: obj-$(CONFIG_ATALK) += p8022.o psnap.o 当用户设置了配置变量CONFIG_ATALK后它将生成右手边的文件。内核配置工具一般不会暴露下属配置变量名。要查出变量名之间的连接以及什么是可见的,在Kconfig中寻找没有CONFIG_前缀的变量名。 find . -name Kconfig -exec fgrep -H -C3 "config ATALK" {} ; 它将产生下面这样的输出: ./drivers/net/appletalk/Kconfig-# 还有一些事情需要做,因为用户需要在配置树中找到Appletalk协议支持,但是至少要清楚要查找的是什么 |
