日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

字符设备驱动初体验(hello驱动)

發(fā)布時間:2025/4/5 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 字符设备驱动初体验(hello驱动) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

    • 1 APP打開的文件在內(nèi)核中如何表示
    • 2 打開字符設(shè)備節(jié)點(diǎn)時,內(nèi)核中也有對應(yīng)的 struct file
    • 3 驅(qū)動程序編寫的步驟
    • 4 驅(qū)動程序編寫
      • 4.1 寫驅(qū)動程序
      • 4.2 寫測試程序
      • 4.3 測試

1 APP打開的文件在內(nèi)核中如何表示

APP 打開文件時,可以得到一個整數(shù),這個整數(shù)被稱為文件句柄。對于 APP 的每一個文件句柄,在內(nèi)核里面都有一個“struct file”與之對應(yīng)。


可以猜測,我們使用 open 打開文件時,傳入的 flags、mode 等參數(shù)會被記錄在內(nèi)核中對應(yīng)的 struct file 結(jié)構(gòu)體里(f_flags、f_mode):int open(const char *pathname, int flags, mode_t mode);

去讀寫文件時,文件的當(dāng)前偏移地址也會保存在 struct file 結(jié)構(gòu)體的 f_pos 成員里。


2 打開字符設(shè)備節(jié)點(diǎn)時,內(nèi)核中也有對應(yīng)的 struct file

注意這個結(jié)構(gòu)體中的結(jié)構(gòu)體:struct file_operations *f_op,這是由驅(qū)動程序提供的。

結(jié)構(gòu)體 struct file_operations 的定義如下:


3 驅(qū)動程序編寫的步驟

① 確定主設(shè)備號,也可以讓內(nèi)核分配。
② 定義自己的 file_operations 結(jié)構(gòu)體。
③ 實(shí)現(xiàn)對應(yīng)的 drv_open/drv_read/drv_write 等函數(shù),填入 file_operations 結(jié)構(gòu)體。
④ 把 file_operations 結(jié)構(gòu)體告訴內(nèi)核:register_chrdev。
⑤ 誰來注冊驅(qū)動程序啊?得有一個入口函數(shù):安裝驅(qū)動程序時,就會去調(diào)用這個入口函數(shù) 。
⑥ 有入口函數(shù)就應(yīng)該有出口函數(shù):卸載驅(qū)動程序時,出口函數(shù)調(diào)用 unregister_chrdev。
⑦ 其他完善:提供設(shè)備信息,自動創(chuàng)建設(shè)備節(jié)點(diǎn):class_create, device_create。


4 驅(qū)動程序編寫

4.1 寫驅(qū)動程序

參考 driver/char 中的程序,包含頭文件,寫框架,傳輸數(shù)據(jù):
A. 驅(qū)動中實(shí)現(xiàn) open, read, write, release,APP 調(diào)用這些函數(shù)時,都打印內(nèi)核信息
B. APP 調(diào)用 write 函數(shù)時,傳入的數(shù)據(jù)保存在驅(qū)動中
C. APP 調(diào)用 read 函數(shù)時,把驅(qū)動中保存的數(shù)據(jù)返回給 APP

hello_drv.c

#include <linux/module.h>#include <linux/fs.h> #include <linux/errno.h> #include <linux/miscdevice.h> #include <linux/kernel.h> #include <linux/major.h> #include <linux/mutex.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/stat.h> #include <linux/init.h> #include <linux/device.h> #include <linux/tty.h> #include <linux/kmod.h> #include <linux/gfp.h>/* 1. 確定主設(shè)備號 */ static int major = 0; static char kernel_buf[1024]; static struct class *hello_class;#define MIN(a, b) (a < b ? a : b)/* 3. 實(shí)現(xiàn)對應(yīng)的open/read/write等函數(shù),填入file_operations結(jié)構(gòu)體 */ static ssize_t hello_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset) {int err;printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);err = copy_to_user(buf, kernel_buf, MIN(1024, size));return MIN(1024, size); }static ssize_t hello_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset) {int err;printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);err = copy_from_user(kernel_buf, buf, MIN(1024, size));return MIN(1024, size); }static int hello_drv_open (struct inode *node, struct file *file) {printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return 0; }static int hello_drv_close (struct inode *node, struct file *file) {printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return 0; }/* 2. 定義自己的file_operations結(jié)構(gòu)體 */ static struct file_operations hello_drv = {.owner = THIS_MODULE,.open = hello_drv_open,.read = hello_drv_read,.write = hello_drv_write,.release = hello_drv_close, };/* 4. 把file_operations結(jié)構(gòu)體告訴內(nèi)核:注冊驅(qū)動程序 */ /* 5. 誰來注冊驅(qū)動程序啊?得有一個入口函數(shù):安裝驅(qū)動程序時,就會去調(diào)用這個入口函數(shù) */ static int __init hello_init(void) {int err;printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);major = register_chrdev(0, "hello", &hello_drv); /* /dev/hello */hello_class = class_create(THIS_MODULE, "hello_class");err = PTR_ERR(hello_class);if (IS_ERR(hello_class)) {printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);unregister_chrdev(major, "hello");return -1;}device_create(hello_class, NULL, MKDEV(major, 0), NULL, "hello"); /* /dev/hello */return 0; }/* 6. 有入口函數(shù)就應(yīng)該有出口函數(shù):卸載驅(qū)動程序時,就會去調(diào)用這個出口函數(shù) */ static void __exit hello_exit(void) {printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);device_destroy(hello_class, MKDEV(major, 0));class_destroy(hello_class);unregister_chrdev(major, "hello"); }/* 7. 其他完善:提供設(shè)備信息,自動創(chuàng)建設(shè)備節(jié)點(diǎn) */module_init(hello_init); module_exit(hello_exit);MODULE_LICENSE("GPL");

4.2 寫測試程序

測試程序要實(shí)現(xiàn)寫、讀功能:
A. ./hello_drv_test -w wiki.100ask.net // 把字符串“wiki.100ask.net”發(fā)給驅(qū)動程序
B. ./hello_drv_test -r // 把驅(qū)動中保存的字符串讀回來

hello_drv_test.c

#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <string.h>/** ./hello_drv_test -w abc* ./hello_drv_test -r*/ int main(int argc, char **argv) {int fd;char buf[1024];int len;/* 1. 判斷參數(shù) */if (argc < 2) {printf("Usage: %s -w <string>\n", argv[0]);printf(" %s -r\n", argv[0]);return -1;}/* 2. 打開文件 */fd = open("/dev/hello", O_RDWR);if (fd == -1){printf("can not open file /dev/hello\n");return -1;}/* 3. 寫文件或讀文件 */if ((0 == strcmp(argv[1], "-w")) && (argc == 3)){len = strlen(argv[2]) + 1;len = len < 1024 ? len : 1024;write(fd, argv[2], len);}else{len = read(fd, buf, 1024); buf[1023] = '\0';printf("APP read : %s\n", buf);}close(fd);return 0; }

4.3 測試

編寫驅(qū)動程序的 Makefile:

# 1. 使用不同的開發(fā)板內(nèi)核時, 一定要修改KERN_DIR # 2. KERN_DIR中的內(nèi)核要事先配置、編譯, 為了能編譯內(nèi)核, 要先設(shè)置下列環(huán)境變量: # 2.1 ARCH, 比如: export ARCH=arm64 # 2.2 CROSS_COMPILE, 比如: export CROSS_COMPILE=aarch64-linux-gnu- # 2.3 PATH, 比如: export PATH=$PATH:/home/book/100ask_roc-rk3399-pc/ToolChain-6.3.1/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin # 注意: 不同的開發(fā)板不同的編譯器上述3個環(huán)境變量不一定相同, # 請參考各開發(fā)板的高級用戶使用手冊KERN_DIR = /home/book/100ask_roc-rk3399-pc/linux-4.4all:make -C $(KERN_DIR) M=`pwd` modules $(CROSS_COMPILE)gcc -o hello_drv_test hello_drv_test.c clean:make -C $(KERN_DIR) M=`pwd` modules cleanrm -rf modules.orderrm -f hello_drv_testobj-m += hello_drv.o

上機(jī)實(shí)驗(yàn):

  • 安裝驅(qū)動程序
  • insmod hello_drv.ko
  • 查看驅(qū)動文件及卸載驅(qū)動
  • cat /proc/devices // 查看所有的驅(qū)動設(shè)備及其主設(shè)備號 ls /dev/hello -l // 驅(qū)動程序會生成設(shè)備節(jié)點(diǎn) lsmod // 查看所有驅(qū)動 rmmod hello_drv // 移除驅(qū)動

    參考資料:

  • 韋東山全系列視頻第1季快速入門
  • 總結(jié)

    以上是生活随笔為你收集整理的字符设备驱动初体验(hello驱动)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 国产首页 | 亚洲在线一区二区三区 | 日韩毛毛片 | 男女黄色又爽大片 | 黄色中文字幕在线观看 | 任你躁av一区二区三区 | 少妇免费直播 | 天堂在线中文 | 天天躁日日躁aaaa视频 | 亚洲男人网 | 高潮又黄又刺激 | 免费日韩毛片 | 裸体视频软件 | 日本亚洲在线 | 国产女人18毛片水真多 | 岛国av在线免费观看 | 在线播放一级片 | 国产精品视频www | 深夜免费在线视频 | aa一级视频 | 色偷偷影院 | 亚洲日本视频在线观看 | 在线观看中文字幕视频 | 性生活视频软件 | 日日骑| 黄色三及 | 国产精品宾馆在线 | 久久国产乱子伦免费精品 | av在线免费播放网站 | 在线中文视频 | 九色丨蝌蚪丨成人 | 久久99国产精品成人 | 在线视频网 | 怡春院一区二区 | 国产一区二区黄色 | 男生操女生网站 | 亚洲天堂一区二区三区四区 | 无码人妻精品中文字幕 | 国产日韩欧美精品在线观看 | 免费看黄色一级视频 | 日韩精品免费一区二区三区竹菊 | 秋葵视频污 | 欧美老女人视频 | 人人干人人爱 | 成人网在线观看 | 国产中文字字幕乱码无限 | 99在线视频免费 | 超碰人人草人人干 | 亚洲伊人久久久 | wwwxxx欧美| 日本乱偷中文字幕 | 亚洲精品www.| 波多野吉衣一区二区 | 日韩视频在线免费播放 | 亚洲青草视频 | 无码国产精品一区二区高潮 | www.久久视频| 国产无遮挡又黄又爽免费视频 | 日本一区中文字幕 | 我要看黄色大片 | 经典一区二区三区 | 日日操网 | 成熟了的熟妇毛茸茸 | 日日干日日摸 | 中文在线字幕免 | 免费观看黄网站 | 欧美破处大片 | 老司机精品视频在线 | 精品免费久久久 | 爱逼综合 | 中文字幕无码乱码人妻日韩精品 | 成人午夜免费在线观看 | 色哥网 | 亚洲最新在线视频 | 天天草天天射 | 中文字幕欧美在线 | 亚洲成人v | 中文字幕网址在线 | 国产成人av一区二区三区在线观看 | 欧美一级不卡视频 | 亚洲AV成人无码久久精品同性 | 久久午夜神器 | 麻豆自拍偷拍 | 日韩欧美电影一区二区三区 | 久久久久国产一区 | 国产亚洲一区二区三区 | 夜夜操夜夜摸 | 色猫咪av | 成人wwwww免费观看 | 91精品国产综合久久福利软件 | 欧美偷拍少妇精品一区 | 香蕉久久久久久 | 高清福利视频 | 国产毛片91 | 日本在线一区二区三区 | 高潮一区二区三区乱码 | 91美女视频 | 国产精品乱码一区二区视频 | 亚洲一区二区三区av无码 |