由于嵌入式技术的发展,嵌入式Web服务器软件越来越大,对硬件的要求也相应地提高,但在工业现场的底层控制中,一般嵌入式系统的硬件配置都不是很高,导致了软件和硬件的冲突。本文就是对实际应用过程中,偶尔出现的Web页面访问出错问题进行深入的研究。
1 嵌入式Web在系统中的应用
多支点触发系统包括以下几个模块:控制台模块、网络触发源模块、被触发设备模块。其中,网络触发源和被触发设备都是挂载在总线上的,通过现场总线可以将系统各个节点相互连接起来以方便管理。嵌入式web就是应用于网络触发源模块中,它负责控制台和被触发设备之间的通信。控制台通过浏览器访问网络触发源,在Web页面上完成相应控制操作后,由网络触发源把操作命令发送到总线上,被触发设备从总线上接收到命令后,完成相应操作。在网络触发源模块中,Web服务器采用的是Boa,嵌入式操作系统采用的是uClinux,处理器采用的是Sam-sung公司的S3C44BO。多支点触发系统结构如图1所示。
2 Boa的运行流程及出现的问题
Boa是单任务的http服务器,源码开放,性能高。与传统的Web服务器不同,它并不对每个进入服务器的连接开辟新的进程,所有活动的http连接都在内部进行处理,而只为每个CGI连接启动新进程。在已进行的测试中,Boa服务器比其他的Web服务器要快,所以它应用在嵌入式系统中是具有良好前景的。图2是Boa基本的运行流程。
在Boa运行过程中,用户请求初始Lo-gin页面时,系统能正常响应操作。当用户输入正确的Login信息,要实现页面跳转时,PC机上的浏览器里面不能正确浏览,提示错误:“502 bad gate-way The CGI was notCGI/1.1 compliant”。由于运行的是CGI程序,通过调试和查看错误日志,发现系统停留在步骤⑤~⑦间。在排除CGI程序错误后,通过串口调试终端打印出的错误信息发现:在执行CGI程序时,内核申请内存时出错,提示申请的内存块不能得到,即内存丢失。
3 系统内存丢失分析
3.1 uClinux的内存管理
uClinux不能使用处理器的虚拟内存管理技术,它仍然采用存储器的分页管理。系统启动时对存储器分页,加载应用程序对程序分页加载。由于没有MMU管理,所以uClinux采用实存储器管理。uClinux系统对内存的访问是直接的(它对地址的访问不经MMU,而是直接送到地址线上输出),所有程序访问的地址是物理地址。那些比物理内存还大的程序将无法执行。
uClinux将整个物理内存划分成为4 KB的页面。由数据结构page管理,有多少页面就有多少page结构,它们又作为元素组成数组men_map[]。物理页面可作为进程代码、数据和堆栈的一部分,还可存储装入的文件,也可作缓冲区。[page]
uClinux用标准Linux内核变型BuddySystem机制管理空闲物理页面。
3.2 内存丢失原因
由于uClinux提供了跟普通Linux一样的内存分配器,普通Linux中缺省的内存分配器是使用“2的幂”的分配方法,这样可以快速找到符合要求的内存区域。在系统开发过程初期,采用的就是“2的幂”的分配方法。如果一个应用程序要求(X)KB内存空间进行装载,则实际使用占用的内存空间大小为Y=2m(Y≥X)。试想一个65 KB应用程序,如果按照“2的幂”的分配方法,就必须分配128 KB(2的7次方)的内存空间,这样就有63 KB的内存空间不能被利用上。这对于小内存的嵌入式系统来说是相当大的浪费。
多支点触发系统运行时,嵌入式操作系统uClinux使用“2的幂”的内存分配方法,大多数情况下都能正常工作。但在不断反复测试中,偶尔会出现上述页面出错问题。错误的原因是不能获得足够的内存加载程序。通过调试终端,用free命令查看系统内存分配情况如表1所列。
由表1可以看出,空闲的内存空间还有1560 KB,而应用程序所需的内存空间为400多KB,但是内核认为并没有足够的内存空间用来加载程序。例如一个系统内存大小为1 MB,有400KB的空闲内存,为了装载一个应用程序需要分配100 KB的空间。大家可能觉得这个需要肯定能得到满足,然而,由于uClinux必须给应用程序分配连续内存空间的特性,所以必须有100KB连续的内存空间才能满足这个需要。而当系统内存分配如图3所示时,最大的连续内存块的大小只有80 KB,这样是没有办法分配给这个应用程序的。这就是系统中页面访问出错的问题所在,虽然有足够的空闲内存空间,但是没有应用程序所需的连续内存空间。
这就是内存丢失问题。虽然系统会显示大量的可用内存,但是应用程序却不能得到。
4 内存丢失问题的解决
由于系统的内存管理默认采用“2的幂”的分配方法,这就造成了内存空间的巨大浪费,当某些应用程序要申请较大的连续空间时,却不能满足。为了解决这个问题,专门为uClinux内核设计了可选的内存分配器。不同的内核版本,这个可选的内存分配器不同,一般是page_alloc2和kmalloc2。
page_alloc2能解决缺省的分配方法造成的浪费问题。虽然它也是使用“2的幂”的分配方法,但它是按页(每页4 096B,即4 KB)分配的,分配的内存大小如果已经满足了要求,则只是将当前的一页分配出去,其他的就不再分配。还是一个65 KB的应用程序,如果使用这种方法,就只是分配68 KB(≥65 KB,且为整页)即可,这样就能节省60 KB的空间。
page_alloc2还采取了一些避免内存碎片的方法。它将所有的两页(8 KB)或更少的内存需求从空闲内存开始部分向上分配,所有大的内存需求从剩余内存的末尾部分开始向下分配。这样防止了网络缓存等的临时分配,避免了内存碎片的出现。同时,它支持一次申请超过1 MB的内存空间,这对一些大的应用程序是很好的支持。采用此方法后,在系统运行过程中,并未出现过页面访问出错问题。通过free命令查看内存分配如表2所列。
结 语
在嵌入式系统应用日益广泛的情况下,本文结合嵌入式Web在多支点触发系统中的应用,介绍了Web访问出现的问题以及它的解决方法。在实际应用中,新的内存分配方法能让系统稳定地工作,但是从表2可以发现:采用“page_alloc2\'’的内存分配方法时,系统的Cache较小,这就造成了页面访问有一定的延时。而“2的幂”的分配方法,系统的Cache较大,访问速度较快。从这个对比得知,在反应时间要求不是很高的情况下,“page_alloc2”的内存分配方法更适合小内存的嵌入式系统;而“2的幂”的分配方法更合适那些内存足够大的嵌入式系统。系统开发者可以根据实际情况采用不同的方案。