Linux字符驅動設備開發入門之框架搭建

聲明

本博客所記錄的關于正點原子i.MX6ULL開發板的學習筆記,(內容參照正點原子I.MX6U嵌入式linux驅動開發指南,可在正點原子官方獲取正點原子Linux開發板 — 正點原子資料下載中心 1.0.0 文檔,旨在如實記錄我在學校學習該開發板過程中所遭遇的各類問題以及詳細的解決辦法。其初衷純粹是為了個人知識梳理、學習總結以及日后回顧查閱方便,同時也期望能為同樣在學習這款開發板的同學或愛好者提供一些解決問題的思路和參考。我盡力保證內容的準確性和可靠性,但由于個人知識水平和實踐經驗有限,若存在錯誤或不嚴謹之處,懇請各位讀者批評指正。

責任聲明:雖然我力求提供有效的問題解決辦法,但由于開發板使用環境、硬件差異、軟件版本等多種因素的影響,我的筆記內容不一定適用于所有情況。對于因參考本筆記而導致的任何直接或間接損失,我不承擔任何法律責任。使用本筆記內容的讀者應自行承擔相關風險,并在必要時尋求專業技術支持。

1. 字符設備驅動簡介

字符設備是 Linux 驅動中最基本的一類設備驅動,字符設備就是一個一個字節,按照字節流進行讀寫操作的設備,讀寫數據是分先后順序的。比如我們最常見的點燈、按鍵、 IIC、 SPI, LCD 等等都是字符設備,這些設備的驅動就叫做字符設備驅動。

Linux 應用程序對驅動程序的調用

在 Linux 中一切皆為文件,驅動加載成功以后會在“/dev”目錄下生成一個相應的文件,應用程序通過對這個名為“/dev/xxx” (xxx 是具體的驅動文件名字)的文件進行相應的操作即可實現對硬件的操作。

應用程序運行在用戶空間,而 Linux 驅動屬于內核的一部分,因此驅動運行于內核空間。當我們在用戶空間想要實現對內核的操作,比如使用 open 函數打開/dev/led 這個驅動,因為用戶空間不能直接對內核進行操作,因此必須使用一個叫做“系統調用”的方法來實現從用戶空間“陷入” 到內核空間,這樣才能實現對底層驅動的操作。

每一個系統調用,在驅動中都有與之對應的一個驅動函數,在 Linux 內核文件 include/linux/fs.h 中有個叫做 file_operations 的結構體,此結構體就是 Linux 內核驅動操作函數集合

file_operation 結構體中比較重要的、常用的函數:

第 1589 行, owner 擁有該結構體的模塊的指針,一般設置為 THIS_MODULE。第 1590 行, llseek 函數用于修改文件當前的讀寫位置。

第 1591 行, read 函數用于讀取設備文件。

第 1592 行, write 函數用于向設備文件寫入(發送)數據。

第 1596 行, poll 是個輪詢函數,用于查詢設備是否可以進行非阻塞的讀寫。

第 1597 行, unlocked_ioctl 函數提供對于設備的控制功能,與應用程序中的 ioctl 函數對應。

第 1598 行, compat_ioctl 函數與 unlocked_ioctl 函數功能一樣,區別在于在 64 位系統上, 32 位的應用程序調用將會使用此函數。在 32 位的系統上運行 32 位的應用程序調用的是unlocked_ioctl。

第 1599 行, mmap 函數用于將設備的內存映射到進程空間中(也就是用戶空間),一般幀緩沖設備會使用此函數,比如 LCD 驅動的顯存,將幀緩沖(LCD 顯存)映射到用戶空間中以后應用程序就可以直接操作顯存了,這樣就不用在用戶空間和內核空間之間來回復制。

第 1601 行, open 函數用于打開設備文件。

第 1603 行, release 函數用于釋放(關閉)設備文件,與應用程序中的 close 函數對應。第 1604 行, fasync 函數用于刷新待處理的數據,用于將緩沖區中的數據刷新到磁盤中。

第 1605 行, aio_fsync 函數與 fasync 函數的功能類似,只是 aio_fsync 是異步刷新待處理的數據。

在字符設備驅動開發中最主要的工作就是實現上面這些函數,不一定全部都要實現,但是像 open、 release、 write、 read 等都是需要實現的,具體需要實現哪些函數還是要看具體的驅動要求。

2. 字符設備驅動開發步驟

2.1 驅動模塊的加載和卸載

Linux 驅動有兩種運行方式,第一種就是將驅動編譯進 Linux 內核中,這樣當 Linux 內核啟動的時候就會自動運行驅動程序。第二種就是將驅動編譯成模塊(Linux 下模塊擴展名為.ko),在Linux 內核啟動以后使“insmod”/modprob”命令加載驅動模塊。在調試驅動的時候一般都選擇將其編譯為模塊,這樣我們修改驅動以后只需要編譯一下驅動代碼即可,不需要編譯整個 Linux 代碼。而且在調試的時候只需要加載或者卸載驅動模塊即可,不需要重啟整個系統。

模塊有加載和卸載兩種操作,我們在編寫驅動的時候需要注冊這兩種操作函數,模塊的加載和卸載注冊函數如下:

module_init(xxx_init); //注冊模塊加載函數

module_exit(xxx_exit); //注冊模塊卸載函數

module_init 函數用來向 Linux 內核注冊一個模塊加載函數,參數 xxx_init 就是需要注冊的具體函數,當使用“insmod”命令加載驅動的時候, xxx_init 這個函數就會被調用。 module_exit()函數用來向 Linux 內核注冊一個模塊卸載函數,參數 xxx_exit 就是需要注冊的具體函數,當使用“rmmod”命令卸載具體驅動的時候 xxx_exit 函數就會被調用。字符設備驅動模塊加載和卸載模板如下所示:

驅動編譯完成以后擴展名為.ko,有兩種命令可以加載驅動模塊: insmod和modprobe, insmod是最簡單的模塊加載命令,此命令用于加載指定的.ko 模塊,比如加載 drv.ko 這個驅動模塊,命令如下:

insmod drv.ko

insmod 命令不能解決模塊的依賴關系,比如 drv.ko 依賴 first.ko 這個模塊,就必須先使用insmod 命令加載 first.ko 這個模塊,然后再加載 drv.ko 這個模塊。但是 modprobe 就不會存在這個問題, modprobe 會分析模塊的依賴關系,然后會將所有的依賴模塊都加載到內核中,因此modprobe 命令相比 insmod 要智能一些。 modprobe 命令主要智能在提供了模塊的依賴性分析、錯誤檢查、錯誤報告等功能,推薦使用 modprobe 命令來加載驅動。 modprobe 命令默認會去/lib/modules/<kernel-version>目錄中查找模塊,比如本書使用的 Linux kernel 的版本號為 4.1.15,因此 modprobe 命令默認會到/lib/modules/4.1.15 這個目錄中查找相應的驅動模塊,一般自己制作的根文件系統中是不會有這個目錄的,所以需要自己手動創建

驅動模塊的卸載使用命令“rmmod”即可,比如要卸載 drv.ko,使用如下命令即可: rmmod drv.ko

也可以使用“modprobe -r”命令卸載驅動,比如要卸載 drv.ko,命令如下: modprobe -r drv.ko

使用 modprobe 命令可以卸載掉驅動模塊所依賴的其他模塊,前提是這些依賴模塊已經沒有被其他模塊所使用,否則就不能使用 modprobe 來卸載驅動模塊。所以對于模塊的卸載,還是推薦使用 rmmod 命令

2.2 字符設備注冊與注銷

當驅動模塊加載成功以后需要注冊字符設備,同樣,卸載驅動模塊的時候也需要注銷掉字符設備。字符設備的注冊和注銷函數原型如下所示:

static inline int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)static inline void unregister_chrdev(unsigned int major, const char *name)

register_chrdev 函數用于注冊字符設備,此函數一共有三個參數,這三個參數的含義如下: major: 主設備號, Linux 下每個設備都有一個設備號,設備號分為主設備號和次設備號兩部分

name:設備名字,指向一串字符串。

fops: 結構體 file_operations 類型指針,指向設備的操作函數集合變量。unregister_chrdev 函數用戶注銷字符設備,此函數有兩個參數,這兩個參數含義如下: major: 要注銷的設備對應的主設備號。

name: 要注銷的設備對應的設備名。

一般字符設備的注冊在驅動模塊的入口函數 xxx_init 中進行,字符設備的注銷在驅動模塊的出口函數 xxx_exit 中進行。

加入字符設備注冊和注銷后的代碼:

CHRDEVBASE_MAJOR是宏定義,使用cat /proc/devices可以查看當前設備的設備號,自己取一個沒被占用的,我選的是66, CHRDEVBASE_NAME就是名字,也是宏定義。

這里使用了 printk 來輸出信息,而不是 printf!因為在 Linux 內核中沒有 printf 這個函數。 printk 相當于 printf 的孿生兄妹, printf運行在用戶態, printk 運行在內核態。在內核中想要向控制臺輸出或顯示一些內容,必須使用printk 這個函數。不同之處在于, printk 可以根據日志級別對消息進行分類,一共有 8 個消息級別,這 8 個消息級別定義在文件 include/linux/kern_levels.h 里面,定義如下:

一共定義了 8 個級別,其中 0 的優先級最高, 7 的優先級最低。如果要設置消息級別,參考如下示例:

printk(KERN_EMERG "gsmi: Log Shutdown Reason\n");

上述代碼就是設置“gsmi: Log Shutdown Reason\n”這行消息的級別為 KERN_EMERG。在具體的消息前面加上 KERN_EMERG 就可以將這條消息的級別設置為 KERN_EMERG。如果使用 printk 的 時 候 不 顯 式 的 設 置 消 息 級 別 , 那 么 printk 將 會 采 用 默 認 級 別MESSAGE_LOGLEVEL_DEFAULT, MESSAGE_LOGLEVEL_DEFAULT 默認為 4。在 include/linux/printk.h 中有個宏 CONSOLE_LOGLEVEL_DEFAULT,定義如下: #define CONSOLE_LOGLEVEL_DEFAULT 7

CONSOLE_LOGLEVEL_DEFAULT 控制著哪些級別的消息可以顯示在控制臺上,此宏默認為7,意味著只有優先級高于 7 的消息才能顯示在控制臺上。

這個就是 printk 和 printf 的最大區別,可以通過消息級別來決定哪些消息可以顯示在控制臺上。默認消息級別為 4, 4 的級別比 7 高,所示直接使用 printk 輸出的信息是可以顯示在控制臺上的。

2.3 設備號

Linux 中每個設備都有一個設備號,設備號由主設備號和次設備號兩部分組成,主設備號表示某一個具體的驅動,次設備號表示使用這個驅動的各個設備。 Linux 提供了一個名為 dev_t 的數據類型表示設備號, dev_t 定義在文件 include/linux/types.h 里面,就是 unsigned int 類型,是一個 32 位的數據類型。 32 位的數據構成了主設備號和次設備號兩部分,其中高 12 位為主設備號, 20 位為次設備號。系統中主設備號范圍為 0~4095,所以在選擇主設備號的時候一定不要超過這個范圍

2.4 實現設備的具體操作函數

&test_fops是Linux 內核驅動操作函數

每個對應的實現:

這四個函數就是 chrtest 設備的 open、 read、 write 和 release 操作函數

2.5 添加LICENSE 和作者信息

最后我們需要在驅動中加入 LICENSE 信息和作者信息,其中 LICENSE 是必須添加的,否則的話編譯的時候會報錯,作者信息可以添加也可以不添加。 LICENSE 和作者信息的添加使用如下兩個函數:

MODULE_LICENSE() //添加模塊 LICENSE 信息

MODULE_AUTHOR() //添加模塊作者信息

3.?chrdevbase 字符設備驅動開發實驗

3.1、創建 VSCode 工程

在 Linux_Drivers 目錄下新建一個名為 1_chrdevbase 的子目錄來存放本實驗所有文件

在 1_chrdevbase 目錄中新建 VSCode 工程

3.2、添加頭文件路徑

打開 VSCode,按下“Crtl+Shift+P”打開 VSCode 的控制臺,然后輸入“C/C++: Edit configurations(JSON) ”,打開 C/C++編輯配置文件,第 5 行的 includePath 表示頭文件路徑,需要將 Linux 源碼里面的頭文件路徑添加進來,也就是我們前面移植的 Linux 源碼中的頭文件路徑。添加頭文件路徑以后的 c_cpp_properties.json的文件內容如下所示:

{"configurations": [{"name": "Linux","includePath": ["${workspaceFolder}/**","/home/mayachao/linux/IMX6ULL/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek/include","/home/mayachao/linux/IMX6ULL/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek/arch/arm/include","/home/mayachao/linux/IMX6ULL/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek/arch/arm/include/generated/"],"defines": [],"compilerPath": "/usr/bin/clang","cStandard": "c11","cppStandard": "c++17","intelliSenseMode": "clang-x64"}],"version": 4}



4.3、編寫實驗程序

在 Ubuntu 中輸入“man 2 open”即可查看 open 函數的詳細內容,其他以此類推。

chrdevbaseAPP.c如下所示:

4.4、編譯驅動程序

編譯驅動程序,也就是 chrdevbase.c 這個文件,我們需要將其編譯為.ko 模塊,創建Makefile 文件,然后在其中輸入如下內容:

第 1 行, KERNELDIR 表示開發板所使用的 Linux 內核源碼目錄,使用絕對路徑,大家根據自己的實際情況填寫即可。

Makefile 編寫好以后輸入“make”命令編譯驅動模塊,編譯過程如圖

編譯成功以后就會生成一個叫做 chrdevbaes.ko 的文件,此文件就是 chrdevbase 設備的驅動模塊。至此, chrdevbase 設備的驅動就編譯成功。

測試 APP 比較簡單,只有一個文件,因此就不需要編寫 Makefile 了,直接輸入命令編譯。因為測試 APP 是要在 ARM 開發板上運行的,所以需要使用 arm-linux-gnueabihf-gcc 來編譯,輸入如下命令:

arm-linux-gnueabihf-gcc chrdevbaseApp.c -o chrdevbaseApp

編譯完成以后會生成一個叫做 chrdevbaseApp 的可執行程序,輸入如下命令查看chrdevbaseAPP 這個程序的文件信息:

file chrdevbaseApp

chrdevbaseAPP 這個可執行文件是 32 位 LSB 格式, ARM 版本的,因此 chrdevbaseAPP 只能在 ARM 芯片下運行。

4.5 運行測試

1、加載驅動模塊

驅動模塊 chrdevbase.ko 和測試軟件 chrdevbaseAPP 都已經準備好了,接下來就是運行測試。為了方便測試, Linux 系統選擇通過 TFTP 從網絡啟動,并且使用 NFS 掛載網絡根文件系統,確保 uboot 中 bootcmd 環境變量的值為:

tftp 80800000 zImage;tftp 83000000 imx6ull-alientek-emmc.dtb;bootz 80800000 - 83000000

bootargs 環境變量的值為:

console=ttymxc0,115200 root=/dev/nfs rw nfsroot=192.168.1.250:/home/mayachao/linux/nfs/ rootfs ip=192.168.1.251:192.168.1.250:192.168.1.1:255.255.255.0::eth0:off

設置好以后啟動 Linux 系統,檢查開發板根文件系統中有沒有“/lib/modules/4.1.15”這個目錄,如果沒有的話自行創建。 注意,“/lib/modules/4.1.15”這個目錄用來存放驅動模塊,使用modprobe 命令加載驅動模塊的時候,驅動模塊要存放在此目錄下。“/lib/modules”是通用的,不管你用的什么板子、什么內核,這部分是一樣的。不一樣的是后面的“4.1.15”,這里要根據你所使用的 Linux 內核版本來設置。

將 chrdevbase.ko 和 chrdevbaseAPP 復制到 rootfs/lib/modules/4.1.15 目錄中,命令如下:

sudo cp chrdevbase.ko chrdevbaseApp /home/mayachao/linux/nfs/rootfs/lib/modules/4.1.15/ -f

輸入“depmod”命令以后會自動生成 modules.alias、modules.symbols 和 modules.dep 這三個文件,如圖

有些根文件系統可能沒有 depmod 這個命令,如果沒有這個命令就只能重新配置busybox,使能此命令,然后重新編譯 busybox。

輸入如下命令加載 chrdevbase.ko 驅動文件:

insmod chrdevbase.ko

modprobe chrdevbase.ko

輸入“lsmod”命令即可查看當前系統中存在的模塊

輸入如下命令查看當前系統中有沒有 chrdevbase 這個設備:

cat /proc/devices

2、創建設備節點文件

輸入如下命令創建/dev/chrdevbase 這個設備節點文件:

mknod /dev/chrdevbase c 66 0

“mknod”是創建節點命令,“/dev/chrdevbase”是要創建的節點文件,“c”表示這是個字符設備,“ 66”是設備的主設備號,“ 0”是設備的次設備號。創建完成以后就會存在/dev/chrdevbase 這個文件,可以使用“ls /dev/chrdevbase -l”命令查看

如果 chrdevbaseAPP 想要讀寫 chrdevbase 設備,直接對/dev/chrdevbase 進行讀寫操作即可。

3 chrdevbase 設備操作測試

輸入如下命令:

./chrdevbaseApp /dev/chrdevbase

4、卸載驅動模塊

如果不再使用某個設備的話可以將其驅動卸載掉,比如輸入如下命令卸載掉 chrdevbase 這個設備:

rmmod chrdevbase.ko

卸載以后使用 lsmod 命令查看 chrdevbase 這個模塊還存不存在,結果如圖

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

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

相關文章

小剛說C語言刷題——第15講 多分支結構

1.多分支結構 所謂多分支結構是指在選擇的時候有多種選擇。根據條件滿足哪個分支&#xff0c;就走對應分支的語句。 2.語法格式 if(條件1) 語句1; else if(條件2) 語句2; else if(條件3) 語句3; ....... else 語句n; 3.示例代碼 從鍵盤輸入三條邊的長度&#xff0c;…

Apache httpclient okhttp(1)

學習鏈接 Apache httpclient & okhttp&#xff08;1&#xff09; Apache httpclient & okhttp&#xff08;2&#xff09; httpcomponents-client github apache httpclient文檔 apache httpclient文檔詳細使用 log4j日志官方文檔 【Java基礎】- HttpURLConnection…

洛谷題單3-P1420 最長連號-python-流程圖重構

題目描述 輸入長度為 n n n 的一個正整數序列&#xff0c;要求輸出序列中最長連號的長度。 連號指在序列中&#xff0c;從小到大的連續自然數。 輸入格式 第一行&#xff0c;一個整數 n n n。 第二行&#xff0c; n n n 個整數 a i a_i ai?&#xff0c;之間用空格隔開…

使用binance-connector庫獲取Binance全市場的幣種價格,然后選擇一個幣種進行下單

一個完整的示例,展示如何使用 api 獲取Binance全市場的幣種價格,然后選擇一個最便宜的幣種進行下單操作 代碼經過修改,親測可用,目前只可用于現貨,合約的待開發 獲取市場價格:使用client.ticker_price()獲取所有交易對的當前價格 賬戶檢查:獲取賬戶余額,確保有足夠的資…

算法設計學習10

實驗目的及要求&#xff1a; 本查找實驗旨在使學生深入了解不同查找算法的原理、性能特征和適用場景&#xff0c;培養其在實際問題中選擇和應用查找算法的能力。通過實驗&#xff0c;學生將具體實現多種查找算法&#xff0c;并通過性能測試驗證其在不同數據集上的表現&#xff…

5天速成ai agent智能體camel-ai之第1天:camel-ai安裝和智能體交流消息講解(附源碼,零基礎可學習運行)

嗨&#xff0c;朋友們&#xff01;&#x1f44b; 是不是感覺AI浪潮鋪天蓋地&#xff0c;身邊的人都在談論AI Agent、大模型&#xff0c;而你看著那些密密麻麻的代碼&#xff0c;感覺像在讀天書&#xff1f;&#x1f92f; 別焦慮&#xff01;你不是一個人。很多人都想抓住AI的風…

MySQL介紹及使用

1. 安裝、啟動、配置 MySQL 1. 安裝 MySQL 更新軟件包索引 sudo apt update 安裝 MySQL 服務器 sudo apt install mysql-server 安裝過程中可能會提示你設置 root 用戶密碼。如果沒有提示&#xff0c;可以跳過&#xff0c;后續可以手動設置。 2. 配置 MySQL 運行安全腳本…

九、重學C++—類和函數

上一章節&#xff1a; 八、重學C—動態多態&#xff08;運行期&#xff09;-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/147004745?spm1001.2014.3001.5502 本章節代碼&#xff1a; cpp/cppClassAndFunc.cpp CuiQingCheng/cppstudy - 碼云 - 開源中國…

lua和C的交互

1.C調用lua例子 #include <iostream> #include <lua.hpp>int main() {//用于創建一個新的lua虛擬機lua_State* L luaL_newstate();luaL_openlibs(L);//打開標準庫/*if (luaL_dofile(L, "test.lua") ! LUA_OK) {std::cerr << "Lua error: &…

java高并發------守護線程Daemon Thread

文章目錄 1.概念2.生命周期與行為2. 應用場景3. 示例代碼4. 注意事項 1.概念 Daemon &#xff1a; 滴門 在Java中&#xff0c;線程分為兩類&#xff1a;用戶線程(User Thread)和守護線程(Daemon Thread)。 守護線程是后臺線程&#xff0c;主要服務于用戶線程&#xff0c;當所…

Docker存儲策略深度解析:臨時文件 vs 持久化存儲選型指南

Docker存儲策略深度解析&#xff1a;臨時文件 vs 持久化存儲選型指南 一、存儲類型全景對比二、臨時存儲適用場景與風險2.1 最佳使用案例2.2 風險警示 三、持久化存儲技術選型3.1 Volume核心優勢Volume管理命令&#xff1a; 3.2 Bind Mount適用邊界掛載模式對比&#xff1a; 四…

【Linux網絡#18】:深入理解select多路轉接:傳統I/O復用的基石

&#x1f4c3;個人主頁&#xff1a;island1314 &#x1f525;個人專欄&#xff1a;Linux—登神長階 目錄 一、前言&#xff1a;&#x1f525; I/O 多路轉接 為什么需要I/O多路轉接&#xff1f; 二、I/O 多路轉接之 select 1. 初識 select2. select 函數原型2.1 關于 fd_set 結…

高級:微服務架構面試題全攻略

一、引言 在現代軟件開發中&#xff0c;微服務架構被廣泛應用于構建復雜、可擴展的應用程序。面試官通過相關問題&#xff0c;考察候選人對微服務架構的理解、拆分原則的掌握、服務治理的能力以及API網關的運用等。本文將深入剖析微服務架構相關的面試題&#xff0c;結合實際開…

使用MQTTX軟件連接阿里云

使用MQTTX軟件連接阿里云 MQTTX軟件阿里云配置MQTTX軟件設置 MQTTX軟件 阿里云配置 ESP8266連接阿里云這篇文章里有詳細的創建過程&#xff0c;這里就不再重復了&#xff0c;需要的可以點擊了解一下。 MQTTX軟件設置 打開軟件之后&#xff0c;首先點擊添加進行創建。 在阿…

【HFP】藍牙Hands-Free Profile(HFP)核心技術解析

藍牙 Hands-Free Profile&#xff08;HFP&#xff09;作為車載通信和藍牙耳機的核心協議&#xff0c;定義了設備間語音交互的標準化流程&#xff0c;并持續推動著無線語音交互體驗的革新。自2002年首次納入藍牙核心規范以來&#xff0c;HFP歷經多次版本迭代&#xff08;最新為v…

輕量化大模型微調工具XTuner指令微調實戰(下篇)

接著上篇文章《輕量化大模型微調工具XTuner指令微調實戰&#xff08;上篇&#xff09;》來接著寫教程。 一、模型轉換 模型訓練后會自動保存成 PTH 模型&#xff08;例如 iter_500.pth&#xff09;&#xff0c;我們需要利用 xtuner convert pth_to_hf 將其轉換為 HuggingFace…

pyTorch框架使用CNN進行手寫數字識別

目錄 1.導包 2.torchvision數據處理的方法 3.下載加載手寫數字的訓練數據集 4.下載加載手寫數字的測試數據集 5. 將訓練數據與測試數據 轉換成dataloader 6.轉成迭代器取數據 7.創建模型 8. 把model拷到GPU上面去 9. 定義損失函數 10. 定義優化器 11. 定義訓練…

強化學習課程:stanford_cs234 學習筆記(3)introduction to RL

文章目錄 前言7 markov 實踐7.1 markov 過程再敘7.2 markov 獎勵過程 MRP&#xff08;markov reward process&#xff09;7.3 markov 價值函數與貝爾曼方程7.4 markov 決策過程MDP&#xff08;markov decision process&#xff09;的 狀態價值函數7.4.1 狀態價值函數7.4.2 狀態…

操作系統 4.5-文件使用磁盤的實現

通過文件進行磁盤操作入口 // 在fs/read_write.c中 int sys_write(int fd, const char* buf, int count) {struct file *file current->filp[fd];struct m_inode *inode file->inode;if (S_ISREG(inode->i_mode))return file_write(inode, file, buf, count); } 進程…

libreoffice-help-common` 的版本(`24.8.5`)與官方源要求的版本(`24.2.7`)不一致

出現此錯誤的原因主要是軟件包依賴沖突&#xff0c;具體分析如下&#xff1a; ### 主要原因 1. **軟件源版本不匹配&#xff08;國內和官方服務器版本有差距&#xff09; 系統中可能啟用了第三方軟件源&#xff08;如 PPA 或 backports 源&#xff09;&#xff0c;導致 lib…