6818Linux內核開發移植

Linux內核開發移植

Linux內核版本變遷及其獲得

Linux是最受歡迎的自由電腦操作系統內核, 是一個用C語言寫成, 并且符合POSIX標準的類Unix操作系統

Linux是由芬蘭黑客Linus Torvalds開發的, 目的是嘗試在英特爾x86架構上提供自由免費的類Unix操作系統

Linux操作系統的誕生、 發展、 和成長過程依賴于五個重要支柱: unix操作系統、 minix操作系統、 GNU計劃、 POSIX標準和互聯網

內核版本號從Linux1.0以后主要分為兩個階段:

Linux1.0-2.6, 數字包括四部分“ A.B.C.D”

  • A代表主版本號, 如1994年的1.0, 1996年的2.0, 2011年的3.0
  • B代表次版本號, 表示一些重大的修改, 偶數表示穩定版, 奇數表示開發版
  • C代表末版本號, 代表著一個新版本的發布(包括安全補丁、 bug修復、 新增功能、 或驅動程序), 一般數字變化范圍比較大
  • D代表一些BUG修復, 對已經加入的安全補丁、 bug修復、 新增功能或驅動程序做的微調或添加新的特性, 2.6版本之后經常出現

Linux2.6之后的版本, 數字主要包括三部分"A.B.C"或"A.B.C-rcn"

  • A代表主版本號
  • B代表次版本號, 隨著一個新版本的發布而增加, 與上一階段中的數字” C“功能類似, 但不再代表穩定與否
  • C代表穩定版本號, 如果只有數字則代表穩定版本, 如果帶"-rcn"表示最終穩定版本之前的候選版本(Release Candidate), n代表候選版本號

各版本之間的關系及命名規則可以參考網站:https://zh.wikipedia.org/wiki/Linux%E5%86%85%E6%A0%B8

注意: page9中的EOL: end of life: 指從此往后不在對應的版本上進行更新。 下面展示了Linux內核的版本變遷過程:

image-20200701153655101

Linux內核結構

Linux內核是Linux系統軟件的核心, 它的性能對整個系統的性能起決定作用

Linux內核文件數目將近4萬個, 他們分別位于頂層目錄下的20個子目錄中, 了解Linux內核的工作過程,必須從了解其目錄結構做起

我們后面研究并移植的內核為:3.4.39, 首先我們從官網上下載3.4.39的內核源碼linux-3.4.39.tar.bz2將其在虛擬機上解壓, 使用tree命令可以在虛擬機下查看其目錄結構

Linux內核源代碼主要包含以下子目錄:

image-20200701155535511

  • arch 與體系結構相關的代碼。 對應于每個支持的體系結構, 有一個相應的子目錄如x86arm等與之對應, 相應目錄下有對應的芯片與之對應
  • crypto 常用加密及散列算法, 和一些壓縮及CRC校驗算法
  • Documentation 內核相關文檔, 關于內核各部分的通用解釋和注釋
  • drivers 設備驅動代碼, 占整個內核代碼量的一半以上, 里面的每個子目錄對應一類驅動程序, 如: block:塊設備、 char:字符設備、 net:網絡設備等
  • fs 文件系統代碼, 每個支持的文件系統有相應的子目錄, 如cramfsyaffsjffs2
  • include 這里包括編譯內核所需的大部分頭文件 , 與平臺無關的頭文件放在include/linux子目錄下 , 各類驅動或功能部件的頭文件( /media/mtd/net等), 與體系相關的頭文件 arch/arm/include/ , 與平臺相關的頭文件路徑arch/arm/mach-s5p6818/include/mach
  • init 內核初始化代碼,其中的main.c中的start_kernel函數是系統引導起來后運行的第1個函數, 這是研究內核工作過程的起點
  • ipc 內核進程間通信代碼
  • kernel 內核管理的核心代碼, 此目錄下的文件實現了大多數linux系統的內核函數, 體系結構相關的代碼在arch/arm/kernel
  • lib 與體系結構無關的內核庫代碼,與系統調用相關 , 與體系結構相關的內核庫代碼在arch/arm/lib
  • mm 與體系結構無關的內存管理代碼 , 與處理器體系結構相關的代碼在 arch/arm/mm
  • net 網絡部分代碼, 其每個目錄對應于網絡的一個方面
  • scripts 存放一些腳本文件, 如配置內核時用到的make menuconfig命令等

Linux kernel組成:

img

image-20200701160147862

Linux內核部分模塊:

進程管理、 進程調度、 系統調用、 中斷處理、 下半部和工作隊列、 內核同步、 定時管理、 內存管理、虛擬文件系統、 塊設備、 網絡子系統、 進程地址空間、 模塊機制等等…

Linux編程風格 :

像所有其他大型軟件項目一樣, Linux制定了一套編碼風格

跟選擇一個唯一確定的風格相比, 到底選擇什么樣的風格反而顯得不是那么重要

編碼風格的主要規范伴隨著Linus一貫的幽默,都記錄在內核源碼的Documentation/Coding Style中了。

制定編碼風格的目的, 是為了提高編程效率, 吸引更多的開發者眼球

縮進

  • 采用制表符(Tab)進行縮進, 而不是空格
  • 禁止制表符和空格混合使用

花括號使用如下:

if (flag) {fun();//...
}void fun (void)
{ //..
}if (flag)fun();
//...

命名規范

  • Linux規定名稱中不允許使用混合大小寫字符
  • 單詞之間用下劃線分隔
  • 避免取有疑惑的簡單名稱, 如pad(), 應該寫成 platform_add_devices()

代碼長度

  • 每行盡量不超過80個字符(可進行有意義分行切割)
  • 函數體代碼長度盡量不超過兩屏
  • 函數局部變量盡量不超過十個
  • 根據函數使用頻率和函數體大小可以使用inline聲明, 以提高調用效率

注釋

  • 一般情況用于描述代碼可以做什么和為什么要做, 盡量不寫實現方式
  • 函數的修改和維護日志統一集中在文件開頭

在程序中對ifdef的處理

一般不這么用:

//...
#ifdef CONFIG_FUNfun();
#endif
//...

而是在聲明處使用ifdef

#ifdef CONFIG_FUN
void fun (void)
{//...
} 
#else
inline void fun (void) { }
#endif

其他

  • 指針中的“ *” 號應靠近變量名, 而不是類型關鍵字
  • 函數之間用空行隔開
  • 函數導出申明緊跟在函數定義的下面

代碼風格的事后修正

indent命令是大多數Linux系統中都帶有的工具, 當得到一段與內核編碼風格大相徑庭的代碼時, 可以通過這個工具進行
調整:

#indent -kr -i8 -ts8 -sob -l80 -ss -bs -psl
<filename>

Linux內核啟動引導過程

了解Linux鏡像的格式及其產生過程

Linux內核有多種鏡像格式:

Image : 直接生成并且無頭部未壓縮的內核, 一般用于PC機

zImage : Image的壓縮版, 采用gzip進行壓縮, 比Image體積小,但啟動時需要進行自解壓, 嵌入式系統中一般采用此種方法

uImage : 是u-boot專用的一種內核鏡像格式, 它是在zImage的基礎上又添加了一個長度為64字節的標簽頭, 在u-boot啟動時會去掉此頭信息, 仍按zImage啟動, 頭信息主要用于區分不同格式的內核鏡像

xipImage : 片上執行的未壓縮內核, (如norflash等)

zImage鏡像產生過程:

vmlinux -> Image -> compressed / vmlinux -> zImage

vmlinux 是由以下內核代碼生成的非壓縮鏡像 (arch/arm/kernel/head.s、 kernel/、 mm/、 fs/、 ipc/、 crypto/、 lib/、drivers/、 net/等等)

Image 是使用objcopy工具對vmlinux進行二進制化處理得到的鏡像

arch/arm/boot/compressed/vmlinux由壓縮的Imagecompressed/head.Smisc.c等文件組成

zImage是由compressed/vmlinux使用objcopy工具二進制化得到

再對zImage加上頭部就成為了uImage

image-20200701161524245

boot.img的生成過程 :

image-20200701161846753

boot.img是使用一種文件系統打包工具制作的, 相當于把各種非必須文件打包在一起成為一整個文件, 然后被燒寫進設備

Linux內核的啟動過程大體上可以分為3個階段:

內核解壓( 匯編+C)

  • 主要由arch/arm/boot/compressed/zImage完成解壓(C語言),并跳轉到下階段代碼

板級引導階段( 匯編)

  • 主要進行對cpu和體系結構的檢查、 cpu本身的初始化以及頁表的建立等

通用內核啟動階段( C語言)

  • 進入init/main.c文件, 從start_kernel開始進行內核初始化工作,最后調用rest_init

rest_init()創建并進入內核第一個線程, 線程函數為 kernel_init()

kernel_init()中會初始化各種驅動并建立起標準輸入/ 標準輸出/錯誤輸出, 最后調用

init_post()中會釋放初始化內存段, 標志著內核啟動完成, 并努力尋找一個用戶進程, 通過kernel_execve()函數加載, 將該進程作為系統的第一個用戶進程init,進程號為1

內核啟動完成, 接下來就是用戶的事兒了

Linux內核的配置與編譯

Linux內核配置裁剪過程

make menuconfig

Linux內核編譯過程

根據配置裁剪的結果配合Makefile完成內核編譯

Linux內核這一配置編譯機制

把驅動程序v_motor_driver.c(振動馬達驅動)添加 到內核源碼來驗證整個過程

在Linux2.6以后的版本中, 文件的組織是通過 Kconfig 和 Makefile 來實現的

通過每層目錄的 Kconfig 和 Makefile 實現了整個Linux 內核的分布式配置

  • Kconfig: 對應內核模塊的配置菜單
  • Makefile: 對應內核模塊的編譯選項

Kconfig包含了當前目錄下所有模塊的配置

子目錄的Makefile在被頂層Makefile調用時, 會負責編譯當前目錄下的所有模塊

當有新的模塊被加入時, 需要更改當前目錄下的Kconfig文件, 并且更改對應的Makefile文件, 這樣在最終編譯之前, 可以通過

make menuconfig 對需要添加的模塊進行配置和添加

當保存make menuconfig時, 系統除了會自動更新.config外, 還會將選項以宏的形式保存在內核根目錄下的include/generated/autoconf.h文件下

當執行make menuconfig時, 配置工具會自動根據根目錄下的ARCH變量讀取arch/$(ARCH)/Kconfig文件來生成配置界面, 這個文件是所有文件的總入口, 其它目錄的Kconfig都由它來引用, 如圖所示:

image-20200701165024280

ARM平臺為例講解其具體配置過程

當執行make menuconfig時, 系統首先讀取 arch/arm/Kconfig生成整個配置界面

在讀取配置界面的同時, 系統會讀取頂層目錄下的.config文件生成所有配置選項的默認值

當修改完配置并保存后, 系統會更新頂層目錄下的.config文件

當執行make時, 各層的Makefile會根據.config文件中的編譯選項來決定哪些文件會被編譯到內核中, 或編譯成模塊

Kconfig語法格式可以參考具體文件, 如:drivers/char/Kconfig

# SPDX-License-Identifier: GPL-2.0
#
# Character device configuration# comment: 注釋信息, 菜單和.config文件中都會出現
# string: 字符串; hex: 16進制的數; int: 10進制的數
# choice/endchoice: 表示選擇性的菜單條目# menu/endmenu: 表示生成一個菜單
menu "Character devices"
# source: 用于包含其它Kconfig
source "drivers/tty/Kconfig"
#config代表一個選項的開始,最終會出現在.config中(會自動增加一個CONFIG_前綴)
config DEVMEM#bool代表此選項僅能選中或不選中,bool后面的字符串代表此選項在make menuconfig中的名字bool "/dev/mem virtual device support"#default: 默認選項值default yhelpSay Y here if you want to support the /dev/mem device.The /dev/mem device is used to access areas of physicalmemory.When in doubt, say "Y".config DEVKMEMbool "/dev/kmem virtual device support"# On arm64, VMALLOC_START < PAGE_OFFSET, which confuses kmem read/write# depends on:依賴其余的選項depends on !ARM64helpSay Y here if you want to support the /dev/kmem device. The/dev/kmem device is rarely used, but can be used for certainkind of kernel debugging operations.When in doubt, say "N".source "drivers/tty/serial/Kconfig"
source "drivers/tty/serdev/Kconfig"config TTY_PRINTK#tristate: 代表可以選擇編譯、 不編譯、 編譯成模塊tristate "TTY driver to output user messages via printk"depends on EXPERT && TTYdefault n---help---If you say Y here, the support for writing user messages (i.e.console messages) via printk is available.The feature is useful to inline user messages with kernelmessages.In order to use this feature, you should output user messagesto /dev/ttyprintk or redirect console to this TTY.If unsure, say N.config VIRTIO_CONSOLEtristate "Virtio console"depends on VIRTIO && TTY# select: 表示當前config被選中時, 此選項也被選中select HVC_DRIVERhelpVirtio console for use with hypervisors.Also serves as a general-purpose serial device for datatransfer between the guest and host.  Character devices at/dev/vportNpn will be created when corresponding ports arefound, where N is the device number and n is the port numberwithin that device.  If specified by the host, a sysfsattribute called 'name' will be populated with a name forthe port which can be used by udev scripts to create asymlink to the device.//....endmenu

將自己開發的內核代碼加入到Linux內核中, 需要有3個步驟:

把自己編寫的代碼放到內核中合適的位置

把自己開發的功能增加到Linux內核的配置選項中, 使用戶能夠選中這項功能并編譯

構建或修改Makefile, 根據用戶的選擇, 將相應的代碼編譯到最終生成的Linux內核中去

將 振動馬達的驅動添加進內核為例 , 講解配置機制的具體應用

添加步驟如下:

Step1: 將v_motor_driver.c拷到drivers/char/目錄下

Step2: vi driver/char/Kconfig,在Kconfig文件結尾, 在endmenu的前面加入一個config選項

config 6818_VMOTORbool "The Vibration motor driver ofr S5P6818"default yhelpThe driver for Vibration motor deviceendmenu

Step3: make menuconfig(添加配置選項)

Device driver —> character devices —> [*] The Vibration motor driver for S5P6818

Step4: vi driver/char/Makefile添加內容如下:

obj-$(CONFIG_6818_VMOTOR)		+= v_motor_driver.c

Step5: make (更新內核鏡像到開發板)

Step6: 交叉編譯 測試程序, 并放到開發板運行

arm-linux-gcc v_motor_test.c -o v_motor_test./v_motor_test 1

Linux3.4.39內核移植

以Linux3.4.39內核在開發板上的移植為例, 學習如何從一個純凈的Linux內核編譯、 配置得到適合在一個特定平臺運行的鏡像。 具體移植步驟如下:

  • 源碼解壓
  • 添加BSP
  • 修改頂層和BSPMakefile
  • 修改鏈接地址機器ID號并拷貝默認配置文件
  • 移植串口驅動支持
  • emmc驅動移植
  • ext4文件系統的支持移植
  • 內核配置、 編譯

練習:

  • 添加鍵盤驅動到Linux-3.4.39
  • Linux-3.4.39內核移植
  • Linux-3.4.39內核LCD移植
  • Linux-3.4.39內核修改開機logo

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/10772.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/10772.shtml
英文地址,請注明出處:http://en.pswp.cn/web/10772.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Task Office for Mac v9.0激活版:任務管理新境界

還在為繁瑣的任務管理而煩惱嗎&#xff1f;Task Office for Mac為您帶來全新的任務管理體驗。簡潔明了的界面設計&#xff0c;讓您輕松上手&#xff1b;強大的任務管理和項目管理功能&#xff0c;讓您輕松掌握任務進度&#xff1b;多用戶協作功能&#xff0c;讓團隊協作更加高效…

ubuntu24.04安裝ros

ubuntu24.04安裝ros 踩坑 踩坑 目前安裝人數比較少&#xff0c;沒有較為詳細的博客&#xff0c;參考官網的鏈接 http://docs.ros.org/en/rolling/Installation/Ubuntu-Install-Debians.html 同時在如下的一步中會找不到網址報錯&#xff0c;此時可以參考https://blog.51cto.c…

Excel辦公技巧之下拉菜單

在日常辦工中&#xff0c;經常需在單元格中輸入特定的值&#xff0c;此時我們可以使用下拉菜單解決&#xff0c;輸入錯誤和錯誤值&#xff0c;可以一勞永逸的解決固定數據輸入問題。 使用Excel下拉菜單時&#xff0c;它在數據輸入和驗證方面發揮著重要作用通過點擊單元格的下拉…

學習筆記-Vue3中Hook函數

什么是Hook函數 Hook翻譯過來是鉤子的意思&#xff0c;其本質上是一組可復用的函數。簡單理解來說&#xff0c;你能夠在不同的組件中&#xff0c;實現相同的代碼邏輯&#xff0c;以達到代碼復用、提高維護性的效果。那為何叫’鉤子’呢&#xff0c;我的理解是&#xff1a; 它可…

商業數據分析--時間序列圖及趨勢分析

繪制時間序列圖,并指出存在什么樣的狀態如上兩圖: 可見狀態:從時間序列圖可以看出,這些數據存在明顯的季節性波動,每年的第4季度值都最高,而第2季度值最低。同時也存在一些下降的趨勢。 通過引進虛擬變量,建立多元線性回歸模型。答: 通過引入虛擬變量,我們可以建立如下的…

Oracle數據庫之多表查詢、層次查詢(五)

目錄 前言 Oracle 的連接條件的類型 多表查詢 1. 使用JOIN關鍵字 2. 使用WHERE子句進行多表查詢 3. 子查詢 4. EXISTS關鍵字 5. 集合運算 6. 注意事項&#xff1a; 層次查詢 前言 Oracle 的連接條件的類型 等值連接不等值連接外連接自連接 多表查詢 在Oracle數據…

商場學習之微服務

前言 寒假前在新電腦上配置了java環境&#xff0c;maven倉庫&#xff0c;node,js&#xff0c;navicat&#xff0c;MySQL&#xff0c;linux&#xff0c;vmware等環境&#xff0c;創建了6個mysql數據庫&#xff0c;77張表。 如此多的表&#xff0c;字段&#xff0c;去手寫基礎…

Web入門——三欄布局頁面

前置知識 內外邊距 內邊距(padding)&#xff1a; padding是元素邊框與其內容之間的空間。也就是說&#xff0c;如果你給一個元素設置了內邊距&#xff0c;這個空間會作為元素內容與元素邊框之間的緩沖區域。設置內邊距會使元素本身變大。例如padding:10px就創建了10像素的空間…

Qt之QMqtt 發送圖片數據

簡述 MQTT(消息隊列遙測傳輸)是ISO標準下基于發布/訂閱范式的消息協議;它工作在TCP/IP協議族上,是為硬件性能低下的遠程設備以及網絡狀況糟糕的情況下而設計的發布/訂閱型消息協議,為此,它需要一個消息中間件; MQTT是一個基于客戶端-服務器的消息發布/訂閱傳輸協議;MQT…

Ubuntu設置中午輸入法

本篇博客將指導您如何在Ubuntu系統中設置中文輸入法&#xff0c;讓您能夠輕松地進行中文輸入。 準備工作 在開始之前&#xff0c;請確保您的系統已經更新到最新版本。這可以通過以下命令來完成&#xff1a; sudo apt update && sudo apt upgrade這將幫助確保所有的軟…

Docker in Docker(DinD)原理與實戰

&#x1f407;明明跟你說過&#xff1a;個人主頁 &#x1f3c5;個人專欄&#xff1a;《Docker幻想曲&#xff1a;從零開始&#xff0c;征服容器宇宙》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目錄 一、引言 1、Docker簡介 2、Docker …

使用 AI Assistant for Observability 和組織的運行手冊增強 SRE 故障排除

作者&#xff1a;Almudena Sanz Oliv, Katrin Freihofner, Tom Grabowski 通過本指南&#xff0c;你的 SRE 團隊可以實現增強的警報修復和事件管理。 可觀測性 AI 助手可幫助用戶使用自然語言界面探索和分析可觀測性數據&#xff0c;利用自動函數調用來請求、分析和可視化數據…

Harmony 添加library依賴庫步驟

在Harmony添加library依賴庫步驟如下&#xff1a; 1、在library中定義名字 在library中的oh-package.json5中定義library對外的名字是什么&#xff1a;格式是 “name”:“ohos/名字” {"name": "ohos/library_name" //名字 }2、在項目目錄build-profi…

windows系統安裝Ubuntu子系統

安裝前先在 控制面板 中打開 程序與功能選項 &#xff0c;點擊 啟用或關閉Windows功能&#xff1a; 勾選 適用于 Linux的Windows子系統 和 虛擬機平臺 、 Hyper-v 。 重啟電腦后再 Microsoft Store Windows應用商店 中下載合適的Ubuntu版本。 運行Ubuntu程序&#xff0c;如出現…

【實戰】算法思路總結

面試過程中&#xff0c;總是被拷打&#xff0c;信心都要沒了。但是也慢慢摸索出一些思路&#xff0c;希望對大家有幫助。 &#xff08;需要多用一下ACM模式&#xff0c;力扣模式提供好了模板&#xff0c;自己在IDEA里面寫的話&#xff0c;還是會有些陌生&#xff09; 0、基本…

僵尸進程111

Linux 系統中的進程可能處于如下狀態中的一種&#xff1a; D 不可中斷的休眠 I 空閑 R 運行中 S 休眠 T 被調度信號終止 t 被調試器終止 Z 僵尸狀態 Interruptible Sleep&#xff0c;可中斷睡眠&#xff0c;在 ps 命令中顯示 S。處在這種睡眠狀態的進程是可以通過給它…

OC中Block為什么不能為nil

在 Objective-C 中&#xff0c;向 nil 對象發送消息是完全有效的&#xff0c;這是因為 Objective-C 運行時對 nil 消息發送進行了特別的處理。當你向 nil 對象發送消息時&#xff0c;消息會被靜默地忽略&#xff0c;不執行任何操作&#xff0c;也不會返回任何值&#xff08;或者…

Unity Editor 找物體助手

找啊找朋友~ &#x1f371;功能介紹&#x1f959;使用方法 &#x1f371;功能介紹 &#x1f4a1;輸入相關字符串&#xff0c;它會幫你找到名稱中帶有該字符串的所有物體&#xff0c;還會找包含該字符串的Text、TextMeshProUGUI。 &#x1f959;使用方法 &#x1f4a1;導入插…

小學拼音弄一下

import re from xpinyin import Pinyindef remove_middle_characters(text):# 僅保留漢字chinese_chars re.findall(r[\u4e00-\u9fff], text)cleaned_text .join(chinese_chars)# 如果字符數為偶數&#xff0c;則在中間添加空格if len(cleaned_text) % 2 0:middle_index le…

【北京迅為】《iTOP-3588從零搭建ubuntu環境手冊》-第5章 安裝SSH

RK3588是一款低功耗、高性能的處理器&#xff0c;適用于基于arm的PC和Edge計算設備、個人移動互聯網設備等數字多媒體應用&#xff0c;RK3588支持8K視頻編解碼&#xff0c;內置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800萬像素ISP&…