linux 内核移植(四)——Makefile和链接脚本分析

1:Makefile分析

(1) kernel的Makefile写法和规则等和uboot的Makefile是一样的,甚至Makefile中的很多内容都是一样的。

(2) kernel的Makefile比uboot的Makefile要复杂,这里我们并不会一行一行的详细分析。

(3) Makefile中只有一些值得关注的我会强调一下,其他不强调的地方暂时可以不管。

(4) Makefile中刚开始定义了kernel的内核版本号。这个版本号挺重要(在模块化驱动安装时会需要用到),要注意会查,会改。

(5) 在make编译内核时,也可以通过命令行给内核makefile传参(跟uboot配置编译时传参一样)。譬如make O=xxx可以指定不在源代码目录下编译,而到另外一个单独文件夹下编译。

(6) kernel的顶层Makefile中定义了2个变量很重要,一个是ARCH,一个是CROSS_COMPILE。ARCH决定当前配置编译的路径,譬如ARCH = arm的时候,将来在源码目录下去操作的arch/arm目录。CROSS_COMPILE用来指定交叉编译工具链的路径和前缀。

(7) CROSS_COMPILE = xxx和ARCH = xxx和O=xxx这些都可以在make时通过命令行传参的方式传给顶层Makefile。

所以有时候你会看到别人编译内核时:make O=/tmp/mykernel ARCH=arm CROSS_COMPILE=/usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-

2: 链接脚本分析

(1) 分析连接脚本的目的就是找到整个程序的entry

(2) kernel的连接脚本并不是直接提供的,而是提供了一个汇编文件vmlinux.lds.S,然后在编译的时候再去编译这个汇编文件得到真正的链接脚本vmlinux.lds。

(3) vmlinux.lds.S在arch/arm/kernel/目录下。

(4) 思考:为什么linux kernel不直接提供vmlinux.lds而要提供一个vmlinux.lds.S然后在编译时才去动态生成vmlinux.lds呢?

猜测:.lds文件中只能写死,不能用条件编译。但是我们在kernel中链接脚本确实有条件编译的需求(但是lds格式又不支持),于是乎kernel工作者找了个投机取巧的方法,就是把vmlinux.lds写成一个汇编格式,然后汇编器处理的时候顺便条件编译给处理了,得到一个不需要条件编译的vmlinux.lds。

(5) 入门在哪里?从vmlinux.lds中ENTRY(stext)可以知道入口符号是stext,在SI中搜索这个符号,发现arch/arm/kernel/目录下的head.S和head-nommu.S中都有。

(6) head.S是启用了MMU情况下的kernel启动文件,相当于uboot中的start.S。head-nommu.S是未使用mmu情况下的kernel启动文件。

时间: 2024-10-31 02:53:46

linux 内核移植(四)——Makefile和链接脚本分析的相关文章

内核移植(四)——Makefile和链接脚本分析

1:Makefile分析 (1) kernel的Makefile写法和规则等和uboot的Makefile是一样的,甚至Makefile中的很多内容都是一样的. (2) kernel的Makefile比uboot的Makefile要复杂,这里我们并不会一行一行的详细分析. (3) Makefile中只有一些值得关注的我会强调一下,其他不强调的地方暂时可以不管. (4) Makefile中刚开始定义了kernel的内核版本号.这个版本号挺重要(在模块化驱动安装时会需要用到),要注意会查,会改. (

linux 内核移植(七)——rest_init函数分析

代码在start_kernel函数运行的最后到了rest_init()函数中 1:rest_init()函数分析 (1)rest_init中调用kernel_thread函数启动了2个内核线程,分别是:kernel_init和kthreadd (2)调用schedule函数开启了内核的调度系统,从此linux系统开始转起来了. (3)rest_init最终调用cpu_idle函数结束了整个内核的启动.也就是说linux内核最终结束了一个函数cpu_idle.这个函数里面肯定是死循环. (4)简单

linux 内核移植和根文件系统的制作

1.1 Linux内核基础知识 在动手进行Linux内核移植之前,非常有必要对Linux内核进行一定的了解,下面从Linux内核的版本和分类说起. 1.1.1  Linux版本 Linux内核的版本号可以从源代码的顶层目录下的Makefile中看到,比如2.6.29.1内核的Makefile中: VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 29 EXTRAVERSION = .1 其 中的“VERSION”和“PATCHLEVEL”组成主版本号,比如2.4.2.5

【转】 linux内核移植和驱动添加(三)

原文网址:http://blog.chinaunix.net/uid-29589379-id-4708909.html 原文地址:linux内核移植和驱动添加(三) 作者:genehang 四,LED驱动的添加 1, 将led.c驱动文件拷贝到linux-3.1.4/drivers/char/目录下 [email protected]# pwd /change/linux-3.1.4/drivers/char [email protected]#  cp /mnt/hgfs/fh/driver/

linux下移植指定的二进制程序脚本

一个程序所依赖的库文件可以由:ldd  命令路径来显示 例 ldd /bin/cat  输出详解 第一行输出为库入口,非库文件 which ls|grep -v alias|grep -o'[^[:space:]]*' 脚本中调试方法 declare –i Debuglevel=1 Debuglevel={0|1} [ $Debuglevel –eq 1 ] && echo -$--. 移植脚本如下所示 #!/bin/bash # declare -i DebugLevel=0 Targe

《linux 内核完全剖析》 exit.c 代码分析笔记

exit.c 代码分析笔记 release 释放进程的函数release() 主要根据指定进程的任务数据结构指针,在任务数组中删除指定的进程指针,释放相关内存页,并立刻让内核重新调度进程的运行. void release(struct task_struct * p) //释放p指向的进程 { int i; if (!p) //常规检测p是否为0 return; if (p == current) { //不能把自己给释放了 printk("task releasing itself\n\r&q

《linux 内核完全剖析》 fork.c 代码分析笔记

fork.c 代码分析笔记 verifiy_area long last_pid=0; //全局变量,用来记录目前最大的pid数值 void verify_area(void * addr,int size) // addr 是虚拟地址 ,size是需要写入的字节大小 { unsigned long start; start = (unsigned long) addr; //把地址强制类型转换之后,赋值给start size += start & 0xfff; //取addr在当前虚拟地址中4

Linux内核中的list用法和实现分析

这些天在思考知识体系的完整性,发现总是对消息队列的实现不满意,索性看看内核里面的链表实现形式,这篇文章就当做是学习的i笔记吧.. 内核代码中有很多的地方使用了list,而这个list的用法又跟我们平时在教科书中常见的用法有很大的不同,所以有必要详细了解下这里面的门道. 内核里面的list(如没有特殊说明,下文说的list都是指内核里面的list)可称之为侵入式链表.这种list最突出的特征就是其节点中不含有任何数据,相反,list节点是嵌入到特定的数据结构中的.大家自然就会问了,这样实现有什么好

《linux 内核完全剖析》 signal.c 代码分析笔记

signal.c 代码分析笔记 sgetmask int sys_sgetmask()// 获取当前进程阻塞的信号 { returncurrent->blocked; } sys_ssetmask int sys_ssetmask(int newmask) //设置当前进程阻塞信号,确保SIGKILL 和SIGSTOP不被阻塞 { int old=current->blocked; current->blocked= newmask & ~(1<<(SIGKILL-1