摘 要:在分析 Linux2.6 内核新特性的基础上 , 在 S3C2410 开发板上移植了 2.6
内核和新的文件系统 , 并成功地对 H.264 编解码多媒体系统提供了支持。
关键词: Linux
内核 嵌入式系统 S3C2410
随着多媒体技术与通讯技术相结合的信息技术的快速发展和互联网的广泛应用
,PC 时代也过渡到了后 PC 时代。在数字信息技术和网络技术高速发展的后 PC 时代 , 嵌入式技术越来越与人们的生活紧密结合。
操作系统为用户使用计算机及其外部设备提供最基本的接口程序 , 管理计算机上的资源。随着应用领域的扩大
, 为了适应不同的应用场合 , 考虑到系统的灵活性、可伸缩性以及可裁剪性 ,
一种以应用为中心、以计算机技术为基础、软硬件可裁剪、适应应用系统对功能、可靠性、成本、体积、功耗要求严格的专用计算机系统 ——
嵌入式操作系统随之延生。
Linux 操作系统是一种性能优良、源码公开且被广泛应用的免费操作系统 ,
由于其体积小、可裁减、运行速度高、良好的网络性能等优点 , 可以作为嵌入式操作系统。随着 2.6 内核的发布 ,Linux
向现有主流的 RTOS 提供商在嵌入式系统市场提出了巨大挑战 , 例如 VxWorks 和 WinCE, 具有许多新特性 ,
将成为更优秀的嵌入式操作系统。
Linux 的低成本和开放性 ,
为其在嵌入式系统领域的应用营造了肥沃的土壤。本文着重介绍 Linux 2.6 内核的新特性及其嵌入式应用中的优势 ,
并将其移植到嵌入式平台中 , 成功支持 H.264 编解码多媒体系统。
1 、 Linux 2.6
内核针对嵌入式开发显著特点
实时可靠性是嵌入式应用较为普遍的要求 , 尽管 Linux 2.6
并不是一个真正的实时操作系统 , 但其改进的特性能够满足响应需求。 Linux 2.6
已经在内核主体中加入了提高中断性能和调度响应时间的改进 , 其中有三个最显著的改进 :
采用可抢占内核、更加有效的调度算法以及同步性的提高 [4] 。在企业服务器以及嵌入式系统应用领域 ,Linux 2.6
都是一个巨大的进步。在嵌入式领域 ,Linux 2.6 除了提高其实时性能 , 系统的移植更加方便 ,
同时添加了新的体系结构和处理器类型 —— 包括对没有硬件控制内存管理方案的 MMU-less 系统的支持 ,
可以支持大容量内存模型、微控制器 , 同时还改善了 I/O 子系统 , 增添更多的多媒体应用功能 [4] 。
1.1 可抢占内核
在先前的内核版本中 ( 包括 2.4 内核 )
不允许抢占以核心态运行的任务 ( 包括通过系统调用进入内核模式的用户任务 ), 只能等待它们自己主动释放 CPU
。这样必然导致一些重要任务延时以等待系统调用结束。
一个内核任务可以被抢占 ,
为的是让重要的用户应用程序可以继续运行。这样做最主要的优势是极大地增强系统的用户交互性。
2.6
内核并不是真正的 RTOS(Real Time Operation System), 其在内核代码中插入了抢占点 ,
允许调度程序中止当前进程而调用更高优先级的进程 , 通过对抢占点的测试避免不合理的系统调用延时。 2.6 内核在一定程度上是可抢占的
, 比 2.4 内核具备更好的响应性。但也不是所有的内核代码段都可以被抢占 , 可以锁定内核代码的关键部分 , 确保 CPU
的数据结构和状态始终受到保护而不被抢占。
软件需要满足最终时间限制与虚拟内存请求页面调度之间是相互矛盾的。慢速的页错误处理将会破坏系统的实时响应性 , 而 2.6
内核可以编译无虚拟内存系统避免这个问题 , 这是解决问题的关键 , 但要求软件设计者有足够的内存来保证任务的执行。
1.2 有效的调度程序
2.6 版本的 Linux 内核使用了由 Ingo
Molnar 开发的新的调度器算法 , 称为 O(1) 算法 , 如图 1 所示。它在高负载情况下执行得极其出色 ,
并且当有很多处理器并行时也可以很好地扩展 [2] 。过去的调度程序需要查找整个 ready task 队列 ,
并且计算它们的重要性以决定下一步调用的 task, 需要的时间随 task 数量而改变。 O(1) 算法则不再每次扫描所有的任务 ,
当 task 就绪时被放入一个活动队列中 , 调度程序每次从中调度适合的 task,
因而每次调度都是一个固定的时间。任务运行时分配一个时间片 , 当时间片结束 ,
该任务将放弃处理器并根据其优先级转到过期队列中。活动队列中任务全部调度结束后 , 两个队列指针互换 , 过期队列成为当前队列 ,
调度程序继续以简单的算法调度当前队列中的任务。这在多处理器的情况更能提高 SMP 的效率 , 平衡处理器的负载 ,
避免进程在处理器间的跳跃。
1.3 同步原型与共享内存
多进程应用程序需要共享内存和外设资源 , 为避免竞争采用了互斥的方法保证资源在同一时刻只被一个任务访问。 Linux
内核用一个系统调用来决定一个线程阻塞或是继续执行来实现互斥 , 在线程继续执行时 , 这个费时的系统调用就没有必要了。
Linux2.6 所支持的 Fast User-Space Mutexes 可以从用户空间检测是不是需要阻塞线程 ,
只在需要时执行系统调用终止线程。它同样采用调度优先级来确定将要执行的进程 [4] 。多处理器嵌入式系统各处理器之间需要共享内存 ,
对称多处理技术对内存访问采用同等优先级 , 在很大程度上限制了系统的可量测性和处理效率。 Linux2.6 则提供了新的管理方法
——NUMA(Non Uniform Memory Access) 。 NUMA 根据处理器和内存的拓扑布局 , 在发生内存竞争时
, 给予不同处理器不同级别权限以解决内存抢占瓶颈 , 提高吞吐量。
1.4 POSIX 线程及 NPTL
新的线程模型基于一个 1:1 的线程模型 ( 一个内核线程对应一个用户线程 ), 包括内核对新的
NPTL(Native POSIX Threading Library) 的支持 , 这是对以前内核线程方法的明显改进。 2.6
内核同时还提供 POSIX signals 和 POSIX high-resolution timers 。 POSIX
signals 不会丢失 , 并且可以携带线程间或处理器间的通信信息。嵌入式系统要求系统按时间表执行任务 ,POSIX timer
可以提供 1kHz 的触发器使这一切变得简单 , 从而可以有效地控制进度。
1.5 微控制器的支持
Linux2.6 内核加入了多种微控制器的支持。无 MMU 的处理器以前只能利用一些改进的分支版本 , 如
uClinux, 而 2.6 内核已经将其整合进了新的内核中 , 开始支持多种流行的无 MMU 微控制器 , 如
Dragonball 、 ColdFire 、 Hitachi H8/300 。 Linux 在无 MMU
控制器上仍旧支持多任务处理 , 但没有内存保护功能。同时也加入了许多流行的控制器的支持 , 如 S3C2410 等。
1.6 面向应用
嵌入式应用有用户定制的特点 , 硬件设计都针对特定应用开发
, 这给系统带来对非标准化设计支持的问题 ( 如 IRQ 的管理 ) 。为了更好地实现 , 可以采用部件化的操作系统。
Linux2.6 采用的子系统架构将功能模块化 , 可以定制而对其他部分影响最小。同时 Linux2.6
提供了多种新技术的支持以实现各种应用开发 , 如 Advanced Linux Sound Architecture(ALSA) 和
Video4Linux 等 , 对多媒体信息处理更加方便 ; 对 USB2.0 的支持 , 提供更高速的传输 ,
增加蓝牙无线接口、音频数据链接和面向链接的数据传输 L2CAP, 满足短距离的无线连接的需要 ; 而且在 2.6
内核中还可以配置成无输入和显示的纯粹无用户接口系统。
2 、应用研究
在
S3C2410 开发板上移植嵌入式 Linux 2.6.11.7 内核系统 , 应用于构建 H.264 多媒体系统。
2.1 建立交叉编译环境
在 RedHat9 的主机上进行内核移植开发 ,
首先需要建立交叉编译环境。由于 2.6 内核中采用了一些新的特性和指令 , 需要采用较新的工具集 , 采用
binutils-2.15 、 gcc-3.4.2 、 glibc-2.2.5 、 linux-2.6.8 、
glibc-linuxthreads-2.2.5 来建立交叉编译工具链 , 建立之后将工具链路径加入系统路径 $PATH 中。
2.2 内核修改
Linux 2.6.11.7 内核加入了对 S3C2410
芯片的支持 , 不再需要任何补丁文件。修改内核源码中 Makefile 的交叉编译选项 ARCH=arm,
CROSS_COMPILE=arm-linux- 。针对硬件配置 , 需要在
arch/arm/mach-s3c2410/devs.c 或者 smdk2410.c 中添加 FLASH 的分区信息
s3c_nand_info, 如表 1 。
表 1 NAND FLASH 分区表
分区名 起始地址 大 小
Vivi 0x00000000 0x00020000
Param 0x00020000 0x00010000
Kernel
0x00030000 0x001c0000
Root 0x00200000 0x00200000
Usr 0x00400000 0x03c00000
然后在
s3c_device_nand 中增加 .dev={.platform_data= &s3c_nand_info}, 在
arch/arm/mach-s3c2410/mach-smdk2410.c 中的 __initdata 部分增加
&s3c_device_nand, 使内核在启动时初始化 NAND FLASH 信息。
2.3
内核编译加载
对内核进行适当的配置是一个量体裁衣的过程。由于 2.6
内核会根据本地系统配置进行初始设置 , 可以导入内核源码默认 s3c2410 的配置文件 , 方便加载内核基本配置 ,
然后再选择所需选项。对 MTD 配置选择支持 MTD 设备驱动以及 NAND FLASH 驱动 ; 选择支持要用到的各类文件系统
(DEVFS 、 TMPFS 、 CRAMFS 、 YAFFS 、 EXT2 、 NFS) 以及网络设备和协议 ,
本系统加载了网络芯片 CS8900 以及 USB 支持 ; 在 H.264 多媒体系统中还需要加载 Frame buffer 以支持
LCD 显示功能。使用交叉编译工具编译内核源码后 , 会在 arch/arm/boot/ 下生成名为 zImage 的内核映像 ,
在 Boot loader 的命令提示模式下使用下载命令完成内核加载到开发板的存储设备 FLASH 中。编译过程 (
相对以前版本的编译过程 ,2.6 内核编译有所简化 ):
make mrproper
make menuconfig( 字符界面 , 或者用 make xconfig 图形界面 , 但需要 Qt
库的支持 , 而 make gconfig 则需要 GTK 库的支持 )
make
make bzImage
2.4 文件系统
Linux
采用文件系统组织系统中的文件和设备 , 为设备和用户程序提供统一接口。 Linux 支持多种文件系统 , 本系统使用 CRAMFS
格式的只读根文件系统 , 而将 FLASH 中的 USER 区使用支持可读写的 YA FFS 文件系统格式 ,
方便添加自己的应用程序。
在根文件系统中 , 为保护系统的基本设置不被更改 , 采用 CRAMFS
格式。采用 DEVFS 来实现基本设备的建立挂载 , 同时使用 BusyBox 也是一个缩小根文件系统的办法 ,
提供了系统的基本指令 ; 还需要建立一些必备的目录 , 添加所需配置文件 , 如 fstab 、 inittab 等 ;
还有一个重要的工作就是添加系统应用必备的动态函数库。使用生成工具 mkcramfs 将整个根文件目录里的内容制作成映像文件。
mkcramfs rootfs rootfs.ramfs
YAFFS
文件系统格式的支持需要将驱动加入到内核代码树下 fs/yaffs/, 修改内核配置文件 ,
就可以在内核编译中加载对该文件系统的支持。使用 mkyaffs 工具将 NAND FLASH 分区格式化为 YAFFS 分区 , 将
mkyaffsimage 生成的应用程序镜像烧写进 YAFFS 分区 , 在启动时通过写入 fstab 自动加载 YAFFS
分区即可。
2.5 网络设备驱动
系统中采用 CS8900A 的 10M
网络芯片 , 它使用 S3C2410 的 nGCS3 和 IRQ_EINT9, 相应修改
linux/arch/arm/mach-s3c2410/irq.c, 并在 mach-smdk2410.c 的
smdk2410_iodesc[] 中增加 {SMDK2410_ETH_IO,S3C2410_CS2, SZ_1M,
MT_DEVICE}, 内核源码中加入芯片的驱动程序 drivers/net/arm/cs8900.h 和 cs8900.c,
并且配置网络设备驱动的 Makefile 和 Kconfig 文件 , 加入 CS8900A 的配置选项 ,
这样可以在内核编译时加载网络设备的驱动。
在 Linux2.6 应用的同时 ,
也要看到其与以前版本内核比较存在的一些问题。在内核的编译时间、内核镜像大小、内核占用 RAM 空间大小、系统启动时间相对
Linux2.4 而言都存在不同程度的不足 , 但在硬件条件日益进步的现今可以接受 , 而且一部分也是由于功能加强必然带来的。虽然
Linux 并非一个真正的实时操作系统 , 但 2.6 内核的改进能够满足大部分的应用需求 , 所以 Linux2.6
内核将会在嵌入式系统领域大展身手。
【本站声明】本站刊载的部分内容全部来源互联网,对于此类文章本站仅提供交流平台,不为其版权负责。如涉及侵犯您的知识产权的文章,请联系我们,我们将尽快做出更正。并向您表示感谢!同时特别感谢对本站所有支持的网友。