[转载] linux启动分析(5)---start_kernel续

原文地址:http://www.eetop.cn/blog/html/45/11145-2154.html

 

================================

Author: taoyuetao
Email:tao_yuetao@yahoo.com.cn
Blog:http://www.eetop.cn/blog/?11145

07-05-21

================================

说完asmlinkage,开始看源代码,第一个函数:lock_kernel(),
这是为了在SMP系统下设计的,它定义在kernel/include/linux/smp_lock.h,如果是SMP系统,则会
定义CONFIG_SMP,否则lock_kernel()将是空函数,如果定义CONFIG_SMP的话,则会包含kernel/include/
asm/smplock.h头文件,lock_kernel()就定一在该文件中,首先我们来看一下smp_lock.h文件:
#ifndef CONFIG_SMP

#define lock_kernel()               do { } while(0)
#define unlock_kernel()             do { } while(0)
#define release_kernel_lock(task, cpu)      do { } while(0)
#define reacquire_kernel_lock(task)     do { } while(0)  
#define kernel_locked() 1

#else

#include <asm/smplock.h>

#endif /* CONFIG_SMP */                                  

我们的平台是单cpu的(没有定义CONFIG_SMP),所以lock_kernel是空函数,不过仍然对它进行一下说明,
如果定义了CONFIG_SMP,则include kernel/include/asm-arm/smplock.h文件,看一下该文件:
static inline void lock_kernel(void)
{
     if (!++current->lock_depth)
        spin_lock(&kernel_flag);
}

static inline void unlock_kernel(void)
{
     if (--current->lock_depth < 0)
         spin_unlock(&kernel_flag);
}
找到两个比较好的说明如下
1
kernel_flag是一个内核大自旋锁,所有进程都通过这个大锁来实现向内核态的迁移。只有
获得这个大自旋锁的处理器可以进入内核,如中断处理程序等。在任何一对lock_kernel/
unlock_kernel函数里至多可以有一个程序占用CPU。 进程的lock_depth成员初始化为-1,
在kerenl/fork.c文件中设置。在它小于0时(恒为 -1),进程不拥有内核锁;当大于或等
于0时,进程得到内核锁。
2
kernel_flag,定义为自旋锁,因为很多核心操作(例如驱动中)需要保证当前仅由一个进程执行,
所以需要调用lock_kernel()/release_kernel()对核心锁进行操作,它在锁定/解锁kernel_flag的
同时还在task_struct::lock_depth上设置了标志,lock_depth小于0表示未加锁。当发生进程切换的时候,
不允许被切换走的进程握有kernel_flag锁,所以必须调用release_kernel_lock()强制释放,同时,
新进程投入运行时如果lock_depth>0,即表明该进程被切换走之前握有核心锁,
必须调用reacquire_kernel_lock()再次锁定;

代码printk(linux_banner)将linux 的一些标语打印在内核启动的开始部分,需要说明的是虽然这是
在内核一开始运行时就打印了,但是它没有马上输出到控制台上,它只是将liunx_banner存储到printk
的内部缓冲中,因为这时printk的输出设备,一般都是串口还没有初始化,只有到输出设备初始化完毕
在缓冲中的数据才被输出,后面会看到在哪个位置linux_banner才真正输出到终端。linux_banner定义在
kernel/init/version.c中:

const char *linux_banner =
  "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
  LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "/n";

这里面的字符串定义在文件kernel/include/linux/compile.h和kernel/include/linux/version.h中,
compile.h中的内容:
#define UTS_VERSION "#1 Thu, 01 Feb 2007 13:32:14 +0800"
#define LINUX_COMPILE_TIME "13:32:14"
#define LINUX_COMPILE_BY "taoyue"
#define LINUX_COMPILE_HOST "swlinux.cecwireless.com.cn"
#define LINUX_COMPILE_DOMAIN "cecwireless.com.cn"
#define LINUX_COMPILER "gcc version 3.2.1"

version.h中的内容:
#define UTS_RELEASE "2.4.19-rmk7-pxa2"
#define LINUX_VERSION_CODE 132115
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
     
这两个文件都是在编译时候生成的,看一下kernel/Makefile文件:
include/linux/compile.h: $(CONFIGURATION) include/linux/version.h newversion
@echo -n /#`cat .version` > .ver1
     @if [ -n "$(CONFIG_SMP)" ] ; then echo -n " SMP" >> .ver1; fi
     @if [ -f .name ]; then  echo -n /-`cat .name` >> .ver1; fi
     @LANG=C echo ' '`date -R` >> .ver1
     @echo /#define UTS_VERSION /"`cat .ver1 | $(uts_truncate)`/" > .ver
     @LANG=C echo /#define LINUX_COMPILE_TIME /"`date +%T`/" >> .ver
     @echo /#define LINUX_COMPILE_BY /"`whoami`/" >> .ver
     @echo /#define LINUX_COMPILE_HOST /"`hostname | $(uts_truncate)`/" >> .ver
     @([ -x /bin/dnsdomainname ] && /bin/dnsdomainname > .ver1) || /
      ([ -x /bin/domainname ] && /bin/domainname > .ver1) || /
      echo > .ver1
     @echo /#define LINUX_COMPILE_DOMAIN /"`cat .ver1 | $(uts_truncate)`/" >> .ver
     @echo /#define LINUX_COMPILER /"`$(CC) $(CFLAGS) -v 2>&1 | tail -1`/" >> .ver
     @mv -f .ver $@
     @rm -f .ver1

include/linux/version.h: ./Makefile
     @expr length "$(KERNELRELEASE)" /<= $(uts_len) > /dev/null || /
      (echo KERNELRELEASE /"$(KERNELRELEASE)/" exceeds $(uts_len) characters >&2; false)
     @echo /#define UTS_RELEASE /"$(KERNELRELEASE)/" > .ver
     @echo /#define LINUX_VERSION_CODE `expr $(VERSION) //* 65536 + $(PATCHLEVEL) //* 256 + $(SUBLEVEL)` >> .ver
     @echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))' >>.ver
     @mv -f .ver $@
    
可以修改的参数是:
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 19
EXTRAVERSION = -rmk7-pxa2

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值