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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

【linux内核分析与应用-陈莉君】字符设备驱动

發(fā)布時(shí)間:2023/12/31 linux 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【linux内核分析与应用-陈莉君】字符设备驱动 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

?

1.什么是字符設(shè)備

2.如何來描述字符設(shè)備

3 struct cdev與const struct file_operations之間的關(guān)系

4.struct file_operations源碼

5.字符設(shè)備驅(qū)動(dòng)框架

6.編寫字符設(shè)備驅(qū)動(dòng)的步驟

7.字符設(shè)備結(jié)構(gòu)

8.字符設(shè)備驅(qū)動(dòng)程序的注冊(cè)

9.從系統(tǒng)調(diào)用到驅(qū)動(dòng)程序

10.用戶空間與內(nèi)核空間數(shù)據(jù)的傳送

11.參考資料與思考問題


1.什么是字符設(shè)備

字符設(shè)備是指只能一個(gè)一個(gè)字節(jié)進(jìn)行讀寫操作的設(shè)備,不能隨機(jī)讀取設(shè)備中的每一個(gè)數(shù)據(jù),取數(shù)據(jù)要 按照先后次序來進(jìn)行,字符設(shè)備時(shí)面向流的設(shè)備,常見的字符設(shè)備有: 鼠標(biāo), 鍵盤, 串口, 控制臺(tái), led等.一般每一個(gè)字符設(shè)備或者塊設(shè)備都會(huì)在dev目錄下對(duì)應(yīng)一個(gè)設(shè)備文件,Linux用戶層程序通過設(shè)備文件來使用 驅(qū)動(dòng)程序,操作字符設(shè)備或者塊設(shè)備.

2.如何來描述字符設(shè)備

?

D:\005-代碼\001-開源項(xiàng)目源碼\004-內(nèi)核源碼\linux-4.15.1\linux-4.15.1\include\linux\types.h typedef unsigned int __u32; typedef __u32 __kernel_dev_t; typedef __kernel_dev_t dev_t;問題:為什么不直接寫成 typedef unsigned int dev_t;D:\005-代碼\001-開源項(xiàng)目源碼\004-內(nèi)核源碼\linux-4.15.1\linux-4.15.1\include\linux\cdev.h struct cdev {struct kobject kobj; // 內(nèi)嵌的內(nèi)核對(duì)象struct module *owner;// 該字符設(shè)備所在的內(nèi)核模塊(所有者)的對(duì)象指針const struct file_operations *ops;// 字符設(shè)備所能實(shí)現(xiàn)的操作表struct list_head list;// 用來將已經(jīng)向內(nèi)核注冊(cè)的所有字符設(shè)備形成鏈表dev_t dev;//字符設(shè)備的設(shè)備號(hào),由主設(shè)備號(hào)和次設(shè)備號(hào)構(gòu)成(如果是一次申請(qǐng)多個(gè)設(shè)備號(hào),此設(shè)備號(hào)為第一個(gè)),主設(shè)備號(hào)12位,次設(shè)備號(hào)20位unsigned int count; // 隸屬于同一主設(shè)備號(hào)的次設(shè)備號(hào)的個(gè)數(shù) } __randomize_layout;

3 struct cdev與const struct file_operations之間的關(guān)系

4.struct file_operations源碼

E:\004-代碼\002-內(nèi)核源碼\linux-4.15.1\linux-4.15.1\include\linux\fs.h construct file_operations {struct module *owner;loff_t (*llseek) (struct file *, loff_t, int);ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);int (*iterate) (struct file *, struct dir_context *);int (*iterate_shared) (struct file *, struct dir_context *);unsigned int (*poll) (struct file *, struct poll_table_struct *);long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);long (*compat_ioctl) (struct file *, unsigned int, unsigned long);int (*mmap) (struct file *, struct vm_area_struct *);unsigned long mmap_supported_flags;int (*open) (struct inode *, struct file *);int (*flush) (struct file *, fl_owner_t id);int (*release) (struct inode *, struct file *);int (*fsync) (struct file *, loff_t, loff_t, int datasync);int (*fasync) (int, struct file *, int);int (*lock) (struct file *, int, struct file_lock *);ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);int (*check_flags)(int);int (*flock) (struct file *, int, struct file_lock *);ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);int (*setlease)(struct file *, long, struct file_lock **, void **);long (*fallocate)(struct file *file, int mode, loff_t offset,loff_t len);void (*show_fdinfo)(struct seq_file *m, struct file *f); #ifndef CONFIG_MMUunsigned (*mmap_capabilities)(struct file *); #endifssize_t (*copy_file_range)(struct file *, loff_t, struct file *,loff_t, size_t, unsigned int);int (*clone_file_range)(struct file *, loff_t, struct file *, loff_t,u64);ssize_t (*dedupe_file_range)(struct file *, u64, u64, struct file *,u64); } __randomize_layout;從源碼中可以看出,每個(gè)字段都是一個(gè)函數(shù),都是指向VFS層所調(diào)用的系統(tǒng)調(diào)用所對(duì)應(yīng)的函數(shù).

?

5.字符設(shè)備驅(qū)動(dòng)框架

6.編寫字符設(shè)備驅(qū)動(dòng)的步驟

?

cdev_alloc()--動(dòng)態(tài)申請(qǐng)或構(gòu)造cdev內(nèi)存 cdev_init() --初始化函數(shù),初始化cdev的成員并且建立起cdev與file_operations之間的關(guān)聯(lián)關(guān)系 cdev_add() --注冊(cè)cdev設(shè)備對(duì)象,也就是添加cdev對(duì)象到字符設(shè)備列表中 cdev_del() --將cdev對(duì)象從系統(tǒng)中刪除,也就是注銷 cdev_put() --釋放cdev內(nèi)存設(shè)備號(hào)的申請(qǐng)與釋放 一個(gè)字符設(shè)備或者一個(gè)塊設(shè)備都有一個(gè)主設(shè)備號(hào)和一個(gè)次設(shè)備號(hào),主設(shè)備號(hào)用來標(biāo)識(shí)與設(shè)備文件相連的 驅(qū)動(dòng)程序,用來反映設(shè)備的類型,次設(shè)備號(hào)被驅(qū)動(dòng)程序用來辨別操作的到底是哪一個(gè)設(shè)備,用來區(qū)分同類 型的設(shè)備,在這里給出三個(gè)宏和三個(gè)函數(shù)分別從設(shè)備號(hào)中提取主設(shè)備號(hào)和次設(shè)備號(hào),將主設(shè)備號(hào)和次設(shè) 備號(hào)拼湊成設(shè)備號(hào),靜態(tài)地申請(qǐng)?jiān)O(shè)備號(hào),動(dòng)態(tài)地申請(qǐng)?jiān)O(shè)備號(hào)以及釋放設(shè)備號(hào).

7.字符設(shè)備結(jié)構(gòu)

問題:struct char_device_struct與struct cdev有什么關(guān)系?

8.字符設(shè)備驅(qū)動(dòng)程序的注冊(cè)

這個(gè)cdrdevs就是字符設(shè)備表.

9.從系統(tǒng)調(diào)用到驅(qū)動(dòng)程序

10.用戶空間與內(nèi)核空間數(shù)據(jù)的傳送

11.參考資料與思考問題

?

總結(jié)

以上是生活随笔為你收集整理的【linux内核分析与应用-陈莉君】字符设备驱动的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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