歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> 詳解Linux啟動過程中硬件模塊的加載

詳解Linux啟動過程中硬件模塊的加載

日期:2017/2/28 16:28:56   编辑:Linux教程

  閱讀Linux內核啟動代碼的直接動力是我想編寫RTL8019AS的網卡驅動程序(2.4.18內核只支持了CS8900A)。既然要寫驅動,我就想知道它是怎麼樣被加載的,好奇心驅使我先去搞定這個問題。

  拿到2.4.18的軟件包,一萬多個文件,我不知怎麼下手。所幸手頭有這麼三件工具助我入門:

  1,一塊移植好Linux的開發板,通過它可以看到Linux啟動過程打印的消息。

  2, google,網上關於Linux的資料真是太多了!!!

  3, Windows文件搜索引擎,通過它可以知道在那些文件中打印出那些消息。

  很快,我就找到了Linux啟動的總的入口,/arch/arm/boot/compressed/head.s。

  head.s完成的工作主要是底層寄存器、MMU的一些設定以及kernel的解壓縮。匯編文件中調用的C代碼大多位於該目錄下misc.c文件,比如decompress_kernel。

  當然,這部分不是重點,head執行完畢以後就跳到start_kernel(),這才是我們的重點所在,這個函數位於文件/init/main.c中。這個文件是啟動的主線!!!

  在start_kernel中,依次執行各個初始話函數,這裡具體我沒有看,一直到最後rest_init(),在這個函數裡啟動了一個init線程,而主線程自己則進入了IDLE狀態。所以我們關心一下init線程做了什麼事情,看文件最後init函數。

  在這個函數裡面,先lock_kernel,然後調用do_basic_setup,在這個函數裡面又是一堆的初始化,有一個函數要引起我們的注意:do_initcalls。看看它干了什麼:(這之後的東西在下文文件系統中講解)

以下是代碼片段:
static void __init do_initcalls(void)
  {
  initcall_t *call;
  call = &__initcall_start;
  do {
  (*call)( );
  call++;
  } while (call < &__initcall_end);
  /* Make sure there is no pending stuff from the initcall sequence */
  flush_scheduled_tasks();
  }


  很難相信,我們關心的外圍模塊的驅動就是被這一段程序加載的。怎麼回事?我們慢慢來看:

  首先看__initcall_start和__initcall_end,找遍了所有C代碼,沒有它們的定義。後來在vmLinux-armv.lds.in文件中找到了它們:

以下是代碼片段:
__initcall_start = .;
  *(.initcall.init)
  __initcall_end = .;

Copyright © Linux教程網 All Rights Reserved