linux内核C阶段分析(一)

今天开始就进入C语言阶段了

 

Asmlinkage

#define asmlinkage CPP_ASMLINKAGE

#ifdef __cplusplus

#define CPP_ASMLINKAGE extern "C"

#else

#define CPP_ASMLINKAGE

#endif

 

还有一种说法是

#define asmlinkage  __attribute__((regparm(0))) 作用是不使用寄存器传递参数,强制让参数走堆栈

 

__init

kernel-3.4.39\include\linux\init.h

#define __init        __section(.init.text) __cold notrace

用于告诉编译器相关函数或变量仅用于初始化。

编译器将标__init的所有代码存在特殊的内存段中,初始化结束后就释放这段内存。

 

 

lockdep_init();

kernel-3.4.39\include\linux\lockdep.h

# define lockdep_init()                       do { } while (0)

检测死锁模块

 

 

smp_setup_processor_id();  判断内核运行在那个物理核心上

kernel-3.4.39\arch\arm\kernel\setup.c

 

debug_objects_early_init();  

kernel-3.4.39\include\linux\debugobjects.h

static inline void debug_objects_early_init(void) { }

在早期引导期间调用,以初始化散列并将静态对象池对象链接到轮询列表中。

这个调用之后,对象跟踪器就完全可以运行了。这个模块是个通用的调试框架,用来跟踪object的生命周期。

使用这个宏打开和关闭这个功能 CONFIG_DEBUG_OBJECTS

如果开启了这个功能会该函数的作用就是初始化obj_hash(hash锁)、obj_static_pool(静态对象池)这两个全局变量

 

boot_init_stack_canary();

\kernel-3.4.39\include\linux\stackprotector.h

static inline void boot_init_stack_canary(void)

{

}

通过宏CONFIG_CC_STACKPROTECTOR控制打开和关闭

该函数主要用于初始化“金丝雀“——canary的值。

用于防止栈溢出攻击。

通常採用两种方法防止栈缓冲溢出:

1 发生栈缓冲溢出时将其检測出来。从而阻止通过恶意代码更改指令指针;

2 未直接检測栈缓冲溢出的情况下,预防恶意代码攻击。

stack canary技术属于第一中方法的一种。在恶意代码运行前,可以发现栈缓冲溢出。

 

cgroup_init_early();

kernel-3.4.39\kernel\cgroup.c

cgroup_init_early—在系统启动时初始化cgroup

在系统启动时初始化cgroup,并初始化任何早期初始化请求的子系统。

cgroup就是control group,就是将一个或者多个task组成一个group,cgroup对这个group的资源进行控制。具体实现依赖于具体的cgroup sub system的实现。

为啥要开发cgroup呢? 打个比方你们组的成员公用一台服务器,现在某个人需要编译代码“make -j 20",然后服务器开始编译代码,其余人的体验就变差,变得很卡,影响工作。

你这时候就会想是不是可以给每个人分配一个最大资源的限制,这样一个人编译代码不会影响到别人的工作。cgroup就是这个用途。

 

local_irq_disable();

功能是屏蔽当前CPU上的所有中断

 

early_boot_irqs_disabled = true;

通过一个静态全局变量 early_boot_irqs_enabled来帮助我们调试代码,通过这个标记可以帮助我们知道是否在”early bootup code”,也可以通过这个标志警告是有无效的终端打开。

 

 

tick_init();

kernel-3.4.39\kernel\time\tick-common.c

void __init tick_init(void)

{

       clockevents_register_notifier(&tick_notifier);

}

内核通知链机制初始化tick控件

用clockevents框架注册通知程序

 

boot_cpu_init();

kernel-3.4.39\init\main.c

对于CPU核的系统来说,设置第一个CPU核为活跃

 

page_address_init();

kernel-3.4.39\mm\highmem.c

初始化内存页链表的地址

 

printk(KERN_NOTICE "%s", linux_banner);

kernel-3.4.39\init\version.c

const char linux_banner[] =

       "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"

       LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";

打印linux_banner的信息

 

setup_arch(&command_line);

kernel-3.4.39\arch\arm\kernel\setup.c

start_kernel阶段最重要的一个函数

内存初始化

 

mm_init_owner(&init_mm, &init_task);

kernel-3.4.39\kernel\fork.c

void mm_init_owner(struct mm_struct *mm, struct task_struct *p)

{

       mm->owner = p;

}

通过宏CONFIG_MM_OWNER控制

全部任务都具有自己的内存,启动阶段中的当前任务必须具备属于自己的内存。

 

mm_init_cpumask(&init_mm);

kernel-3.4.39\include\linux\mm_types.h

static inline void mm_init_cpumask(struct mm_struct *mm)

{

#ifdef CONFIG_CPUMASK_OFFSTACK

       mm->cpu_vm_mask_var = &mm->cpumask_allocation;

#endif

}

通过宏CONFIG_CPUMASK_OFFSTACK控制

当CONFIG_CPUMASK_OFFSTACK=y时cpumasks不再放在堆栈上。

当CONFIG_CPUMASK_OFFSTACK=n时cpumask_var_t为struct cpumask[1](而且alloc_cpumask_var等为空操作)。

 

 

setup_command_line(command_line); 初始化命令行

kernel-3.4.39\init\main.c

我们需要存储未触及的命令行,以备将来参考。

我们还需要存储触摸命令行,因为参数解析是在适当的位置执行的,我们应该允许组件存储名称/值的引用,以供将来引用。

 

setup_nr_cpu_ids();

kernel-3.4.39\init\main.c

void __init setup_nr_cpu_ids(void)

{

       nr_cpu_ids = find_last_bit(cpumask_bits(cpu_possible_mask),NR_CPUS) + 1;

}

 

先到这里,吃饭去喽~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值