1. 程式人生 > >一、內核結構

一、內核結構

pfile fonts 用戶應用 sta sock ket linux 語句 程序

1.1 內核在操作系統中的位置

  技術分享圖片

  • 用戶進程:用戶應用程序是運行在 Linux 操作系統最高層的一個龐大的軟件集合。當一個用戶程序
    在操作系統之上運行時,它成為操作系統中的一個進程。
  • 系統調用接口:在應用程序中, 可通過系統調用來調用操作系統內核中特定的過程, 以實現特定的服務。
    • 系統調用本身也是由若幹條指令構成的過程。但它與一般的過程不同,主要區別是:系統調用是運行在內核態(或叫系統態),而一般過程是運行在用戶態。在 Linux 中,系統調用是內核代碼的一部分
  • Linux內核:內核是操作系統的靈魂,它負責管理磁盤上的文件、內存,負
    責啟動並運行程序,負責從網絡上接收和發送數據包等。簡言之,內核實際是抽象的資源操
    作到具體硬件操作細節之間的接口。
  • 硬件

1.2 Linux內核抽象結構

  技術分享圖片

  (1)進程調度(SCHED)控制著進程對 CPU 的訪問。當需要選擇下一個進程運行時,由調度程序選擇最值得運行的進程。可運行進程實際是僅等待 CPU 資源的進程,如果某個進程在等待其他資源,則該進程是不可運行進程。Linux 使用了比較簡單的基於優先級的進程調度算法選擇新的進程

  (2)內存管理(MM)允許多個進程安全地共享主內存區域。Linux 的內存管理支持虛擬內存,即在計算機中運行的程序,其代碼、數據和堆棧的總量可以超過實際內存的大小,操 作系統只將當前使用的程序塊保留在內存中,其余的程序塊則保留在磁盤上。必要時,操作

系統負責在磁盤和內存之間交換程序塊。

  內存管理從邏輯上可以分為硬件無關的部分和硬件相關的部分。硬件無關的部分提供了進程的映射和虛擬內存的對換;硬件相關的部分為內存管理硬件提供了虛擬接口。

  (3)虛擬文件系統(Virtul File System,VFS)隱藏了各種不同硬件的具體細節,為所有設備提供了統一的接口,VFS 還支持多達數十種不同的文件系統,這也是 Linux 較有特色的一部分

  虛擬文件系統可分為邏輯文件系統和設備驅動程序。邏輯文件系統指 Linux 所支持的文件系統,如 ext2,fat 等,設備驅動程序指為每一種硬件控制器所編寫的設備驅動程序模塊。

  (4)網絡接口(NET)提供了對各種網絡標準協議的存取和各種網絡硬件的支持。網絡

接口可分為網絡協議和網絡驅動程序兩部分。網絡協議部分負責實現每一種可能的網絡傳輸協議,網絡設備驅動程序負責與硬件設備進行通信,每一種可能的硬件設備都有相應的設備驅動程序。

  (5)進程間通信(IPC) 支持進程間各種通信機制。

1.3 內核源代碼目錄結構

  include/目錄包含了建立內核代碼時所需的大部分包含文件,這個模塊利用其他模塊重建內核。

  init/ 子目錄包含了內核的初始化代碼,這是內核開始工作的起點。

  arch/子目錄包含了所有硬件結構特定的內核代碼

  drivers/ 目錄包含了內核中所有的設備驅動程序

  fs/ 目錄包含了所有文件系統的代碼

  net/ 目錄包含了內核的連網代碼

  mm/ 目錄包含了所有的內存管理代碼

  ipc/ 目錄包含了進程間通信的代碼

  kernel/ 目錄包含了主內核代碼

1.4 內核源碼讀法

1.4.1 系統的啟動和初始化

  當u-boot 把內核裝入到內存中後,並把控制權傳遞給內核時,內核開始啟動。啟動可以看 arch/*/kernel/head.S,head.S進行特定結構的設置,然後跳轉到 init/main.c 中執行。

1.4.2 內存管理

  內存管理的代碼主要在 /mm 中,特定結構的代碼在 arch/*/mm。缺頁中斷處理的代碼在 /mm/memory.c,內存映射和頁高速緩存器的代碼在 mm/filemap.c 。緩沖器高速緩存是在mm/buffer.c 中實現,而交換高速緩存是在 mm/swap_state.c 和 mm/swapfile.c 中實現。

1.4.3 內核

  內核中,特定結構的代碼在 arch/*/kernel,調度程序在 kernel/sched.c,fork 的代碼在 kernel/fork.c,task_struct 數據結構在 include/linux/sched.h 中。

1.4.4 PCI

  PCI 偽驅動程序在 drivers/pci/pci.c ,其定義在 include/linux/pci.h。

1.4.5 進程間通信

  所有 System V IPC 對象權限都包含在 ipc_perm 數據結構中,這可以在include/linux/ipc.h 中找到, System V 消息是在 ipc/msg.c 中實現, 共享內存在 ipc/shm.c 中,信號量在 ipc/sem.c 中,管道在 ipc/pipe.c 中實現。

1.4.6 中斷處理

  內核的中斷處理代碼是幾乎所有的微處理器所特有的。

1.4.7 設備驅動程序

  Linux 內核源代碼的很多行是設備驅動程序。Linux 設備驅動程序的所有源代碼都保存在/driver,根據類型可進一步劃分為:
  /block
    塊設備驅動程序如 ide(在 ide.c)。如果想看包含文件系統的所有設備是如何被初始化的,應當看 drivers/block/genhd.c 中的 device_setup(),device_setup()不僅初始化了硬盤,當一個網絡安裝 nfs 文件系統時,它也初始化網絡。塊設備包含了基於 IDE 和 SCSI的設備。
  /char
    這是看字符設備(如 tty,串口及鼠標等)驅動程序的地方。
  /cdrom
    Linux 的所有 CDROM 代碼都在這裏, 如在這兒可以找到 Soundblaster CDROM 的驅動程序。
    註意 ide CD 的驅動程序是 ide-cd.c,放在 drivers/block;SCSI CD 的驅動程序是 scsi.c,放在 drivers/scsi。
  /pci
    這是 PCI 偽驅動程序的源代碼,在這裏可以看到 PCI 子系統是如何被映射和初始化的。
  /scsi
    在這裏可以找到所有的 SCSI 代碼及 Linux 所支持的 scsi 設備的所有設備驅動程序。
  /net
    在這裏可以找到網絡設備驅動程序,如 DECChip 21040 PCI 以太網驅動程序在 tulip.c 中。
  /sound
    這是所有聲卡驅動程序的所在地。

1.4.8 文件系統

  EXT2 文件系統的源代碼全部 在 fs/ext2/ 目錄下,而其數據結構的定義在 include/linux/ ext2_fs.h,ext2_fs_i.h 及 ext2_fs_sb.h 中。虛擬文件系統的數據結構在 include/linux/fs.h 中描述,而代碼是在 fs/* 中。 緩沖區高速緩存與更新內核的守護進程的實現是在 fs/buffer.c 中。

1.4.9 網絡

  網絡代碼保存在/net 中,大部分的 include 文件在 include/net 下,BSD 套節口代碼在 net/socket.c 中,IP 第 4 版本的套節口代碼在 net/ipv4/af_inet.c。
  一般的協議支持代碼(包括 sk_buff 處理例程)在 net/core 下,TCP/IP 聯網代碼在 net/ipv4 下,網絡設備驅動程序在/drivers/net 下。

1.4.10 模塊

  內核模塊的代碼部分在內核中,部分在模塊包中,前者全部在 kernel/modules.c 中,而數據結構和內核守護進程 kerneld 的信息分別在 include/linux/module.h 和include/linux/kerneld.h 中。
  如果想看 ELF 目標文件的結構,它位於 include/linux/elf.h 中。

1.5 zImage生成過程

  通過內核初始化、內核配置、內核構建、內核安裝過程,形成Linux內核並處於可啟動狀態。

  技術分享圖片

1.5.1 內核初始化

  make distclean:執行 mrproper 命令,清除內核編譯後生成的所有對象文件、備份文件等。

  make mrproper:只清除包括 .config 文件在內的、為內核編譯及鏈接而生成的諸多設置文件。

  這兩個命令可以使內核恢復到剛解壓的狀態。

  make clean:刪除大多數生成的文件,留下編譯的擴展模塊。

  頂層的 Makefile 中可以查看到這三個命令

  技術分享圖片

1.5.2 內核配置

  • 內核配置的三個工具:
    • make xconfig
    • make menuconfig
    • make gconfig
  • 在 scripts/Kconfig/Makefile 中可以查看到這些對象,各對象會執行與之對應的二進制文件。

  技術分享圖片

  • 也可以使用 arch/$ARCH/configs 下的默認配置文件,進行修改。執行 make xxx_defconfig,就會生成 .config文件。
  • .config 文件是只構建自身內核所需的內核配置目錄。在 CONFIG_XXX變量值中用y、n、m這三個狀態進行內核配置的目錄。這種形態的內核配置系統叫做 kconfig 。根據 kconfig 提供的三個狀態(y n m)決定是否構建內核。
    • y:相應的二進制文件與 vmlinux 鏈接
    • n:不構建
    • m:雖然不會和 vmlinux 鏈接,但是作為模塊執行編譯。
  • mconf 通過 .config 配置文件生成 autoconf.h 頭文件。可通過 scripts/kconfig/confdata.c 的conf_write_autoconf 函數得知 autoconf.h 的生成過程  
  • 內核利用以 .config 文件為背景生成的 autoconf.h 文件,在預處理階段決定是否包含#ifdef 中的語句

1.5.3 內核構建

  • 構建內核是指編譯內核並鏈接二進制文件,由此生成一個二進制文件 zImage 的過程。
  • 從頂端的 Makefile 開始編譯內核,並通過因 Kbuild 系統而存在的 script 目錄上的多個腳本文件生成 zImage 。

  技術分享圖片

  技術分享圖片

  技術分享圖片

  技術分享圖片

  技術分享圖片

  KBUILD_IMAGE 的變量名為 zImage,最後執行 arch/arm/boot/Makefile 中的 Makefile 對象,如下:

  技術分享圖片

  $(call if_changed,objcopy) 將執行script/Makefile.lib 中聲明的 cmd_objcopy 。

  技術分享圖片

  技術分享圖片

  接著執行 arch/arm/boot/compressed/Makefile:

  技術分享圖片

  生成 vmlinux 的映像結構如下:

  技術分享圖片

  zImage的生成過程:

  技術分享圖片

  

1.5.4 內核安裝

  技術分享圖片

  

  

一、內核結構