《ARMLinux内核》由会员分享,可在线阅读,更多相关《ARMLinux内核(74页珍藏版)》请在金锄头文库上搜索。
1、ARMLinux 内核 1提纲l1. ARM系统结构简介 l2. ARM-Linux内存管理 l3. ARM-Linux 的中断响应和处理 l4. ARM-Linux系统调用l5. 系统的启动和初始化 l6. ARM-Linux进程管理和调度 l7. Linux的模块机制 21. ARM系统结构简介lARM有7种运行状态:l用户状态(User) l中断状态(IRQ, Imterrupt Request) (0x18)l快中断状态(FIQ,Fast Imterrupt Request)(0x1c) l监管状态(Supervisor) l终止状态(Abort) l无定义状态(Undefined)
2、l系统状态(System) 3lARM系统结构中各个寄存器的使用方式 寄存器使用方式程序计数器pc(r15)由所有运行状态共用通用寄存器r0-r7由所有运行状态共用通用寄存器r8-r12除快中断以外所有其他运行状态共用(快中断状态有自己专用的r8-r12)当前程序状态寄存 器CPSR由所有运行状态共用保存程序状态寄存器SPSR除用户状态以外的6种运行状态,各有自己的保存程序状态寄存器SPSR堆栈指针sp(r13)和链接寄存器lr(r14)7种运行状态各有自己的sp和lr42 ARM-Linux内存管理 l存储管理是一个很大的范畴 l地址映射、空间分配、保护机制l存储管理机制的实现和具体的CPU
3、以及MMU的结构关系非常紧密 l操作系统内核的复杂性相当程度上来自内存管理,对整个系统的结构有着根本性的深远影响 52.1内存管理和内存管理和MMU lMMU,也就是“内存管理单元”,其主要作用是两个方面:l地址映射 l对地址访问的保护和限制 lMMU就是提供一组寄存器lMMU可以做在芯片中,也可以作为协处理器lARM中的CP15 62.2 冯冯诺依曼结构和哈佛结构诺依曼结构和哈佛结构 l冯诺依曼结构:程序只是一种数据,对程序也可以像对数据一样加以处理,并且可以和数据存储在同一个存储器中 l嵌入式系统中往往采用程序和数据两个存储器、两条总线的系统结构,称为“哈佛结构” 72.3 ARM存储管理
4、机制存储管理机制 lARM系统结构中,地址映射可以是单层的按“段(section)”映射,也可以是二层的页面映射 l采用单层的段映射的时候,内存中有个“段映射表” ,当CPU访问内存的时候:l其32位虚地址的高12位用作访问段映射表的下标,从表中找到相应的表项 l每个表项提供一个12位的物理段地址,以及对这个段的访问许可标志,将这12位物理段地址和虚拟地址中的低20位拼接在一起,就得到了32位的物理地址 8l如果采用页面映射,“段映射表”就成了“首层页面映射表”,映射的过程如下(以页面大小4KB为例): l以32位虚地址的高12位(bit20-bit31)作为访问首层映射表的下标,从表中找到相
5、应的表项,每个表项指向一个二层映射表。l以虚拟地址中的次8位(bit12-bit19)作为访问所得二层映射表的下标,进一步从相应表项中取得20位的物理页面地址。l最后,将20位的物理页面地址和虚拟地址中的最低12位拼接在一起,就得到了32位的物理地址。9l凡是支持虚存的CPU必须为有关的映射表提供高速缓存,使地址映射的过程在不访问内存的前提下完成,用于这个目的高速缓存称为TLBl高速缓存 (I/O的特殊性)lARM系统结构中配备了两个地址映射TLB和两个高速缓存 10lARM处理器中,MMU是作为协处理器CP15的一部分实现的 lMMU相关的最主要的寄存器有三个:l控制寄存器,控制MMU的开关
6、、高速缓存的开关、写缓冲区的开关等l地址转换表基地址寄存器 l域访问控制寄存器 11l控制寄存器中有S位(表示System)和R位(表示ROM),用于决定了CPU在当前运行状态下对目标段或者页面的访问权限,如果段或者页面映射表项中的2位的“访问权限” AP为00,那么S位和R位所起的作用如表 SRCPU运行在特权状态CPU运行在用户状态00不能访问不能访问10只读不能访问01只读只读11不确定不确定12l如果AP为01,则和S位R位无关,特权状态可读可写,用户状态不能访问。l如果AP为10,则和S位R位无关,特权状态可读可写,用户状态只读。l如果AP为11,则和S位R位无关,特权状态、用户状态
7、都可读可写。132.4 ARM-Linux存储机制的建立存储机制的建立 lARM-Linux内核也将这4GB虚拟地址空间分为两个部分 ,系统空间和用户空间 lARM将I/O也放在内存地址空间中,所以系统空间的一部分虚拟地址不是映射到物理内存,而是映射到一些I/O设备的地址 14#define TASK_SIZE (0xc0000000UL)#define PAGE_OFFSET (0xc0000000UL)#define PHYS_OFFSET (0xa0000000UL)#define _virt_to_phys(x) (x) - PAGE_OFFSET + PHYS_OFFSET)#def
8、ine _phys_to_virt(x) (x) - PHYS_OFFSET + PAGE_OFFSET)15lXsbase255开发系统存储管理的描述数据结构: static struct map_desc xsbase255_io_desc _initdata = /* virtual physical length domain r w c b */ 0xE8000000, 0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 , 0xF0000000, 0x04000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 ,
9、0xf0110000, 0x08000000, 0x00010000, DOMAIN_IO, 0, 1, 0, 0 , 0xf0120000, 0x08100000, 0x00010000, DOMAIN_IO, 0, 1, 0, 0 , 0xf1000000, 0x0C700000, 0x00010000, DOMAIN_IO, 0, 1, 0, 0 , ;/片选0 CS0 : Intel Strata Flash 32M; / 片选1CS1 : CS8900A;/片选2 CS2 : Extend PORT0,扩充的GPIO;/ CS2 : Extend PORT1;/ 片选CS3 : US
10、B Host(Ez-Host)16lARM处理器上的实现和x86的既相似又有很多不同: l在ARM处理器上,如果整个段(1MB,并且和1MB边界对齐)都有映射,就采用单层映射;而在x86上总是采用二层映射 lARM处理器上所谓的“段(section)”是固定长度的,实质上就是超大型的页面;而x86上的“段(segment)”则是不定长的lLinux在启动初始化的时候依次调用:start_kernel()setup_arch()pageing_init()memtable_init()create_mapping() 172.5 ARM-Linux进程的虚存空间 lLinux虚拟内存的实现需要6
11、种机制的支持:l地址映射机制l内存分配回收机制l缓存和刷新机制l请求页机制l交换机制l内存共享机制 18l系统中的每个进程都各有自己的首层映射表,这就是它的空间,没有独立的空间的就只是线程而不是进程 lLinux内核需要管理所有的虚拟内存地址,每个进程虚拟内存中的内容在其task_struct结构中指向的 vm_area_struct结构中描叙 19ltask_struct结构分析图 :20l由于那些虚拟内存区域来源各不相同,Linux使用vm_area_struct中指向一组虚拟内存处理过程的指针来抽象此接口 l为进程创建新的虚拟内存区域或处理页面不在物理内存中的情况下,Linux内核重复使
12、用进程的vm_area_struct数据结构集合。采用AVL树来减少查找时间。l当进程请求分配虚拟内存时,Linux并不直接分配物理内存 213 ARM-Linux 的中断响应和处理的中断响应和处理 l中断是一个流程,一般来说要经过三个环节:l中断响应l中断处理l中断返回 l中断响应是第一个环节,主要是确定中断源,在整个中断机制中起着枢纽的作用 22l使CPU在响应中断的时候能迅速的确定中断源,且尽量减少引脚数量且尽量减少引脚数量,辅助手段主要有下列几种:l中断源通过数据总线提供一个代表具体设备的数值,称为“中断向量” l在外部提供一个“集线器”,称为“中断控制器” l将中断控制器集成在CPU
13、芯片中,但是设法“挪用”或“复制”原有的若干引线,而并不实际增加引线的数量 23lARM是将中断控制器集成在CPU内部的,由外设产生的中断请求都由芯片上的中断控制器汇总成一个IRQ中断请求l中断控制器还向CPU提供一个中断请求寄存器和一个中断控制寄存器 lGPIO是一个通用的可编程的I/O接口,其接口寄存器中的每一位都可以分别在程序的控制下设置用于输入或者输出 24lARM Linux将中断源分为三组:l第一组是针对外部中断源;l第二组中是针对内部中断源,它们都来自集成在芯片内部的外围设备和控制器,比如LCD控制器、串行口、DMA控制器等等。l第三组中断源使用的是一个两层结构。25l在Linu
14、x中,每一个中断控制器都由strcut hw_interrut_type数据结构表示:struct hw_interrupt_type const char * typename;unsigned int (*startup)(unsigned int irq);void (*shutdown)(unsigned int irq);void (*enable)(unsigned int irq);void (*ack)(unsigned int irq);void (*end)(unsigned int irq);void (*set_affinity)(unsiged int irq,uns
15、igned long mask);26l每一个中断请求线都有一个struct irqdesc 数据结构表示: typedef struct unsigned int status; /* IRQ status */hw_irq_controller *handler;struct irqaction *action; /*IRQ action list */unsigned int depth; /* nested irq disables */spinlock_t lock;_cacheline_aligned irq_desc_t;27l具体中断处理程序则在数据结构 struct irqa
16、ctionl三个数据结构的相互关系如图 :struct hw_interrupt_typeStruct irqacton指向具体的中断服务函数irq_descNR_IRQS 28lARM Linux的中断初始化。l在ARM Linux存储管理中,内核中DRAM区间的虚拟地址和物理地址是相同的。系统加电引导以后,CPU进入内核的总入口,即代码段的起点stext,CPU首先从自身读出CPU的型号以及其所在的开发板,把有关的信息保存在全局变量中;l然后就转入start_kernel()函数进行初始化;l接着是执行函数trap_init()l这个函数做的第一件事是将下列指令搬运到虚拟地址0处: 29l
17、第二件事是搬运底层中断响应程序的代码(如下所示)到0x200处 :.LCvectors: swi SYS_ERROR0 b _real_stubs_start + (vector_undefinstr - _stubs_start) ldr pc, _real_stubs_start + (.LCvswi - _stubs_start) b _real_stubs_start + (vector_prefetch - _stubs_start) b _real_stubs_start + (vector_data - _stubs_start) b _real_stubs_start + (v
18、ector_addrexcptn - _stubs_start) b _real_stubs_start + (vector_IRQ - _stubs_start) b _real_stubs_start + (vector_FIQ - _stubs_start)_stubs_start:vector_IRQ:vector_data:vector_prefetch:vector_undefinestr:vector_FIQ:vector_addrexcptn:.LCvswi:.wordvector_swi.LCsirq:.word_temp_irq.LCsund:.word_temp_und.
19、LCsabt:.word_temp_abt_stubs_end:30ltrap_init()函数执行完了以后,再执行init_IRQ()。通过函数init_IRQ()建立上面提及的3个数据结构及其相互联系的框架。 31l在进入中断响应之前,CPU自动完成下列操作:l将进入中断响应前的内容装入r14_irq,即中断模式的lr,使其指向中断点。l将cpsr原来的内容装入spsr_irq,即中断模式的spsr;同时改变cpsr的内容使CPU运行于中断模式,并关闭中断。l将堆栈指针sp切换成中断模式的sp_irq。l将pc指向0x18。 32l中断流程图: 334 ARM-Linux系统调用系统调用
20、lLIBC和直接调用lX86有INT 0x80larm处理器有自陷指令SWI lcpu遇到自陷指令后,跳转到内核态l操作系统首先保存当前运行的信息,然后根据系统调用号查找相应的函数去执行l执行完了以后恢复原先保存的运行信息返回 34实验一创建和使用一个新的系统调用(1) l在 arch/arm/kernel/目录下创建一个新的文件mysyscall.c l在 arch/arm/kernel/call.S 中添加新的系统调用,新的系统调用号0x900000+226void hello(void) printk(“hello worldn”); .long SYMBOL_NAME(sys_gett
21、id) .long SYMBOL_NAME(sys_readahead) .long .long SYMBOL_NAME(helloSYMBOL_NAME(hello) )_syscall_end: .rept NR_syscalls - (_syscall_end - _syscall_start) / 4 .long SYMBOL_NAME(sys_ni_syscall) .endr35实验一创建和使用一个新的系统调用(2)l修改arch/arm/kernel/目录下的Makefile文件,在obj-y后面添加mysyscall.o obj-y := arch.o compat.o dma
22、.o $(ENTRY_OBJ) entry-common.o irq.o process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o time.o traps.o $(O_OBJS_$(MACHINE) mysyscall.o36实验一创建和使用一个新的系统调用(3)l写一个测试程序来使用新的系统调用: test.h:#definesys_hello()_asm_ _volatile_ (swi 0x900000+226nt)while(0)test.c:#include #include “test.h”int main(void)pr
23、intf(start hellon);sys_hello();printf(end hellon);37实验一创建和使用一个新的系统调用(4)l然后执行 l启动开发板,将应用程序test通过zmodem协议下载到开发板的文件系统目录下,在板子上运行test程序所得结果如下: 注意,上面的例子是直接用汇编使用系统调用的,而不是使用libc,因为test应用程序使用的是新添加的系统调用,而libc中并没有,所以只能直接用汇编。 # arm-linux-gcc test.c -o test# ./teststart hellohello worldend hello38l思考:如何增加一个带参数的系
24、统调用?395. 系统的启动和初始化系统的启动和初始化 l使用bootloader将内核映像载入 l内核数据结构初始化(内核引导第一部分) :lstart_kernel()中调用了一系列初始化函数,以完成kernel本身的设置 l调用init()过程,创建第一个内核线程。 40Start_kernel():l输出Linux版本信息(printk(linux_banner)) l设置与体系结构相关的环境(setup_arch()) l页表结构初始化(paging_init()) l设置系统自陷入口(trap_init()) l初始化系统IRQ(init_IRQ()) l核心进程调度器初始化(包括
25、初始化几个缺省的Bottom-half,sched_init()) l时间、定时器初始化(包括读取CMOS时钟、估测主频、初始化定时器中断等,time_init()) l提取并分析核心启动参数(从环境变量中读取参数,设置相应标志位等待处理,(parse_options()) l控制台初始化(为输出信息而先于PCI初始化,console_init()) l剖析器数据结构初始化(prof_buffer和prof_len变量) l核心Cache初始化(描述Cache信息的Cache,kmem_cache_init()) l延迟校准(获得时钟jiffies与CPU主频ticks的延迟,calibrat
26、e_delay()) 41l内存初始化(设置内存上下界和页表项初始值,mem_init()) l创建和设置内部及通用cache(slab_cache,kmem_cache_sizes_init()) l创建uid taskcount SLAB cache(uid_cache,uidcache_init()) l创建文件cache(files_cache,filescache_init()) l创建目录cache(dentry_cache,dcache_init()) l创建与虚存相关的cache(vm_area_struct,mm_struct,vma_init()) l块设备读写缓冲区初始化
27、(同时创建buffer_headcache用户加速访问,buffer_init()) l创建页cache(内存页hash表初始化,page_cache_init()) l创建信号队列cache(signal_queue,signals_init()) l初始化内存inode表(inode_init()) l创建内存文件描述符表(filp_cache,file_table_init()) lSMP机器其余CPU(除当前引导CPU)初始化(对于没有配置SMP的内核,此函数为空,smp_init()) l启动init过程(创建第一个核心线程,调用init()函数,原执行序列调用cpu_idle()
28、等待调度,init()) l至此start_kernel()结束,基本的核心环境已经建立起来了。42l外设初始化-内核引导第二部分:linit()函数作为内核线程,首先锁定内核,然后调用do_basic_setup()完成外设及其驱动程序的加载和初始化ldo_basic_setup()返回后,init()使用execve()系统调用加载执行init程序。43Do_basic_setup():l总线初始化(比如pci_init()) l网络初始化(初始化网络数据结构,包括sk_init()、skb_init()和proto_init()三部分,在proto_init()中,将调用protocol
29、s结构中包含的所有协议的初始化过程,sock_init()) l创建bdflush核心线程(bdflush()过程常驻核心空间,由核心唤醒来清理被写过的内存缓冲区,当bdflush()由kernel_thread()启动后,它将自己命名为kflushd) l创建kupdate核心线程(kupdate()过程常驻核心空间,由核心按时调度执行,将内存缓冲区中的信息更新到磁盘中,更新的内容包括超级块和inode表) l设置并启动核心调页线程kswapd(为了防止kswapd启动时将版本信息输出到其他信息中间,核心线调用kswapd_setup()设置kswapd运行所要求的环境,然后再创建 kswa
30、pd核心线程) 44l创建事件管理核心线程(start_context_thread()函数启动context_thread()过程,并重命名为keventd) l设备初始化(包括并口parport_init()、字符设备chr_dev_init()、块设备 blk_dev_init()、SCSI设备scsi_dev_init()、网络设备net_dev_init()、磁盘初始化及分区检查等等,device_setup()) l执行文件格式设置(binfmt_setup()) l启动任何使用_initcall标识的函数(方便核心开发者添加启动函数,do_initcalls()) l文件系统初始
31、化(filesystem_setup()) l安装root文件系统(mount_root())l加载INIT程序45linit()函数到此结束,内核的引导部分也到此结束了,这个由start_kernel()创建的第一个线程已经成为一个用户模式下的进程了。此时系统中存在着六个运行实体:lstart_kernel()本身所在的执行体,这其实是一个手工创建的线程,它在创建了init()线程以后就进入cpu_idle()循环了,它不会在进程(线程)列表中出现 linit线程,由start_kernel()创建,当前处于用户态,加载了init程序 lkflushd核心线程,由init线程创建,在核心态运
32、行bdflush()函数 lkupdate核心线程,由init线程创建,在核心态运行kupdate()函数 lkswapd核心线程,由init线程创建,在核心态运行kswapd()函数 lkeventd核心线程,由init线程创建,在核心态运行context_thread()函数46linit进程和inittab脚本linit进程是系统所有进程的起点,它的进程号是1 linit进程到底是什么可以通过内核参数“init=XXX”设置 l通常,init进程是在根目录下的linuxrc脚本文件。 47#!/bin/shecho Setting up RAMFS, please wait . /bin
33、/mount -n -t ramfs ramfs /etc/tmp/bin/mount -n -t ramfs ramfs /etc/var/bin/mount -n -t ramfs ramfs /root/bin/cp -a /mnt/var/* /etc/var#/bin/cp -a /mnt/root/* /rootecho done and exitingexec /sbin/init48l/sbin/init程序需要读取/etc/inittab文件。linittab是以行为单位的描述性(非执行性)文本,每一个指令行都具有以下格式:id:runlevel:action:process
34、49lrc启动脚本:rc.sysinit中最常见的动作就是激活交换分区,检查磁盘,加载硬件模块lShell的启动 506 ARM-Linux进程管理和调度进程管理和调度 lLinux进程有5种状态,分别是:lTASK_RUNNING lTASK_INTERRUPTIBLE lTASK_UNINTERRUPTIBLE lTASK_ZOMBIE lTASK_STOPPED 516.1 Linux进程的创建、执行和消亡进程的创建、执行和消亡 l1. Linux进程的创建 l系统的第一个真正的进程,init内核线程(或进程)的标志符为1 l新进程通过克隆老进程或当前进程来创建,系统调用fork或clo
35、ne可以创建新任务 l复制完成后,Linux允许两个进程共享资源而不是复制各自的拷贝 52l2. Linux进程的执行 l要让若干新进程按照需要处理不同的事情,就必须通过系统调用exec l函数sys_execve将可执行文件的名字从用户空间取入内核空间以后就调用do_execve( )执行具体的操作 53ldo_execve( )执行的流程: l打开可执行文件,获取该文件的 file结构。l获取参数区长度,将存放参数的页面清零。l对linux_binprm结构的其它项作初始化 l通过对参数和环境个数的计算来检查是否在这方面有错误 l调用prepare_binprm() 对数据结构linux_
36、binprm作进一步准备 l把一些参数(文件名、环境变量、文件参数)从用户空间复制到内核空间 l调用search_binary_handler(),搜寻目标文件的处理模块并执行 54l3. Linux进程的消亡 l进程终止由可终止进程的系统调用通过调用do_exit()实现 ldo_exit(long code)带一个参数code,用于传递终止进程的原因 55l以下情况要调用do_exit()函数:l具体对应的系统调用出错,不得不终止进程 ,如:ldo_page_fault() lsys_sigreturn() lsetup_frame()lsave_v86_state()l其他终止进程的情况
37、,通过调用以下函数实现终止:sys_exit() sys_reboot() do_signal() 56lLINUX系统进程的切换包括三个层次:l用户数据的保存:l正文段、数据段、栈段、共享内存段 l寄存器数据的保存lPC、PSW、SP、PCBP、FP l系统层次的保存 lproc、u、虚拟存储空间管理表格、中断处理栈576.2 ARM-Linux进程的调度 lLinux进程调度由函数schedule()实现的,其基本流程可以概括为五步:l清理当前运行中的进程l选择下一个投入运行的进程l设置新进程的运行环境l执行进程上下文切换l后期整理lLinux调度的时机有两种:l在内核应用中直接调用sch
38、edule() l被动调用schedule() 587. Linux的模块机制 lLinux中的可加载模块(Module)是 Linux内核支持的动态可加载模块 lInsmodlrmmod lLinux module载入内核后,它就成为内核代码的一部分 l若某个module空闲,用户便可将它卸载出内核 59l与module相关的命令有: llsmod 把现在 kernel 中已经安装的modules 列出来linsmod 把某个 module 安装到 kernel 中lrmmod 把某个没在用的 module 从kernel中卸载ldepmod 制造 module dependency fil
39、e,以告诉将来的 insmod 要去哪儿找modules 来安装 60lmodule 相关的数据结构主要有 :lmodule的声明如下: struct module struct module *next;struct module_ref *ref; /* the list of modules that refer to me */struct symbol_table *symtab;const char *name;int size; /* size of module in pages */void* addr; /* address of module */int state;vo
40、id (*cleanup)(void); /* cleanup routine */;61lsymbol_table的声明如下: struct symbol_table int size; /* total, including string table! */int n_symbols;int n_refs;struct internal_symbol symbol0; /* actual size defined by n_symbols */struct module_ref ref0; /* actual size defined by n_refs */;62l和module相关的系
41、统调用有: 系统调用说明Sys_create_module为模块分配空间,将模块链入系统的模块链中Sys_init_module初始化模块,修正指针使模块正常工作Sys_delete_module从系统模块链中删除模块,释放内存空间Sys_get_kernel_syms将系统的所有符号表全部取出到用户空间63 7.1 Module的使用 lModule的装入有两种方法 :l通过insmod命令手工将module载入内核 l根据需要载入module(demand loaded module) l卸载module有两种方法l用户使用rmmod命令卸载modulelkerneld自动卸载 64l2.
42、4系列内核的insmod工作的主要流程是: linsmod先调用系统调用sys_get_kernel_syms,将当前加到系统中的模块和内核的符号表全部输出到kernel_sym结构中,为后面使用。l将Mymodule目标文件读进insmod用户进程空间,成为一个映像。l根据第一步得到的信息,将Mymodule映像中的地址没有确定的函数和变量一一修正过来。l调用系统调用sys_create_module、sys_init_module,将Mymodule链入到系统中去 65实验二 Linux2.6内核移植 l2.4.18内核、2.6内核和LynuxOS 4.0在最好情况、平均情况下和最坏情况下
43、任务的响应时间比较:66实验二 Linux2.6内核移植(1)lLinux内核移植大致可以归纳成以下几个步骤:l准备工作,下载Linux2.6内核源代码和编译器源代码等l建立交叉编译环境l制作Boot Loaderl修改和编译内核l制作文件系统l编写相应的设备驱动l编写应用程序 67实验二 Linux2.6内核移植(2)l1.准备工作l下载Linux2.6.10内核源代码,可以到ftp:/ftp.kernel.org 下载 lARM Linux是基于标准Linux内核为ARM做的补丁,可以在 ftp:/ftp.arm.linux.org.uk上下载 68实验二 Linux2.6内核移植(3)l
44、2.编译交叉编译工具 l编译linux2.6内核需要gcc3.2以上的版本 ,在这次实验中在主机平台上编译arm-linux-gcc3.4.2 l修改t-linux文件,在TARGET_LIBGCC2_CFLAGS加上-D_gthr_posix_h和-Dinhibit_libc l编译安装$cd gcc-3.4.2$./configure -target=arm-linux -prefix=/arm-linux -with-headers=/root/linux-2.6.10/include -enable-languages=c -disable-shared -disable-thread
45、s$make$make install69实验二 Linux2.6内核移植(4)l3.配置Linux2.6.10内核l首先修改Makefile,把里面的 SUBARCH :=(shell uname m | sed e s/i.86/i386/ -es/sun4u/sparc64/ -e s/arm. */arm/ -e s/sa110/arm/)这一行去掉,改成SUBARCH : =arml修改编译器选项:CROSS_COMPILE =arm-linux-70实验二 Linux2.6内核移植(5)l4.编译内核 l使用make menuconfig配置内核 l在SYSTEM TYPE目录中选
46、择正确的CPU ,在Intel Imlementations选项中选择Intel DBPXA25X Development Platform。71l在Character Devices下的选上PXA Serial Port Support选项 l在General Setup下的Default Kernel command string选项中填入正确的串口名字ttyS0或ttyS1和波特率115200 72实验二 Linux2.6内核移植(6)l使用make zImage命令来编译内核,编译好的二进制的文件zImage在/linux-2.6.10/arch/arm/boot下 l把zImage拷贝到/tftpboot目录下,并下载到Xsbase255板子中运行 l这时应该可以在minicom中看到有系统启动信息输出 73l可以看到Linux2.6内核在XSBase255开发系统跑起来:74