主頁 >  其他 > 一葉知秋,一個 LED 就能入門 Linux 內核

一葉知秋,一個 LED 就能入門 Linux 內核

2021-08-18 08:03:16 其他

請添加圖片描述

簡單點燈

最近專案上需要用到 LED 子系統,在嵌入式 Linux 里面點個燈還是比較簡單的,只要在某個燈對應的目錄里,向相應檔案寫入特定值,就可以讓 LED 亮/滅/閃爍,

# echo 1 > /sys/class/leds/green/brightness // 點亮 LED
# echo 0 > /sys/class/leds/green/brightness // 熄滅 LED
# echo heartbeat > /sys/class/leds/green/trigger // 讓 LED 像心跳一樣閃爍

led trigger

當然,專案里用到的點燈功能要比上面介紹的稍微復雜一點,類似于硬碟燈,即對硬碟進行讀寫操作時,LED 會閃爍,
隱隱約約感覺到,這個功能應該和 trigger 檔案有關系,因為在 cat 這個檔案時,里面有 mmc0 這個字眼,
那就往 trigger 里面寫個 mmc0 看看會有什么效果呢

# echo mmc0 > /sys/class/leds/green/trigger
# cat /sys/class/leds/green/trigger
none rc-feedback kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock [mmc0] heartbeat default-on ir-power-click axp20x-usb-online

向磁盤中寫入資料

# touch aa | sync

神奇地發現,每執行一次命令向磁盤中寫入資料,板子上綠色的燈就會閃爍一次,神奇,
通過查閱資料,了解到這是 LED 觸發器相關的功能,

一時間,想到

  • 為什么往 tigger 里寫入 mmc0,就能讓 LED 變成硬碟燈?
  • 為什么往 brightness 檔案里寫入 1/0,就能控制燈的亮滅?
  • 為什么往 trigger 檔案里面寫入 timer,LED 就會閃爍,同時會產生兩個檔案 delay_on、delay_off,并能用它們控制燈的閃爍頻率?
  • 等等
    種種疑惑涌上心頭,急切地想了解這些功能背后的原理,

思想斗爭

帶著這些疑惑,準備去到內核一探究竟,好奇心很強烈,但是腦海后面又傳來了阻撓的聲音,內核那么大,從哪看啊?能看懂嗎?其實這種場景在腦海里不止一次地發生過了,興趣和困難進行猛烈地撞擊,意志力稍強,會有所突破,靜下心來研究,可能會有所識訓,也可能識訓甚微,意志力稍差,打游戲去了,,
很遺憾,我選擇了后者,打游戲去了,哈哈!因為不知道從哪下手,先玩一局,放松下心情,
在這里插入圖片描述
打完游戲晚上躺在床上又繼續想 LED 子系統,突然想到,白天的時候誤呼叫了一個名字好像叫做 led_classdev_register(“aaa”) 的介面,結果在 leds 目錄下產生了一個 aaa 的目錄,那我就從這開始研究唄,好,就這樣,明天開搞,


開始探索

問題驅動行動,先列出想要知道的問題

  • 各個燈對應的目錄是怎么來的?
  • trigger 里面的各個觸發器是怎么產生的?
  • 為什么向 brightness 里面寫入 1/0,LED 會亮/滅
  • 為什么向 trigger 里面寫入 timer,會產生 delay_on、delay_off 這兩個檔案

開始研究,那就從昨晚想到的 led_classdev_register(“aaa”) 會產生一個 LED 目錄開始,


LED 設備注冊

先做一個實驗,確定下 led_classdev_register() 是否會產生一個 led 燈對應的目錄,
隨便找了一個可以被運行到的地方,加入了下面這幾行代碼,期望是在 leds 目錄下能夠產生 aaa 目錄

	struct led_classdev *cdev;
	int ret;


	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
	if (!cdev)
		return -ENOMEM;

	cdev->name = "aaa";
	// cdev->brightness_set = ebsa110_led_set;
	// cdev->brightness_get = ebsa110_led_get;
	// cdev->default_trigger = "heartbeat";

	ret = led_classdev_register(NULL, cdev);
	if (ret	< 0) {
		kfree(cdev);
		return ret;
	}

編譯、燒錄、運行、查看

# ls /sys/class/leds/
aaa    green

果然在 leds 下產生了我希望出現的目錄 aaa,信心大增!

后來又追了下底層呼叫關系:

led_classdev_register()
	of_led_classdev_register() // register a new object(物件) of led_classdev class.
		led_classdev_next_name()
		device_create_with_groups()
		led_add_brightness_hw_changed()
		list_add_tail() // add to the list of leds
		led_update_brightness()
		//led_trigger_set_default()

leds 目錄

知道了某個燈是怎么注冊產生的,又想知道 leds 目錄是怎么產生的,搜索了下代碼,也不難找到,下面是產生 leds 目錄相關的函式呼叫關系:

subsys_initcall(leds_init);
leds_init()	// 創建 leds 類,即產生 /sys/class/leds 目錄
	class_create()
		__class_create()
			__class_register()
				kset_register()

觸類旁通

后來,查資料了解到,/sys/class/leds 是一個類,一個類代表一個內核子系統,像這樣的子系統在內核中還有很多,/sys/class/ 里面的每個目錄都是一個類,也都是一個子系統

# ls /sys/class/
ata_device    extcon        mdio_bus      ptp           sound
ata_link      gpio          mem           pwm           spi_master
ata_port      graphics      misc          rc            thermal
bdi           hwmon         mmc_host      regulator     tty
block         i2c-adapter   net           rtc           udc
bsg           i2c-dev       phy           scsi_device   vc
dma           input         power_supply  scsi_disk     vtconsole
drm           leds          pps           scsi_host     watchdog

每個類里面又有具體的實體化物件,如 green、aaa

# ls /sys/class/leds/
aaa    green

每個物件里面又有相應的成員方法/屬性,如 brightness、trigger

# ls /sys/class/leds/aaa/
brightness      power           trigger
max_brightness  subsystem       uevent

多像 C++ 里面的類啊!其實就是類,簡單對比一下
在這里插入圖片描述
具體 class 里面的注冊邏輯,我這里就不展開講了,因為我也還沒研究透,哈哈!這里先不細究這點,等后面有時間了再慢慢吃透,
繼續我們的路線探索,
注意,其實這里我的探索路線已經變掉了,已經不局限于探究 LED 子系統了,開始向 LED 子系統外面的 kernel 擴展了,


class 目錄的產生

現在來到了 class 目錄,因為知道 leds 目錄是怎么來的之后,就在想其上面一級 class 目錄是怎么來的,追代碼,得到

classes_init()
	kset_create_and_add("class", NULL, NULL); // create a struct kset dynamically and add it to sysfs
		kset_create()
			kobject_set_name()
		kset_register()
			kset_init()
			kobject_add_internal()
				kobject_get()
				kobj_kset_join()
					kset_get()
					list_add_tail()
						__list_add()
						{
							next->prev = new;
							new->next = next;
							new->prev = prev;
						}
				create_dir() // 創建目錄

start_kernel()

其實追到 classes_init() 后,就不用我費腦筋去想下面再去追啥代碼了,繼續向上追就行了,干就完了

/* kernel */
start_kernel()
	rest_init() // Do the rest non-__init'ed, we're now alive
		kernel_thread(kernel_init, NULL, CLONE_FS);
		kernel_init()
			kernel_init_freeable()
			/*
			 * Ok, the machine is now initialized. None of the devices
			 * have been touched yet, but the CPU subsystem is up and
			 * running, and memory and process management works.
			 *
			 * Now we can finally start doing some real work..
			 */
			do_basic_setup()
			driver_init() // to initialize their subsystems.
				devtmpfs_init()
				devices_init()
				buses_init()
				classes_init() // 剛剛的 classes_init()
				firmware_init()
				hypervisor_init()
				platform_bus_init()
				cpu_dev_init()
				memory_dev_init()
				container_dev_init()
				of_core_init()

如上,一不小心就追到了 start_kernel(),夢開始的地方啊,第一次發現追內核代碼這么有趣,,


Starting kernel …

追到 start_kernel() 后,便不自由地想,Starting kernel ... 這段字串在哪列印的啊,每次開機 uboot 之后都能看到這句,如果能找到,豈不美哉,不幸的是,在內核代碼中沒搜到,


uboot

一開始我以為 Starting kernel ... 會在 start_kernel() 中列印,但是在內核代碼中沒搜到,這時候便想到會不會是在 ubbot 中列印的,在開始加載內核前列印這句也是合理的,
就去 uboot 里面搜了下,
果然

boot_jump_linux()
	announce_and_cleanup()
		printf("\nStarting kernel ...%s\n\n", fake ? "(fake run for tracing)" : "");

這里也就是 uboot 即將退出,kernel 即將運行的地方,


附完整呼叫關系

從 uboot 到 kernel 再到 /sys/class,然后注冊 leds 類,再實體化一個 LED 燈,

/* uboot */
boot_jump_linux()
	announce_and_cleanup()
		printf("\nStarting kernel ...%s\n\n"); // printf() 
		bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
		cleanup_before_linux()
	kernel_entry(0, machid, r2);


/* kernel */
start_kernel()
	rest_init() // Do the rest non-__init'ed, we're now alive
		kernel_thread(kernel_init, NULL, CLONE_FS);
		kernel_init()
			kernel_init_freeable()
			/*
			 * Ok, the machine is now initialized. None of the devices
			 * have been touched yet, but the CPU subsystem is up and
			 * running, and memory and process management works.
			 *
			 * Now we can finally start doing some real work..
			 */
			do_basic_setup()
			driver_init() // to initialize their subsystems.
				devtmpfs_init()
				devices_init()
				buses_init()
				classes_init()
					kset_create_and_add("class", NULL, NULL); // create a struct kset dynamically and add it to sysfs
						kset_create()
							kobject_set_name()
						kset_register()
							kset_init()
							kobject_add_internal()
								kobject_get()
								kobj_kset_join()
									kset_get()
									list_add_tail()
										__list_add()
										{
											next->prev = new;
											new->next = next;
											new->prev = prev;
										}
								create_dir()
				firmware_init()
				hypervisor_init()
				platform_bus_init()
				cpu_dev_init()
				memory_dev_init()
				container_dev_init()
				of_core_init()


subsys_initcall(leds_init);
leds_init()	// 創建 leds 類,即 /sys/class/leds 目錄
	class_create()
		__class_create()
			__class_register()
				kset_register()


led_classdev_register()
	of_led_classdev_register() // register a new object(物件) of led_classdev class.
		led_classdev_next_name()
		device_create_with_groups()
		led_add_brightness_hw_changed()
		list_add_tail() // add to the list of leds
		led_update_brightness()
		//led_trigger_set_default()

人生切入點

以上,從 LED 子系統進行切入,研究 Linux 內核,找到了研究 Linux 內核的切入點,
面對龐大的事物,我們往往會產生恐懼心理,這種恐懼阻止我們進一步研究,也就更加對其不了解,戰勝不了它,
兩個事例:

  1. 一個著名的馬拉松運動員在給大家講自己的成功經驗,他說自己總是事先將路程坐車看一遍,記下參照物,然后把距離縮成一節一節的,跑好每一節,
  2. 我上高中時物理成績比較好,因為我做題的方式跟別人不太一樣,別人拿到題就死盯著最后的問題,想立馬得到答案,而我是先掃一遍題,找其中幾個已知條件,根據物理公式,嘗試去推導未知的量,就這樣一點一點推導,有時定睛一看,答案就在眼前,

小到一道題目,一門學科,一項技能,大到作業、生活,甚至整個人生,我們如果能夠找到一個切入點,那么我們是幸運的,我們將以此通往成功,通向美好,

難了不會,會了不難,找到了切入點,我們就是后者,
請添加圖片描述

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/294474.html

標籤:其他

上一篇:Day6:資料結構之二叉樹

下一篇:【歷史上的今天】8 月 16 日:Debian 誕生;小米手機及 MIUI 系統發布!

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more