很是好!!!Linux源代碼閱讀——環境準備【轉】

Linux源代碼閱讀——環境準備

轉自:http://home.ustc.edu.cn/~boj/courses/linux_kernel/0_prepare.htmlphp

目錄

  1. Linux 系統環境準備
    • 定製安裝 Ubuntu
    • 安裝工具鏈
  2. 編譯 Linux 內核
    • 默認編譯
    • 自定義編譯
  3. 模擬執行 Linux
    • 用 qemu 模擬 Hello World 系統
  4. 準備源碼閱讀環境
    • vim 基本設置
    • 在 vim 中使用 cscope
    • 在 vim 中使用 ctags
    • 使用 taglist 顯示 symbol 窗口
  5. Linux 內核源代碼結構

1 Linux系統環境準備

1.1 定製安裝Ubuntu

  1. 從科大源下載 Ubuntu Alternative CD,校驗 MD5。
  2. 掛載 ISO,使用 preseed 文件來進行一些預約制,參考 http://pxe.ustc.edu.cn/boot/conf/preseed.debian.ustc.cfg(固然其中的 debian 須要改成 ubuntu,hostname 改爲本身但願的主機名),指定安裝所使用的源,以及其餘一些預約義設置。
  3. 卸載ISO,使用 usb-creator-gtk 製做啓動U盤。
  4. 使用 parted 分區:將硬盤的一個空閒 NTFS 分區刪除;mkpartfs 創建一個ext2(用於/boot)、一個swap、一個ext4(用於根分區)。
  5. 從U盤啓動,選擇 Install a command-line system,設置鍵盤、分區等(其餘設置已經寫在 preseed 中了),安裝基本系統,設置用戶名密碼。
  6. grub-mkimage 製做包含 reiserfs 模塊的 grub2(原有的 linux 所在分區是 reiserfs 的),grub-mkconfig 更新 grub.cfg 配置文件。
  7. 安裝 X(xserver-xorg)、GNOME 桌面環境(gdm、gnome-core、xinit、gnome-utils、synaptic)
  8. 安裝中文語言包(language-pack-zh-base、language-support-fonts-zh、xfonts-wqy、language-selector),修改 locale
  9. 安裝輸入法(fcitx)、vim等
  10. 安裝、設置聲卡驅動(alsa)(特定硬件的驅動問題,採用網上的辦法)
  11. 安裝 ntfs-3g、wine 等系統工具,tcpdump、firefox、filezilla、amule 等網絡工具,okular、chmsee、libreoffice 等辦公工具
  12. 安裝 ssh、nginx、php5-fpm、MySQL、memcached、vsftpd 等服務器須要的 daemon(網絡開發用)
  13. apt-get clean 清除緩存
  14. 編輯 /etc/modules,開機加載 fuse(用戶態文件系統)模塊,以便使用 ntfs-3g
  15. 編輯 /etc/fstab 將 /dev/sda4(NTFS)自動掛載上,爲方便 Windows 使用,學習資料等數據放在這個分區。
    # <file system> <mount point>   <type>  <options>       <dump>  <pass>
    proc            /proc           proc    nodev,noexec,nosuid 0       0
    # / was on /dev/sda2 during installation
    UUID=d993c54c-0602-48d2-935f-be9ac654f9a0 /               ext4    errors=remount-ro 0       1
    /dev/sda1       none            swap    sw              0       0
    /dev/sda4	/media/DATA	ntfs-3g	silent,umask=0,locale=zh_CN.utf8	0	0
    

1.2 安裝工具鏈

  • 編譯內核所需工具鏈:
    • build-essential (gcc, make, ld等)
    • binutils
    • libncurses-dev (make menuconfig 時須要)
    • kernel-package
  • 模擬內核所需工具:
    • qemu
    • gdb
    • fakeroot (chroot)
    • initramfs-tools
    • module-init-tools

2 編譯Linux內核

2.1 默認編譯

  1. 從 kernel.org 下載 Linux 2.6.26 源碼,tar -zvxf
  2. make mrproper 清除全部已編譯文件和配置文件
  3. make i386_defconfig 生成x86體系結構的默認配置。此過程首先HOSTCC、SHIPPED、HOSTLD一些配置文件,而後進入 Linux Kernel Configuration,與 make config 的命令行界面相同,只是全部選項都被自動選擇了(具體參見 arch/x86/configs/i386_defconfig)。
  4. make 編譯代碼。由CC、LD、AR、AS、GEN、HOSTCC、OBJCOPY、BUILD等過程組成。其中有一些 warning,是由於代碼不符合當前C標準,能夠忽略。
    BUILD   arch/x86/boot/bzImage
    Root device is (8, 2)
    Setup is 10140 bytes (padded to 10240 bytes).
    System is 2651 kB
    CRC e3791c7
    Kernel: arch/x86/boot/bzImage is ready  (#1)
    

2.2 自定義編譯

  1. 每次更改配置從新編譯前,make clean 清除上次編譯的目標文件和中間文件,但保留配置文件以便在其基礎上修改。
  2. make menuconfig 進入終端下的菜單選擇。相比徹底命令行界面的 config,用起來更方便;而圖形界面的 xconfig 或 gconfig 雖然比較直觀,但不便於使用鍵盤。
  3. 設置完畢,保存到 .config
  4. make 編譯代碼,生成的內核映像是 arch/x86/boot/bzImage
    Root device is (8, 2)
    Setup is 10140 bytes (padded to 10240 bytes).
    System is 3063 kB
    CRC aa68b290
    Kernel: arch/x86/boot/bzImage is ready  (#3)
      Building modules, stage 2.
      MODPOST 26 modules
    
  5. 因爲咱們是在虛擬機內運行而不是安裝到本地系統,所以不須要 make install

具體設置參考:Linux 2.6.19.x 內核編譯配置選項簡介(金步國)html

  • General Setup
    • 爲 local version 賦予一個唯一的自定義版本號(如boj1),以避免不一樣的內核發生混淆
    • 選中 Auditing Support,以方便之後試驗 SELinux
    • 要選中 Initramfs,如今 Linux 啓動通常都用 initramfs(原來的 initrd)
  • Loadable Module Support
    • modprobe 時須要使用
    • 選中 Automatic kernel module loading,讓內核經過運行 modprobe 來自動加載所須要的模塊,自動解決模塊的依賴關係
  • Enable the block layer
    • 塊設備須要使用
    • Large Block Device 暫時不須要,沒有 2TB 以上的塊設備
  • Processor Type and Features
    • 根據 /etc/cpuinfo,當前的CPU是 Intel(R) Core(TM) Duo CPU T2250 @ 1.73GHz
      所以選擇 Core 2/Newer Xeon。
    • 因爲只在本身的計算機上使用,取消 Generic x86 support。
    • 因爲本身的CPU是雙核的,Maximum number of CPUs 設爲2,每一個CPU在內核映像中佔據8KB。
    • High Memory Support 選擇 4G(因爲內存是2.5G的)
    • Timer Frequency 因爲是桌面系統,對實時性要求較高,設爲 1000Hz。
  • Power management options
    • 選中 Hibernation,以實現休眠功能
  • Bus options
    • 選中 PCI Express Support,顯卡和網卡都須要
  • Executable file formats
    • Kernel support for MISC binaries 容許插入二進制的封裝層到內核中,使用 Java 等語言編寫的程序時須要它
  • Networking Support
    • Networking options
      • 選中 Packet Socket 和 mmaped IO,以便使用網絡監控工具。
      • 選中 TCP Syncookie support,抵抗 SYN flood 攻擊。須要同時啓用 /proc 文件系統和 Sysctl support,而後在系統啓動並掛載了 /proc 以後執行 "echo 1 >/proc/sys/net/ipv4/tcp_syncookies" 命令。
      • 選中 Network packet filtering,Netfilter 對數據包進行過濾和修改。
        • 選中 IPv4/IPv6 connection tracking support,以使用 NAT。
        • 選中 IP tables 和 ARP tables,常常須要用。其中選中 Full NAT 以便使用 iptables 中的 NAT 功能。
        • 選中 IP6 tables support,監控 IPv6 協議須要用。
      • 選中 Network Testing 中的 Packet Generator(編譯爲 pktgen 模塊),方便網絡測試。
    • 選中 Ameteur Radio Support,由於咱們要玩無線電。AX.25 協議編譯爲 ax25 模塊。
    • 將 IrDA (infrared) subsystem support 編譯爲 irda 模塊,以便使用無線鼠標鍵盤。
    • 選中 Bluetooth subsystem support,藍牙常常要用。
    • 選中 Generic IEEE 802.11 Networking Stack,wifi 等都是基於 802.11 的協議。
  • Device Drivers
    • Block Devices
      • 取消 Normal Floppy Disk support,沒有軟驅
      • 須要選中 RAM block device support,initrd 須要用。
        Menuconfig Help 中說
          │ Saying Y here will allow you to use a portion of your RAM memory as
          │ a block device, so that you can make file systems on it, read and
          │ write to it and do all the other things that you can do with normal
          │ block devices (such as hard drives). It is usually used to load and
          │ store a copy of a minimal root file system off of a floppy into RAM
          │ during the initial install of Linux.
        
        Most normal users won't need the RAM disk functionality, and can thus say N here.
        
        所以第一次配置時沒有編譯進內核,致使虛擬機沒法啓動:
        [   0.776881] Unpacking initramfs...<0>Kernel panic - not syncing: bad gzip magic numbers
    • ATA/ATAPI/MFM/RLL support
      • 取消 Include IDE/ATA-2 DISK support
    • SCSI device support
      • 選中 RAID Transport Class,未來可能折騰 RAID
    • Multiple devices driver support (RAID and LVM)
      • 將 RAID support 及相關選項編譯爲模塊,以使用軟RAID。
      • 選中 Device Mapper support,以使用 LVM。
    • 取消 Macintosh device drivers
    • Multimedia devices
      • 選中 Video for Linux,以便進行攝像頭編程
    • Sound
      • 選中 Advanced Linux Sound Architechture,計算機上的聲卡須要用 ALSA。
      • 取消 Open Sound System
    • 選中 Real Time Clock,以便獲取系統時間
    • 選中 DMA Engine Support,以便使用 Direct Memory Access
  • Firmware Drivers
    沒有特殊固件,所以保留默認配置。
  • File Systems
    • ext二、ext三、ext4 都是 Linux 經典文件系統,常常須要用到,編譯進內核
    • ReiserFS 對於小文件的處理效率很高,有個存放各類源代碼的分區用這個文件系統,編譯進內核
    • 選中 Filesystem in Userspace Support,ntfs-3g 是基於 fuse 的,這樣不用每次開機都加載 fuse 模塊。
    • 微軟文件系統:不選 NTFS 文件系統支持,內核中對於 NTFS 寫的支持很差,使用用戶態的 ntfs-3g 代替。
    • 本地語言支持:默認本地語言設爲 utf-8,選中 Codepage 437, GB2312, Big5, ASCII, ISO 8859-1, UTF-8.
  • Kernel Hacking
    • 選中 Show timing information on printks,方便內核調試
    • 選中 Magic SysRq key,在緊急狀態時使用 reisub 奪回系統控制權
  • Security Options
    暫時不須要其餘安全模型,保留默認值,全不選。
  • Cryptographic options
    將 MD五、SHA一、Blowfish、DES 等經常使用加密算法編譯爲模塊備用。
  • Virtualization
    電腦硬件不支持 KVM,所以不選。
  • Library routines
    保留默認值。

3 模擬執行 Linux

3.1 用 qemu 模擬 Hello World 系統

  1. 寫一個 Hello World 程序:
    [boj@boj-laptop:~/test]$ cat test.c
    #include<stdio.h>
    int main() {
    	printf("Hello World!");
    	return 0;
    }
    
  2. 靜態連接編譯
    [boj@boj-laptop:~/test]$ gcc -static -o init test.c
  3. 創建目標根目錄映像
    [boj@boj-laptop:~/test]$ dd if=/dev/zero of=initrd4M.img bs=4096 count=1024
    [boj@boj-laptop:~/test]$ mke2fs initrd4M.img
    [boj@boj-laptop:~/test]$ mkdir rootfs
    [boj@boj-laptop:~/test]$ sudo mount -o loop initrd4M.img rootfs
    
  4. 將init拷貝到目標根目錄下
    [boj@boj-laptop:~/test]$ cp init rootfs/
  5. 準備 /dev 目錄、console 設備、linux 根設備(ram)
    [boj@boj-laptop:~/test]$ sudo mkdir rootfs/dev
    [boj@boj-laptop:~/test]$ sudo mknod rootfs/dev/console c 5 1
    [boj@boj-laptop:~/test]$ sudo mknod rootfs/dev/ram b 1 0
    [boj@boj-laptop:~/test]$ sudo umount rootfs
    
  6. 用 qemu 模擬運行
    [boj@boj-laptop:~]$ qemu -kernel linux-2.6.26/arch/x86/boot/bzImage -initrd test/initrd4M.img -append "root=/dev/ram init=/init"
    

    一段初始化後,輸出了 Hello World,隨即 Kernel Panic(由於 init 在輸出字符串後就自行退出了)node

    [    4.270006] Freeing unused kernel memory: 244k freed
    Hello World![    4.326627] Kernel panic - not syncing: Attempted to kill init!

4 準備源碼閱讀環境

4.1 vim 基本設置

[boj@boj-laptop:~]$ cat ~/.vimrc
set encoding=UTF-8
set langmenu=zh_CN.UTF-8
language message zh_CN.UTF-8
set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1
set fileencoding=utf-8
sy on
set ai
set nu
set shiftwidth=2
set tabstop=4
set softtabstop=4
set ic "搜索時忽略大小寫,以便在某些「駱駝」變量名風格的源碼中查找

4.2 在 vim 中使用 cscope

  1. 安裝 CScope:
    sudo apt-get install cscope
  2. 確認 vim 支持 cscope:
    vim --version | grep cscope
  3. 給源代碼創建索引:
    cscope -Rbq

    其中,ctags 遞歸的在每一個目錄下生成 tags 文件,供 vim 讀取;cscope 生成 cscope.outlinux

    cscope.out: cscope reference data version 15 with inverted index
  4. 將如下內容添加到 ~/.vimrc 中,以自動加載 cscope.out。
    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    " cscope setting
    
    if has("cscope")
       set csprg=/usr/bin/cscope              "指定用來執行 cscope 的命令
       set csto=1                             "先搜索tags標籤文件,再搜索cscope數據庫
       set cst                                "使用|:cstag|(:cs find g),而不是缺省的:tag
       set nocsverb                           "不顯示添加數據庫是否成功
       " add any database in current directory
       if filereadable(ncscope.out")
          cs add cscope.out                   "添加cscope數據庫
       endif
       set csverb                             "顯示添加成功與否
    endif
    
    nmap <C-@>s :cs find s <C-R>=expand("<cword>")<CR><CR>
    nmap <C-@>g :cs find g <C-R>=expand("<cword>")<CR><CR>
    nmap <C-@>c :cs find c <C-R>=expand("<cword>")<CR><CR>
    nmap <C-@>t :cs find t <C-R>=expand("<cword>")<CR><CR>
    nmap <C-@>e :cs find e <C-R>=expand("<cword>")<CR><CR>
    nmap <C-@>f :cs find f <C-R>=expand("<cfile>")<CR><CR>
    nmap <C-@>i :cs find i ^<C-R>=expand("<cfile>")<CR>$<CR>
    nmap <C-@>d :cs find d <C-R>=expand("<cword>")<CR><CR>
    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    
  5. 根據上面的 .vimrc,使用簡單的組合鍵和字母便可使用 cscope 的查找功能。nginx

    例如,<C-@>g 先按 ctrl+@,再按 g,便可查看當前光標所在符號的定義。算法

    :cs help數據庫

    • s: 查找 C 語言符號,即查找函數名、宏、枚舉值等出現的地方
    • g: 查找函數、宏、枚舉等定義的位置,相似 ctags 所提供的功能
    • d: 查找本函數調用的函數
    • c: 查找調用本函數的函數
    • t: 查找指定的字符串
    • e: 查找 egrep 模式,至關於 egrep 功能,但查找速度快多了
    • f: 查找並打開文件,相似 vim 的 find 功能
    • i: 查找包含本文件的文件

4.3 在 vim 中使用 ctags

在源代碼根目錄下執行 ctags -R 命令用來爲程序源代碼生成標籤文件,-R 選項表示遞歸操做,同時爲子目錄也生成標籤文件。vim 利用生成的標籤文件,能夠進行相應檢索、並在不一樣的文件中的C語言元素之間來回切換。編程

須要在 tags 文件所在的目錄下運行 vim。不然,要用 :set tags=xxx 指定 tags 文件的路徑。ubuntu

使用 tag 命令時,可使用 TAB 鍵進行匹配查找,繼續按 TAB 鍵向下切換。vim

  • 跳到函數或數據結構xxx處
    :tag xxx
  • 跳到第一個定義處,優先跳轉到當前文件
    :tnext
  • 跳到第一個
    :tfirst
  • 跳到前 count 個
    :[count]tprevious
  • 跳到後 count 個
    :[count]tnext
  • 跳到最後一個
    :tlast
  • 在全部 tagname 中選擇
    :tselect tagname
  • 跳到包含 block 的標識符
    :tag /block 

    (這裏 '/' 就是告訴 vim,'block' 是一個語句塊標籤。)

  • 跳轉到光標所在函數標識符的定義處
    Ctrl+]
  • 使用"ctrl+t"退回上層
    Ctrl+t
  • 在以 write_ 開頭的標識符中選擇
    :tselect /^write_
    這裏,'^'表示開頭,同理,'$'表示末尾。

在函數中移動光標的快捷鍵:

  • [{ 轉到上一個位於第一列的"{"
  • }] 轉到下一個位於第一列的"{"
  • { 轉到上一個空行
  • } 轉到下一個空行
  • gd 轉到當前光標所指的局部變量的定義
  • * 轉到當前光標所指的單詞下一次出現的地方
  • # 轉到當前光標所指的單詞上一次出現的地方

4.4 使用 taglist 顯示 symbol 窗口

taglist 插件能夠像 Source Insight 那樣將當前文件中的宏、全局變量、函數等 tag 顯示在 Symbol 窗口,用鼠標點上述 tag,就跳到該 tag 定義的位置;能夠按字母序、該tag所屬的類或scope,以及該 tag 在文件中出現的位置進行排序;若是切換到另一個文件,Symbol 窗口更新顯示這個文件中的 tag。taglist 依賴於 ctags。

  1. 打開 vim 的文件類型自動檢測功能;
  2. 系統中裝了 Exuberant ctags 工具,而且 taglist 可以找到此工具(由於 taglist 須要調用它來生成 tag 文件);
  3. vim 支持 system() 調用;
  4. 在 ~/.vimrc 中加入
    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    " ctags setting
    set tags=./tags,./../tags,./*/tags;
    
    " Tag list (ctags)
    
    filetype on                            "文件類型自動檢測
    
    if MySys() == "windows"                "設定windows系統中ctags程序的位置
       let Tlist_Ctags_Cmd = 'ctags'
    elseif MySys() == "linux"              "設定linux系統中ctags程序的位置
       let Tlist_Ctags_Cmd = '/usr/bin/ctags'
    endif
    
    let Tlist_Show_One_File = 1            "不一樣時顯示多個文件的tag,只顯示當前文件的
    let Tlist_Exit_OnlyWindow = 1          "若是taglist窗口是最後一個窗口,則退出vim
    let Tlist_Use_Right_Window = 1         "在右側窗口中顯示taglist窗口 
      
    map <silent> <F8> :TlistToggle<cr>     "在映射F8鍵打開tags窗口
    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    

上述配置過程參考了:http://www.cnblogs.com/sunblackshine/archive/2011/08/25/2152962.html

5 Linux 內核源代碼結構

Linux 2.6.26 源碼各目錄大體做用:

  • Documentation/ 內核文檔,包括 CodingStyle 等
  • include/子目錄包含了創建內核代碼時所需的大部分包含文件,這個模塊利用其它模塊重建內核。每種體系結構有相應的子目錄。
  • init/ 子目錄包含了內核的初始化代碼,這是內核開始工做的起點。(main.c, function start_kernel)
  • arch/ 子目錄包含了全部硬件結構特定的內核代碼,在 x86 體系結構下,包括 kernel、mm、lib 等子目錄,分別是與體系結構相關的核心、內存管理、庫代碼。
  • drivers/ 目錄包含了內核中全部的設備驅動程序,如字符設備、塊設備。
  • fs/ 目錄包含了全部文件系統的代碼,如:ext二、vfat、proc。
  • net/ 目錄包含了內核的網絡代碼。
  • mm/ 目錄包含了全部的內存管理代碼。
  • ipc/ 目錄包含了進程間通訊的代碼。
  • kernel/ 目錄包含了主內核代碼
  • lib/ 目錄包含了與體系結構無關的內核庫代碼
  • modules/ 目錄包含了可動態加載的模塊。
  • Scripts/ 目錄包含了配置核心的腳本文件。

Copyright © 2012 李博傑 PB10000603

This document is available from http://home.ustc.edu.cn/~boj/courses/linux_kernel/0_prepare.html

相關文章
相關標籤/搜索