惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recent Announcements
Recent Announcements
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog
T
The Blog of Author Tim Ferriss
J
Java Code Geeks
腾讯CDC
D
Docker
G
Google Developers Blog
D
DataBreaches.Net
雷峰网
雷峰网
Blog — PlanetScale
Blog — PlanetScale
S
SegmentFault 最新的问题
The Cloudflare Blog
有赞技术团队
有赞技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Stack Overflow Blog
Stack Overflow Blog
大猫的无限游戏
大猫的无限游戏
量子位
美团技术团队
aimingoo的专栏
aimingoo的专栏
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Engineering at Meta
Engineering at Meta
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - Wu.Country@侠缘

用户中心 - 博客园 [Linux]OpenSuse12图形和文字界面转换 haneWIN NFS Server An Introduction to the Linux-based Assignments Booting Linux with U-Boot on QEMU ARM Using The mkimage Tool To Create U-Boot Images SUSE安全大揭秘之“十诫” [Copy]如何使用qemu执行交叉环境下的内核镜像文件 CT-NG编译错误以及解决办法 无法忍受在SUSE10上安装开发环境了 Windows的路由命令 【CLFS】记录: [读书笔记]Binary Hancks(2) livepatch在X86下的实践 [读书笔记]Binary Hancks(1) ARM Stack Unwinding Physical Address Extension - PAE Memory and Windows 如何制作grub启动光盘 [译]Kernel Memory Layout on ARM Linux [转]ucLinux下sqlite数据库移植全攻略
Linux内核代码学习笔记(2.6.21.7 ARM) -- 内核启动函数start_...
Wu.Country@侠缘 · 2010-11-15 · via 博客园 - Wu.Country@侠缘

其实对内核的代码已经分析很久了,早就想自己写些什么,从今天开始,从新继续我的博客!

这几年都在与Linux打交道了,而且我觉得我也真正的爱上了Linux,所以就写些Linux的东西吧!

Linux的东西很多,就内核而言,已经无法一个人去了解所有的机制和细节了。但好在源码是可以随时取到的,只要你熟悉和了解内核的一些基本特性,还是可以很容易上手的!

下面,我就把我自己的一些学习经历写出来和大家分享一下!

首选,内核代码里有大小写重名的文件,所以,从网上下载了内核源码包以后,不能直接在Windows下解压,否则会有些文件被大小写重复的文件名复盖掉!主要是网络相关的。我暂时先不想了解网络相关的内容,所以,就先在Windows下,使用SourceInsight来看代码!如果要看到全部的代码,还是要在Linux系统下解压代码!

另外,我对X86体系结构的代码也暂时不感兴趣,先从ARM入手,不过不同的体系结构,关系并不太大,明白一些机制以后,大部份是一样的!

先从第一个函数入手:

E:\Projects\kernel\linux-2.6.21.1.src\init\main.c (501/825)

asmlinkage void __init start_kernel(void);

这个函数是内核由引导程序引导以后,由自解压程序解压以后执行的第一个函数,可以认为是整个内核的入口函数,以后我分析的代码全部从这个函数开始!

这个函数做的事情相对比较简单,就是线性的初始化一些内核的基础机制,如中断,内存管理,进程管理,信号,文件系统,KO等!最后就启动一个init线程,init线程再读取文件系统里的init程序,做为系统的第一个进程而存在!

其实,start_kernel函数是0是做为0号进程存在的,它在最后就是空转CPU:

代码

/*
 * The idle thread.  We try to conserve power, while trying to keep
 * overall latency low.  The architecture specific idle is passed
 * a value to indicate the level of "idleness" of the system.
 
*/
void cpu_idle(void)
{
    local_fiq_enable();
/* endless idle loop with no priority at all */
    
while (1) {
        
void (*idle)(void= pm_idle;

#ifdef CONFIG_HOTPLUG_CPU

if (cpu_is_offline(smp_processor_id())) {
            leds_event(led_idle_start);
            cpu_die();
        }
#endifif (!idle)
            idle 
= default_idle;
        leds_event(led_idle_start);
        
while (!need_resched())
            idle();
        leds_event(led_idle_end);
        preempt_enable_no_resched();
        schedule();
        preempt_disable();
    }
}

而在它之前,启动的init线程,则是运行文件系统里的init程序:

代码

/* This is a non __init function. Force it to be noinline otherwise gcc
 * makes it inline to init() and it becomes part of init.text section
 
*/
static int noinline init_post(void)
{
    free_initmem();
    unlock_kernel();
    mark_rodata_ro();
    system_state 
= SYSTEM_RUNNING;
    numa_default_policy();
if (sys_open((const char __user *"/dev/console", O_RDWR, 0< 0)
        printk(KERN_WARNING 
"Warning: unable to open an initial console.\n");

    (

void) sys_dup(0);
    (
void) sys_dup(0);if (ramdisk_execute_command) {
        run_init_process(ramdisk_execute_command);
        printk(KERN_WARNING 
"Failed to execute %s\n",
                ramdisk_execute_command);
    }
/*
     * 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) {

  /* 如果有启动参数做为执行命令,就执行 */
        run_init_process(execute_command);
        printk(KERN_WARNING 
"Failed to execute %s.  Attempting "
                    
"defaults...\n", execute_command);
    }

  /* 依次查询文件系统里的init程序,这里的run_init_process函数不能返回,否则启动失败 */
    run_init_process(
"/sbin/init");
    run_init_process(
"/etc/init");
    run_init_process(
"/bin/init");
    run_init_process(
"/bin/sh");

    panic(

"No init found.  Try passing init= option to kernel.");
}

 因为内核为很多体系结构的CPU实现具体的函数,所以一个函数可能在很多目录里的同名文件所实现。在查询是具体的哪个函数时,要对应的具体的体系结构。如果对应的具体体系结构里没有相关函数,就可在使用通用的函数或者通用的体系结构里的函数!

================================
  /\_/\                        
 (=^o^=)  Wu.Country@侠缘      
 (~)@(~)  一辈子,用心做一件事!
--------------------------------
  学而不思则罔,思而不学则怠!  
================================