企業(yè)網(wǎng)站導航優(yōu)化成都做整站優(yōu)化
? 7.1 ARM-Linux內(nèi)核簡介
? 內(nèi)核:是一個操作系統(tǒng)的核心。是基于硬件的第一層軟件擴充, 提供操作系統(tǒng)的最基本的功能,是操作系統(tǒng)工作的基礎,它負責管理系統(tǒng)的進程、內(nèi)存、設備驅(qū)動程序、文件和網(wǎng)絡系統(tǒng), 決定著系統(tǒng)的性能和穩(wěn)定性?,F(xiàn)代操作系統(tǒng)設計中,為減少系 統(tǒng)本身的開銷,往往將一些與硬件緊密相關的(如中斷處理程 序、設備驅(qū)動程序等)、基本的、公共的、運行頻率較高的模 塊(如時鐘管理、進程調(diào)度等)以及關鍵性數(shù)據(jù)結(jié)構(gòu)獨立開來, 使之常駐內(nèi)存,并對他們進行保護。通常把這一部分稱之為操 作系統(tǒng)的內(nèi)核。
? Linux內(nèi)核:Linux內(nèi)核的主要模塊(或組件)分以下幾個部分: 存儲管理、CPU和進程管理、文件系統(tǒng)、設備管理和驅(qū)動、網(wǎng) 絡通信,以及系統(tǒng)的初始化(引導)、系統(tǒng)調(diào)用等。
? ARM-Linux內(nèi)核:基于ARM處理器的Linux內(nèi)核。
? 7.1.1 ARM-Linux內(nèi)核和普通Linux內(nèi)核的區(qū)別(背)
– 相對于ARM Linux,我們說的普通Linux指的是x86 Linux,它們 都是Linux系統(tǒng),但是由于ARM和x86是不同的CPU架構(gòu),它們的 指令集不同,所以軟件編譯環(huán)境不同,軟件代碼一般不能互用, 一般需要進行兼容性移植。
– x86是經(jīng)典的CISC指令集,指令集復雜,功能多,串行執(zhí)行,但 是也意味著執(zhí)行效率低下,但性價比突出,所以稱為民用終端 的主流處理器內(nèi)置指令集。Intel和AMD的家用處理器都是x86指 令集。以x86為代表的CISC,理論并發(fā)線程1-2條。
– ARM是Advanced RISC Machine 的縮寫。它的指令集比RISC還要 精簡。通常使用ARM架構(gòu)處理器的機型,多為嵌入式或者便攜 機。主頻通常不高,現(xiàn)在高通公司的ARM架構(gòu)處理器有1.0GHz 的,已經(jīng)算相當高了。另外,ARM 7沿用馮·諾依曼結(jié)構(gòu);而從 ARM 9以后,就都采用了哈佛結(jié)構(gòu)。ARM的并發(fā)線程,理論上 有4條左右,處理效率較X86高不少。
? 7.1.2 ARM-Linux的版本控制
– Linux的版本號
????????? 主版本號:序號的第1位
????????? 次版本號:序號的第2位
????????? 修訂號:序號的第3位
????????? 穩(wěn)定版:序號的第2位(次版本號)為偶數(shù)
????????? 測試版:序號的第2位(次版本號)為奇數(shù)
– 查看Linux系統(tǒng)的版本號(Ubuntu)
? linux@linux-pc:~$ cat /etc/issue
– Ubuntu 18.04.4 LTS \n ? linux@linux-pc:~$ cat /etc/os-release
– NAME="Ubuntu"
– VERSION="18.04.4 LTS (Bionic Beaver)"
– ID=ubuntu
– ID_LIKE=debian
– PRETTY_NAME="Ubuntu 18.04.4 LTS"
– VERSION_ID="18.04"
– HOME_URL="https://www.ubuntu.com/"
– SUPPORT_URL="https://help.ubuntu.com/"
– BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
– PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
– VERSION_CODENAME=bionic
– UBUNTU_CODENA
?– 查看Linux內(nèi)核的版本號(Ubuntu)
? linux@linux-pc:~$ cat /proc/version
– Linux version 5.4.0-139-generic (buildd@lcy02-amd64-036) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #156~18.04.1-Ubuntu SMP Wed Jan 25 15:56:22 UTC 2023? linux@linux-pc:~$ uname-a
– Linux linux-pc 5.4.0-139-generic #156~18.04.1-Ubuntu SMP Wed Jan 25 15:56:22 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux? linux@linux-pc:~$ uname-r
– 5.4.0-139-gen
?? 7.1.3 ARM-Linux的代碼結(jié)構(gòu)
– 位于Ubuntu的/home/linux/workdir/fs3399/system/kernel/目錄下
?1.android:Android系統(tǒng)的配置
2.arch :包含和硬件體系結(jié)構(gòu)相關的代碼,每種平臺(處理器)占一個相應的目錄,如i386、 arm、arm64、powerpc、mips等
3.block:塊設備驅(qū)動程序
4.certs:存儲認證和簽名相關代碼
5.crypto:常用加密和散列算法(如AES、SHA 等),還有一些壓縮和CRC 校驗算法
6.Documentation:內(nèi)核各部分的通用解釋和注釋(文檔)
7.drivers :設備驅(qū)動程序,每個不同的驅(qū)動占用一個子目錄,如char、block、net、mtd、i2c 等
8. firmware:固件,包含了讓計算機讀取和理解從設備發(fā)來的信號的代碼
9. fs:所支持的各種文件系統(tǒng),如EXT、FAT、NTFS、JFFS2 等
10. include:頭文件,與系統(tǒng)相關的頭文件放置在include/linux子目錄下
11. init:內(nèi)核初始化代碼,著名的start_kernel() 就位于init/main.c文件中
12. ipc:進程間通信的代碼
13. kernel :內(nèi)核最核心的部分,包括進程調(diào)度、定時器等,而和平臺(處理器)相關的一部分 代碼放在arch/*/kernel 目錄下
14. lib:庫文件代碼
15. mm:內(nèi)存管理代碼,和平臺(處理器)相關的一部分代碼放在arch/*/mm 目錄下
16. net:網(wǎng)絡相關代碼,實現(xiàn)各種常見的網(wǎng)絡協(xié)議
17. samples:一些內(nèi)核編程的范例 文 件 夾
18. scripts:用于配置內(nèi)核的腳本文件
19. security:Linux安全模型的代碼
20. sound:ALSA、OSS 音頻設備的驅(qū)動核心代碼和常用設備驅(qū)動
21. tools:這個文件夾中包含了和內(nèi)核交互的工具
22. usr:實現(xiàn)用于打包和壓縮的cpio等
23. virt:此文件夾包含了虛擬化代碼,它允許用戶一次運行多個操作系統(tǒng)
23. Kbuild:這是一個設置一些內(nèi)核設定的腳本
24. Kconfig:內(nèi)核配置選項文件
25. Makefile:這個腳本是編譯內(nèi)核的主要文件,這個文件將編譯參數(shù)和編譯所需的文件和必要的 信息傳給編譯器
26. System.map:該文件可以幫助我們理解內(nèi)核編譯,它記錄了所有代碼的運行地址
27. vmlinux:是可引導的、壓縮的Linux內(nèi)核
28. vmlinux.o:是vmlinux的目標文件
?
?
? 7.2 ARM-Linux內(nèi)存管理
? 7.2.1 影響內(nèi)存管理的兩個方面
– Linux內(nèi)核對內(nèi)存的管理(Linux操作系統(tǒng)的內(nèi)存管理)
????????? 內(nèi)存管理是操作系統(tǒng)必不可少也是非常重要的一部分,包括:
????????????????① 地址映射
????????????????② 內(nèi)存空間的分配
????????????????③ 地址訪問的限制(即保護機制)
????????????????④ I/O地址的映射(I/O編址與內(nèi)存編址相同)
– ARM體系結(jié)構(gòu)對內(nèi)存的管理(MMU)
????????? MMU(存儲器管理單元)的主要作用有兩個方面:
????????????????① 地址映射
????????????????② 對地址訪問進行保護和限制
????????? MMU可以做在CPU芯片中,也可以作為一個協(xié)處理器(用協(xié)處理器實現(xiàn))
? 7.2.2 ARM-Linux的存儲機制
– 基于x86體系結(jié)構(gòu)的Linux內(nèi)核的存儲空間
? 32位地址形成4GB的虛擬地址空間,被分為兩部分:
????????① 內(nèi)核空間(系統(tǒng)空間):位于高端的1GB,屬于Linux操作系統(tǒng)
????????② 用戶空間:位于低端的3GB,屬于應用程序
?– ARM-Linux內(nèi)核的存儲空間?
? 32位地址形成4GB的虛擬地址空間,也被分為兩部分,但是內(nèi)核空間(系統(tǒng)空 間)和用戶空間的具體劃分,可以因CPU芯片和開發(fā)板(實驗箱)而有所不同
? 另外,ARM將I/O也放在內(nèi)存地址空間中
? 7.2.3 虛擬內(nèi)存
– 虛擬內(nèi)存(虛擬存儲器):是計算機系統(tǒng)內(nèi)存管理的一種技術(shù), 它使得應用程序認為它擁有連續(xù)的可用的內(nèi)存(一個連續(xù)完整的 地址空間),而實際上,它通常是被分隔成多個物理內(nèi)存碎片, 還有部分暫時存儲在外部磁盤存儲器上,在需要時進行數(shù)據(jù)交換。
– Linux虛擬內(nèi)存的實現(xiàn)需要6種機制的支持:
????????① 地址映射機制
????????② 請求頁機制
????????③ 內(nèi)存分配回收機制 ????????
????????④ 緩存和刷新機制
????????⑤ 交換機制
????????⑥ 內(nèi)存共享機制
? 7.3 ARM-Linux進程管理和調(diào)度
? 進程:也稱為任務,是一個動態(tài)的執(zhí)行過程,是處于執(zhí)行期的程序,進程是系統(tǒng)資源 分配的最小單位。
? 狹義定義:進程是正在運行的程序的實例。
? 廣義定義:進程是一個具有一定獨立功能的程序關于某個數(shù)據(jù)集合的一次運行活動。 它是操作系統(tǒng)動態(tài)執(zhí)行的基本單元,在傳統(tǒng)的操作系統(tǒng)中,進程既是基本的分配單元, 也是基本的執(zhí)行單元。
? 進程的概念主要有兩點:
????????① 進程是一個實體。每一個進程都有它自己的地址空間,一般情況下,包括文本區(qū)域(text region)、數(shù)據(jù) 區(qū)域(data region)和堆棧(stack region)。文本區(qū)域存儲處理器執(zhí)行的代碼;數(shù)據(jù)區(qū)域存儲變量和進程 執(zhí)行期間使用的動態(tài)分配的內(nèi)存;堆棧區(qū)域存儲著活動過程調(diào)用的指令和本地變量。
????????② 進程是一個“執(zhí)行中的程序”。程序是一個沒有生命的實體,只有處理器賦予程序生命時(操作系統(tǒng) 執(zhí)行之),它才能成為一個活動的實體,我們稱其為進程。
? 7.3.1 進程的表示和生命周期
– 進程描述符:用task_struct{}數(shù)據(jù)結(jié)構(gòu)表示
– 進程的狀態(tài)(重要):
????????① TASK_RUNNING:可執(zhí)行狀態(tài),進程要么正在執(zhí)行,要么準備 執(zhí)行
????????② TASK_INTERRUPTIBLE:可中斷的睡眠狀態(tài)
????????③ TASK_UNINTERRUPTIBLE:不可中斷的睡眠狀態(tài)
????????④ TASK_STOPPED:暫停狀態(tài),進程停止執(zhí)行
????????⑤ TASK_TRACED:跟蹤狀態(tài),進程被追蹤
????????⑥ EXIT_ZOMBIE:僵尸狀態(tài)的進程,表示進程被終止
????????⑦ EXIT_DEAD:進程的最終狀態(tài),進程死亡
????????⑧ TASK_DEAD:死亡
????????⑨ TASK_WAKEKILL:喚醒并殺死的進程
????????⑩ TASK_WAKING:喚醒進程
– 進程標識符:PID,Process ID(進程ID)
? 7.3.3 Linux進程的調(diào)度
– Linux進程的創(chuàng)建:
????????? 通過fork函數(shù)創(chuàng)建進程
????????? 創(chuàng)建用戶空間進程:vfork()、fork()
????????? 創(chuàng)建內(nèi)核空間進程:copy_process()、kernel_thread()、do_fork()、 sys_vfork()、sys_fork()、sys_clone()
– Linux進程的執(zhí)行:
????????? 通過exec函數(shù)執(zhí)行進程
????????? exec函數(shù)族:execl() 、execlp()、execle()、execv()、execvp()、execve()
– Linux進程的銷毀:
????????? 通過do_exit函數(shù)結(jié)束進程
? 7.3.2 Linux進程的創(chuàng)建、執(zhí)行和銷毀(重要)
– Linux是一個多進程系統(tǒng)。多進程就是指計算機同時執(zhí)行多個進程,即同 時運行多個程序。對于多進程系統(tǒng),就存在多個進程如何進行調(diào)度的問 題,包括進程調(diào)度時機和進程調(diào)度依據(jù)。
– 進程調(diào)度時機:
① 主動調(diào)度:隨時可以進行。
② 被動調(diào)度:發(fā)生在系統(tǒng)調(diào)用返回的前夕、中斷異常處理返回前、用戶態(tài)處理軟中 斷返回前。
③ 搶占式內(nèi)核:處于內(nèi)核態(tài)的進程也可能被調(diào)度出去。
– 進程調(diào)度依據(jù):
????????? 在所有處于可運行狀態(tài)的進程中,如何選擇最值得運行的進程投入運行,以下4項 是選擇的依據(jù):
????????① policy:進程的調(diào)度策略。
????????② priority:進程的靜態(tài)優(yōu)先級。
????????③ counter:進程剩余的時間片(進程的動態(tài)優(yōu)先級)。
????????④ rt_priority:用于實時進程間的選擇。
– 進程調(diào)度函數(shù):schedule()函數(shù)
????????① 主動調(diào)度:主動調(diào)用schedule()函數(shù)。
????????② 被動調(diào)度:被動調(diào)用schedule()函數(shù)。
? 7.4 ARM-Linux模塊機制
? Linux是單內(nèi)核的,單內(nèi)核最大的優(yōu)點是效率高,因為所有的內(nèi)容都集中在一起, 單內(nèi)核也有可擴展性差、可維護性差的缺點。
– 單內(nèi)核,是個很大的進程。它的內(nèi)部又能夠被分為若干模塊(或是層次或其他)。但是在運行的時候,它是個單獨的二 進制大映象。其模塊間的通訊是通過直接調(diào)用其他模塊中的函數(shù)實現(xiàn)的,而不是消息傳遞。單內(nèi)核結(jié)構(gòu)的例子:傳統(tǒng)的 UNIX內(nèi)核----例如伯克利大學發(fā)行的版本,Linux內(nèi)核。
– 微內(nèi)核結(jié)構(gòu)由一個非常簡單的硬件抽象層和一組比較關鍵的原語或系統(tǒng)調(diào)用組成,這些原語僅僅包括了建立一個系統(tǒng)必 需的幾個部分,如線程管理,地址空間和進程間通信等。微內(nèi)核的例子:AIX,BeOS,L4微內(nèi)核系列,.Mach中用于GNU Hurd和Mac OS X,Minix,MorphOS,QNX,RadiOS,VSTa,鴻蒙OS。
– 混合內(nèi)核它很像微內(nèi)核結(jié)構(gòu),只不過它的的組件更多的在核心態(tài)中運行,以獲得更快的執(zhí)行速度?;旌蟽?nèi)核實質(zhì)上是微 內(nèi)核,只不過它讓一些微核結(jié)構(gòu)運行在用戶空間的代碼運行在內(nèi)核空間,這樣讓內(nèi)核的運行效率更高些?;旌蟽?nèi)核的例 子: BeOS 內(nèi)核 ,DragonFly BSD,ReactOS內(nèi)核,Windows NT、Windows 2000、Windows XP、Windows Server 2003以 及Windows Vista等基于NT技術(shù)的操作系統(tǒng)。
– 外內(nèi)核系統(tǒng),也被稱為縱向結(jié)構(gòu)操作系統(tǒng),是一種比較極端的設計方法。 外內(nèi)核這種內(nèi)核不提供任何硬件抽象操作,但 是允許為內(nèi)核增加額外的運行庫,通過這些運行庫應用程序可以直接地或者接近直接地對硬件進行操作。外核設計還停 留在研究階段,沒有任何一個商業(yè)系統(tǒng)采用了這種設計。幾種概念上的操作系統(tǒng)正在被開發(fā),如劍橋大學的Nemesis, 格拉斯哥大學的Citrix系統(tǒng)和瑞士計算機科學院的一套系統(tǒng)。麻省理工學院也在進行著這類研究。
? 模塊機制的引入就是為了彌補這一缺點(可擴展性差、可維護性差)。
? 模塊(內(nèi)核模塊,動態(tài)可加載內(nèi)核模塊,Loadable Kernel Module,LKM)是Linux 內(nèi)核向外部提供的一個插口。
? 7.4.1 Linux模塊概述
– Linux內(nèi)核支持動態(tài)可加載模塊(Loadable Kernel Module,LKM), 模塊是內(nèi)核的一部分,模塊通常是設備驅(qū)動程序,但是并沒有編 譯到內(nèi)核里面去。
– 與模塊相關的命令:
① insmod:加載模塊
② rmmod:卸載模塊
③ lsmod:列出已經(jīng)安裝的模塊
④ depmod:產(chǎn)生模塊依賴的映射文件
⑤ modprob:根據(jù)depmod命令所產(chǎn)生的相依關系,決定要載入哪些 模塊
? 7.4.2 模塊代碼結(jié)構(gòu)
– module_test實驗驅(qū)動程序(模塊)的代碼結(jié)構(gòu):
? 頭文件
#include <linux/kernel.h>
#include <linux/module.h>
?? 模塊宏聲明
MODULE_LICENSE("GPL");
MODULE_ALIAS("hqyj:module");
MODULE_AUTHOR("HQYJ <yanfa@hqyj.com>");
MODULE_DESCRIPTION("A sample Hello World module");
?? 模塊初始化函數(shù)
static int __init hello_init(void){printk("hello init\n");return 0;}
?? 模塊退出函數(shù)
static void __exit hello_exit(void){printk("hello exit\n");}
?? 入口、出口函數(shù)設置
module_init(hello_init);
module_exit(hello_exit);
? 7.4.3 模塊的加載
– 模塊加載的兩種方式:
① 手工加載模塊:通過insmod命令將模塊加載到內(nèi)核:
– insmodmodule_test.ko:加載module_test.ko模塊
② 根據(jù)需要加載模塊到內(nèi)核:當內(nèi)核發(fā)現(xiàn)需要某個模塊時,內(nèi)核守 護進程(kerneld)加載該模塊到內(nèi)核。
? 7.4.4 模塊的卸載
– 使用rmmod命令卸載模塊:
? rmmod module_test:卸載module_test.ko模塊
– 但是當內(nèi)核在使用模塊時,該模塊是不能被卸載的。
? 7.4.5 版本依賴
– 模塊代碼一定要在連接到不同內(nèi)核版本之前重新編譯, 因為模塊是結(jié)合到某個特殊內(nèi)核版本的數(shù)據(jù)結(jié)構(gòu)和數(shù) 據(jù)原型上,不同的內(nèi)核版本的接口可能差別很大。
– 模塊依賴于內(nèi)核的版
? 7.5 ARM-Linux系統(tǒng)啟動和初始化
? 7.5.1 使用Boot Loader將內(nèi)核映像載入
– Boot Loader將Linux的內(nèi)核加載到內(nèi)存(SDRAM)后,將跳到函數(shù) start_kernel()進入初始化過程。
– start_kernel()函數(shù):位于 /home/linux/workdir/fs3399/system/kernel/init/main.c中。
? 7.5.2 內(nèi)核引導第一部分:內(nèi)核數(shù)據(jù)結(jié)構(gòu)初 始化
– start_kernel()函數(shù)中調(diào)用了一系列初始化函數(shù),以完成內(nèi)核 (Kernel)本省的設置。
– start_kernel()函數(shù)最后啟動init過程,創(chuàng)建第一個內(nèi)核線程,調(diào)用 init()函數(shù)。
? 7.5.3 內(nèi)核引導第二部分:外設初始化
– init()函數(shù)作為內(nèi)核線程,首先鎖定內(nèi)核,然后調(diào)用 do_basic_setup()函數(shù),完成外設及其驅(qū)動程序的加載和初始化。
? 7.5.4 init進程和inittab腳本
– init進程是系統(tǒng)所有進程的起點,內(nèi)核在完成核內(nèi)引導以后,即在 本線程(進程)空間內(nèi)加載init程序,它的進程號是1。
– init程序需要讀取Ubuntu的inittab腳本文件作為其行為指針。
? 7.5.5 rc啟動腳本
– Linux系統(tǒng)運行后將啟動rc腳本(S05rc.local)。
– rc啟動腳本(S05rc.local)位于實驗箱的/etc/rc2.d/目錄下。
? 7.5.6 Shell的啟動
– Login用戶(Ubuntu和實驗箱都是linux用戶)將啟動一個用戶指定的Shell,這個指 定的Shell就是/bin/bash
? Shell:俗稱殼(用來區(qū)別于核),是指“為使用者提供操作界面”的軟件(命令解析器)。
– bash:是一個為GNU計劃編寫的Unix shell。它的名字是一系列縮寫:Bourne-Again SHell — 這是關于Bourne shell(sh)的一個雙關語(Bourne again / born again)。 Bourne shell是一個早期的重要shell,由史蒂夫·伯恩在1978年前后編寫,并同 Version 7 Unix一起發(fā)布。bash則在1987年由布萊恩·??怂箘?chuàng)造。在1990年,Chet Ramey成為了主要的維護者。