1 / 39

建立嵌入式 Linux 应用系统

建立嵌入式 Linux 应用系统. 概要. 开发环境 内核配置 bootloader 根文件系统 系统配置和管理 应用开发. 主机系统和目标机系统 主机: x86 , sparc , ... 开发板,评估板,用户定制系统 嵌入式微处理器使用的体系结构 x86 , arm , ppc , mips , ... 主机操作系统 Unix/Linux 交叉编译工具链 编译器,二进制工具集, Windows 专用集成开发环境 如: ADS ,用于编译 ARM 体系结构的代码 虚拟机 VMware+Linux. 其它 内核或驱动程序开发 内核源代码

bat
Download Presentation

建立嵌入式 Linux 应用系统

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 建立嵌入式Linux应用系统

  2. 概要 • 开发环境 • 内核配置 • bootloader • 根文件系统 • 系统配置和管理 • 应用开发

  3. 主机系统和目标机系统 主机:x86,sparc,... 开发板,评估板,用户定制系统 嵌入式微处理器使用的体系结构 x86,arm,ppc,mips,... 主机操作系统 Unix/Linux 交叉编译工具链 编译器,二进制工具集, Windows 专用集成开发环境 如:ADS,用于编译ARM体系结构的代码 虚拟机 VMware+Linux 其它 内核或驱动程序开发 内核源代码 应用程序开发 交叉编译工具集相关头文件和库函数 开发环境

  4. 交叉编译工具集 • 交叉编译器 • gcc:编译器,将c程序转换成汇编程序 • as:汇编器,将汇编程序转换成目标代码 • 二进制工具(binutil) • ld:连接器,将(多个)目标代码连接成一个目标代码或可执行代码 • nm:用于读取目标代码中的符号 • objcopy:可以将一种目标代码形式转换成另一种目标代码形式 • objdump:反汇编一个目标代码或可执行代码 • strip:从目标代码中去掉符号表 • ... • c库 • 静态库:libc.a,libm.a,... • 动态库:libc.so,libm.so,ld.so,...

  5. 获得交叉编译工具集 • GNU提供编译工具的源代码,用户可以自己建立交叉编译工具集。 • 需要的源代码(可从GNU提供的众多镜像网站上得到) • gcc:编译器 • binutils:二进制工具 • kernel:内核 • gdb:调试器 • glibc:c库 • 通常可以找到预编译好的交叉编译工具集 • 编译器版本与内核版本有一定的关联 • 大多来源于经验,无确定对应关系。 • 如:ARM体系结构的交叉编译工具集 • http://handhelds.org/download/projects/toolchain/arm-linux-gcc-3.4.1.tar.bz2

  6. 内核编译配置 • 预置选项 • 可用命令 • make config • make menuconfig • make xconfig • 新增功能或模块 • 增加预置选项 • arch/$(ARCH)/config.in • 直接修改相关Makefile文件

  7. make menuconfig

  8. make menuconfig

  9. make menuconfig

  10. Loadable module support Enable loadable module support Kernel module loader System type (S3C2410-based) ARM system type SMDK (MERI TECH BOARD) change AIJI by threewater--1 ARM920T CPU idle ARM920T I-Cache on ARM920T D-Cache on General setup (0) Compressed ROM boot loader base address (0) Compressed ROM boot loader RSS address Networking support System V IPC Sysctl support NWFPE math emulation (ELF) Kernel core (/proc/kcore) format Kernel support for ELF binaries Kernel-mode alignment trap handler Networking options Packet socket Packet socket: mmapped IO Unix domain sockets TCP/IP networking IP: multicasting Character devices Virtual terminal Unix98 PTY support S3C2410 Real Time Clock File systems Kernel automounter version 4 support Yaffs filesystem on NAND Compressed ROM file system support /proc file system support /dev file system support Automatically mount at boot /dev/pts file system for Unix98 PTYs Network File Systems NFS file system support Provide NFSv3 client support 例1:内核编译主要配置选项

  11. bootloader • bootloader:引导加载程序 • boot loader,bootstrap loader,bootstrap,... • 可能由多个程序接力完成引导加载过程 • 作用 • 只负责系统的启动引导 • 作为系统监控程序 • 各种Linux系统用bootloader • lilo • GRUB • u-boot • vivi • redboot

  12. vivi • vivi是由韩国mizi公司设计为ARM处理器系列设计的一个bootloader • http://www.mizi.com • vivi目前只支持使用串口和主机通信,所以必须使用一条串口电缆来连接目标板和主机。 • vivi最初的加载需要使用JTAG端口 • 主要功能 • flash管理和读写 • 串口数据传输 • 硬件初始化 • 启动内核 • 内置命令 • load:通过串口进行数据传输 • part:将flash进行分区 • param:显示和设置各种参数 • boot:启动各种应用,包括Linux内核 • flash:管理flash设备

  13. 编译vivi 配置: make config 或 make menuconfig 编译: make 或 make vivi

  14. vivi> bon part 0 128k 192k 1216k 4288k:m 64704k 128k 64k 1024k 3072k 60416k vivi param kernel root yaffs vivi/arch/s3c2410/smdk.c mtd_partition_t default_mtd_partitions[] = { { name: "vivi", offset: 0, size: 0x00020000, flag: 0 }, { name: "param", offset: 0x00020000, size: 0x00010000, flag: 0 }, { name: "kernel", offset: 0x00030000, size: 0x000C0000, flag: 0 }, { name: "root", offset: 0x00100000, size: 0x00140000, flag: MF_BONFS } };

  15. u-boot • 由DENX Software Engineering提供的引导加载程序,可支持多种微处理器。 • http://www.denx.de • arm, mips, i386, ppc, ... • u-boot提供多种功能 • flash以及SDRAM的管理和读写 • 串口数据传输 • 加载和启动内核或其它应用程序 • 支持网络启动 • 识别多种文件系统 • 内置命令 • 内置命令非常多,用户可根据需要进行裁减或添加。

  16. cpu/$(CPU)/start.S u-boot的启动部分代码为汇编程序 u-boot-$(version)/common/command.c ... int do_version (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { extern char version_string[]; printf ("\n%s\n", version_string); return 0; } U_BOOT_CMD( version, 1, 1, do_version, "version - print monitor version\n", NULL ); ... u-boot命令实现

  17. 编译u-boot 配置:(例:s3c2410) make smdk2410_config 编译: make 或 make u-boot.bin

  18. 根文件系统 • Linux系统运行需要根文件系统 • 根节点 • 文件系统 • 常用根文件系统 • cramfs • romfs • ramdisk • ext2 • 其它 • 基于磁盘 • yaffs,...

  19. 根文件系统内容 drwxr-xr-x 2 root root 1024 Dec 2 2006 bin drwxr-xr-x 3 root root 2048 Mar 20 2006 dev drwxr-xr-x 6 root root 1024 Dec 2 2006 etc drwxr-xr-x 2 root root 1024 Jul 5 2004 home drwxr-xr-x 2 root root 1024 Jul 5 2004 lib drwxr-xr-x 3 root root 1024 Dec 2 2006 mnt drwxr-xr-x 2 root root 1024 Apr 4 2000 proc drwxr-x--- 2 root root 1024 Mar 20 2006 root drwxr-xr-x 2 root root 1024 Feb 5 2003 sbin drwxrwxrwt 2 root root 1024 Apr 4 2000 tmp drwxr-xr-x 7 root root 1024 Jul 5 2004 usr drwxr-xr-x 8 root root 1024 Apr 18 2003 var

  20. /bin lrwxrwxrwx 1 501 root 7 Apr 21 10:10 ash -> busybox -rwxr-xr-x 1 501 root 385516 Apr 21 10:10 busybox lrwxrwxrwx 1 501 root 7 Apr 21 10:10 cat -> busybox lrwxrwxrwx 1 501 root 7 Apr 21 10:10 chgrp -> busybox lrwxrwxrwx 1 501 root 7 Apr 21 10:10 chmod -> busybox lrwxrwxrwx 1 501 root 7 Jan 1 1970 chown -> busybox lrwxrwxrwx 1 501 root 7 Jan 1 1970 cp -> busybox lrwxrwxrwx 1 501 root 7 Jan 1 1970 date -> busybox lrwxrwxrwx 1 501 root 7 Jan 1 1970 dd -> busybox /sbin -rwxr-xr-x 1 501 root 14180 Apr 21 10:19 cardctl -rwxr-xr-x 1 501 root 44368 Apr 21 10:19 cardmgr -rwxr-xr-x 1 501 root 54476 Apr 21 10:19 depmod -rwxr-xr-x 1 501 root 82172 Apr 21 10:19 fdisk lrwxrwxrwx 1 501 root 14 Jan 1 1970 freeramdisk -> ../bin/busybox -rwxr-xr-x 1 501 root 53572 Jan 1 1970 ftpd -rwxr-xr-x 1 501 root 11880 Jan 1 1970 fuser lrwxrwxrwx 1 501 root 14 Jan 1 1970 getty -> ../bin/busybox lrwxrwxrwx 1 501 root 14 Jan 1 1970 halt -> ../bin/busybox -rwxr-xr-x 1 root root 41781 Jan 1 1970 hciconfig -rwxr-xr-x 1 root root 61572 Jan 1 1970 hcid -rwxr-xr-x 1 root root 41502 Jan 1 1970 hcitool -rwxr-xr-x 1 501 root 1818 Jan 1 1970 hotplug lrwxrwxrwx 1 501 root 14 Jan 1 1970 ifconfig -> ../bin/busybox

  21. /usr/bin lrwxrwxrwx 1 501 root 17 Apr 21 10:27 [ -> ../../bin/busybox lrwxrwxrwx 1 501 root 17 Apr 21 10:27 basename -> ../../bin/busybox lrwxrwxrwx 1 501 root 17 Apr 21 10:27 bunzip2 -> ../../bin/busybox lrwxrwxrwx 1 501 root 17 Apr 21 10:27 bzcat -> ../../bin/busybox lrwxrwxrwx 1 501 root 17 Jan 1 1970 chvt -> ../../bin/busybox lrwxrwxrwx 1 501 root 17 Jan 1 1970 clear -> ../../bin/busybox lrwxrwxrwx 1 501 root 17 Jan 1 1970 cmp -> ../../bin/busybox lrwxrwxrwx 1 501 root 17 Jan 1 1970 cut -> ../../bin/busybox lrwxrwxrwx 1 501 root 17 Jan 1 1970 deallocvt -> ../../bin/busybox /usr/sbin lrwxrwxrwx 1 501 root 17 Apr 21 10:34 chroot -> ../../bin/busybox -rwxr-xr-x 1 root 232 4092 Apr 21 10:34 dongle_attach -rwxr-xr-x 1 root root 17332 Apr 21 10:34 imagewrite -rwxr-xr-x 1 501 root 9164 Apr 21 10:34 imagewrite5 -rwxr-xr-x 1 root 232 11916 Jan 1 1970 irattach -rwxr-xr-x 1 root root 9726 Jan 1 1970 irdaping -rwxr-xr-x 1 root root 6437 Jan 1 1970 irnetd

  22. ramdisk • 内核支持 • CONFIG_BLK_DEV_INITRD=y • drivers/block/rd.c • 使用 • 只在系统启动过程中使用 • 加载额外的设备驱动程序等 • 作为系统根文件系统 • 制作 • 见:文件系统和网络系统,例1。 • 将根文件系统内容拷贝到ramdisk中。

  23. cramfs • 内核支持 • CONFIG_CRAMFS=y • fs/cramfs • 使用 • 只读文件系统 • 通常作为嵌入式系统的根文件系统 • 特点 • 文件大小不能超过16MB • 文件系统大小最大只有256MB(可以稍微超过一点) • 只能使用4096字节大的磁盘块 • 字节顺序与制作主机使用的字节顺序相同 • 制作 • 工具:mkcranfs,cramfsck • http://sourceforge.net/projects/cramfs/

  24. busybox • 专门为嵌入式系统或其它袖珍型系统开发的多功能系统工具,常被称为嵌入式系统上的瑞士军刀。 • http://www.busybox.net • 可实现大多数常用unix或linux命令 • 符合unix命令使用习惯 • 特性 • 用一个可执行文件实现多种命令功能 • 针对嵌入式系统的应用 • 尽量小的代码尺寸 • 去掉不常用的命令选项 • 用户可根据需要配置和裁剪busybox • 有很好的可移植性

  25. 使用busybox命令 Busybox将unix命令作为参数,进而执行相应功能。如: $ busybox ls -l /proc 为符合unix命令的使用习惯,通常将unix命令作为符号链接指向busybox。这时可以直接使用符号链接形式的命令直接调用busubox。

  26. 配置和编译busybox $ make menuconfig

  27. busybox命令实现 busybox中把每个命令称为一个applet,并用一个BB_applet类型的数据结构表示。 include/busybox.h: struct BB_applet struct BB_applet { const char *name; int (*main) (int argc, char **argv); enum Location location:4; enum SUIDRoot need_suid:4; };

  28. 所有配置时选中的命令保存在applets数组中,数组中的元素为BB_applet类型的数据结构。所有配置时选中的命令保存在applets数组中,数组中的元素为BB_applet类型的数据结构。 include/applets.h: applets[ ] const struct BB_applet applets[] = { #define APPLET(a,b,c,d) {#a,b,c,d}, #define APPLET_NOUSAGE(a,b,c,d) {a,b,c,d}, #define APPLET_ODDNAME(a,b,c,d,e) {a,b,c,d}, #ifdef CONFIG_TEST APPLET_NOUSAGE("[", test_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) #endif #ifdef CONFIG_ADDGROUP APPLET(addgroup, addgroup_main, _BB_DIR_BIN, _BB_SUID_NEVER) #endif #ifdef CONFIG_ADDUSER APPLET(adduser, adduser_main, _BB_DIR_BIN, _BB_SUID_NEVER) #endif ... };

  29. busybox的main函数 applets/busybox.c: main( ) int main(int argc, char **argv) { const char *s; bb_applet_name = argv[0]; if (bb_applet_name[0] == '-') bb_applet_name++; for (s = bb_applet_name; *s != '\0';) { if (*s++ == '/') bb_applet_name = s; } run_applet_by_name(bb_applet_name, argc, argv); bb_error_msg_and_die("applet not found"); }

  30. run_applet_by_name( ) applets/applet.c: run_applet_by_name( ) void run_applet_by_name (const char *name, int argc, char **argv) { static int recurse_level = 0; extern int been_there_done_that; /* From busybox.c */ ... /* Do a binary search to find the applet entry given the name. */ if ((applet_using = find_applet_by_name (name)) != NULL) { bb_applet_name = applet_using->name; if (argv[1] && strcmp (argv[1], "--help") == 0) { if (strcmp (applet_using->name, "busybox") == 0) { if (argv[2]) applet_using = find_applet_by_name (argv[2]); else applet_using = NULL; } if (applet_using) bb_show_usage (); been_there_done_that = 1; busybox_main (0, NULL); } exit ((*(applet_using->main)) (argc, argv)); } ... }

  31. 系统配置和管理 内核启动init进程 init/main.c: init( ) static int init(void * unused) { lock_kernel(); ... unlock_kernel(); ... /* * We try each of these until one succeeds. * The Bourne shell can be used instead of init if we are * trying to recover a really broken machine. */ if (execute_command) execve(execute_command,argv_init,envp_init); execve("/sbin/init",argv_init,envp_init); execve("/etc/init",argv_init,envp_init); execve("/bin/init",argv_init,envp_init); execve("/bin/sh",argv_init,envp_init); panic("No init found. Try passing init= option to kernel."); } linuxrc

  32. /sbin/init程序执行过程 系统的init程序根据配置文件/etc/inittab配置操作系统并进而启动各种系统级应用。用户可通过修改配置文件inittab改变系统启动参数。 /etc/inittab # Default runlevel. The runlevels used by RHS are: # 0 - halt (Do NOT set initdefault to this) # 1 - Single user mode # 2 - Multiuser, without NFS (The same as 3, if you do not have networking) # 3 - Full multiuser mode # 4 - unused # 5 - X11 # 6 - reboot (Do NOT set initdefault to this) # id:3:initdefault: # System initialization. si::sysinit:/etc/rc.d/rc.sysinit l0:0:wait:/etc/rc.d/rc 0 l1:1:wait:/etc/rc.d/rc 1 l2:2:wait:/etc/rc.d/rc 2 l3:3:wait:/etc/rc.d/rc 3 l4:4:wait:/etc/rc.d/rc 4 l5:5:wait:/etc/rc.d/rc 5 l6:6:wait:/etc/rc.d/rc 6 ...

  33. rc.sysinit rc.sysinit是一个shell脚本,负责启动各种基本系统功能: 将启动过程记入系统日志 启动网络功能 启动控制台,设定字体 加载/proc文件系统 设定内核参数 设置时钟 设置主机名 加载各种模块 加载各种磁盘文件系统 启动网络系统 根据系统运行级别启动相应的服务器程序 /etc/rc.d/rc0.d~rc6.d 用户可使用chkconfig命令配置服务器启动选项

  34. rc.local rc.local也是一个shell脚本,主要用于用户启动各种用户自己设定的启动程序或命令,这些程序或命令在系统启动时将会被自动执行。rc.local在所有其它初始化脚本执行完后才执行。 例:rc.local #!/bin/sh # # This script will be executed *after* all the other init scripts. # You can put your own initialization stuff in here if you don't # want to do the full Sys V style init stuff. touch /var/lock/subsys/local # added by liyi /sbin/ifconfig eth0 192.168.1.12

  35. 重要系统配置文件 • /etc/inittab • /etc/fstab • /etc/resolv.conf • /etc/xinetd.d/* • /etc/securetty • /etc/logrotate.conf • /etc/hosts, hosts.allow, hosts.deny • /etc/exports • /etc/security/* • /etc/X11/XF86Config • /etc/sysconfig/*

  36. 例2:rc3.d K05saslauthd K36lisa S05kudzu S17keytable S56rawdevices S95atd K15httpd K45named S08iptables S20random S56xinetd S97rhnsd K20nfs K50snmpd S09isdn S24pcmcia S85gpm S99local K24irda K50snmptrapd S10network S25netfs S90crond K30sendmail K50vsftpd S12syslog S26apmd S90cups K35smb K74ntpd S13portmap S28autofs S90xfs K35winbind K95firstboot S14nfslock S55sshd S95anacron S99local -> ../rc.local ... K15httpd -> ../init.d/httpd S dd name S: start,系统启动时执行的脚本 dd: 00-99,数值小则先被系统执行 name: init.d目录中对应的脚本名称 K dd name K: kill,系统退出时执行的脚本 dd: 00-99,数值小则先被系统执行 name: init.d目录中对应的脚本名称

  37. 应用程序开发和调试 • 程序编译 • 交叉编译环境 • 使用静态连接还是动态连接库 • 应用程序调试 • 基于Linux系统的调试方法 • gdb • gdbserver • http://www.gnu.org • 其它调试方法 • JTAG,...

  38. 使用gdb和gdbserver调试程序 192.168.1.10 主机 gdb 192.168.1.12 目标机 gdbserver 网络 / 串口 $ gdb GNU gdb Red Hat Linux ... (gdb) target remote 192.168.1.12:4567 Remote debugging using 192.168.1.12:4567 0x40000be0 in ?? () (gdb) 运行各种调试命令 (gdb)q $ # gdbserver192.168.1.10:4567 myprog Process myprog created; pid = 678 Remote debugging from host 192.168.1.10 Killing inferior #

  39. 关于考试 • 50分 • 范围 • 内存:管理,寻址 • 进程:基本概念,创建,调度,... • 中断、定时、系统调用:基本概念 • 文件系统:ext2文件系统,基本概念,结构 • 设备驱动程序:基本概念,结构,...

More Related