網(wǎng)站開(kāi)發(fā)使用哪種語(yǔ)言免費(fèi)網(wǎng)站站長(zhǎng)查詢
文章目錄
- 注冊(cè)雜項(xiàng)設(shè)備
- 驅(qū)動(dòng)模塊傳參
- 注冊(cè)字符設(shè)備
開(kāi)發(fā)環(huán)境: windows + ubuntu18.04 + 迅為rk3568開(kāi)發(fā)板
注冊(cè)雜項(xiàng)設(shè)備
相較于字符設(shè)備,雜項(xiàng)設(shè)備有以下兩個(gè)優(yōu)點(diǎn):
- 節(jié)省主設(shè)備號(hào):雜項(xiàng)設(shè)備的主設(shè)備號(hào)固定為 10,在系統(tǒng)中注冊(cè)多個(gè) misc 設(shè)備驅(qū)動(dòng)時(shí),只需使用子設(shè)備號(hào)進(jìn)行區(qū)分即可。
- 使用簡(jiǎn)單:相比如普通的字符設(shè)備驅(qū)動(dòng), misc驅(qū)動(dòng)只需要將基本信息通過(guò)結(jié)構(gòu)體傳遞給相應(yīng)處理函數(shù)即可。
在linxu系統(tǒng)中可使用 cat /proc/misc
命令查看系統(tǒng)中的雜項(xiàng)設(shè)備。注冊(cè)雜項(xiàng)設(shè)備的步驟:
-
1.填充設(shè)備操作集結(jié)構(gòu)體
struct file_operations
; -
2.填充雜項(xiàng)設(shè)備結(jié)構(gòu)體
struct miscdevice
; -
3.使用函數(shù)
misc_register
注冊(cè)雜項(xiàng)設(shè)備; -
4.使用函數(shù)
misc_deregister
卸載雜項(xiàng)設(shè)備;
上面三步可使用下面函數(shù)直觀用表達(dá),即:
static struct file_operations xxx_fops{.owner = THIS_MODULE, .read = xxx_read, ....
};
struct miscdevice xxx_dev{.minor = MISC_DYNAMIC_MINOR, .name = "xxx", .fops = &xxx_fops
};
static int __init xxx_init(void) //驅(qū)動(dòng)入口函數(shù)
{int ret;printk(KERN_EMERG "xxx_init\r\n");ret = misc_register(&xxx_dev);//注冊(cè)雜項(xiàng)設(shè)備if(ret<0){printk( "misc_register failed\r\n");return -1;}printk( "misc_register ok\r\n");return 0;
}
static void __exit xxx_exit(void) //驅(qū)動(dòng)出口函數(shù)
{printk(KERN_EMERG "xxx_exit\r\n");misc_deregister(&xxx_dev); //卸載雜項(xiàng)設(shè)備
}
module_init(xxx_init); //注冊(cè)入口函數(shù)
module_exit(xxx_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("xxx");
具體實(shí)現(xiàn)注冊(cè)一個(gè)雜項(xiàng)設(shè)備的示例代碼如下:
#include <linux/kernel.h>
#include <linux/init.h> //初始化頭文件
#include <linux/module.h> //最基本的文件,支持動(dòng)態(tài)添加和卸載模塊。
#include <linux/miscdevice.h> //注冊(cè)雜項(xiàng)設(shè)備頭文件
#include <linux/fs.h> //注冊(cè)設(shè)備節(jié)點(diǎn)的文件結(jié)構(gòu)體
#include <linux/uaccess.h>// 打開(kāi)雜項(xiàng)設(shè)備
int _open(struct inode *inode,struct file*file)
{printk(KERN_EMERG"hello misc");return 0;
}// 關(guān)閉雜項(xiàng)設(shè)備
int close(struct inode * inode, struct file *file)
{printk(KERN_EMERG"close");return 0;
}// 讀取雜項(xiàng)設(shè)備中的數(shù)據(jù)
ssize_t misc_read (struct file *file, char __user *buff, size_t size, loff_t *loff)
{char kbuff[32] = "kernel";if(copy_to_user(buff,kbuff,strlen(kbuff)) != 0) // 將內(nèi)核中的數(shù)據(jù)給應(yīng)用{printk("copy_to_user error\r\n");return -1;} printk(KERN_EMERG"copy_to_user is successful\r\n");return size;
}// 寫(xiě)入數(shù)據(jù)到雜項(xiàng)設(shè)備中
ssize_t misc_write (struct file *file, const char __user *buff, size_t size, loff_t *loff)
{char kbuff[32] ;if(copy_from_user(kbuff,buff,size)!= 0) // 從應(yīng)用那兒獲取數(shù)據(jù){printk("copy_from_user error\r\n");return -1;} printk(KERN_EMERG"copy_from_user data:%s\r\n",kbuff);return size;
}// 設(shè)備文件描述集
struct file_operations misc_fops ={.owner = THIS_MODULE,.open = misc_open,.release = close,.read = misc_read,.write = misc_write
};struct miscdevice misc_dev = {.minor = MISC_DYNAMIC_MINOR,.name = "hello_misc", // 雜項(xiàng)設(shè)備名 注冊(cè)成功后會(huì)在 /dev目錄下顯示.fops = &misc_fops
};// 驅(qū)動(dòng)的入口函數(shù)
static int __init misc_init(void)
{int ret = 0;ret = misc_register(&misc_dev);if(ret < 0)printk(KERN_EMERG"misc register is error\r\n.");elseprintk(KERN_EMERG"misc register is seccussful\r\n.");return 0;
}//驅(qū)動(dòng)的出口函數(shù)
static void __exit misc_exit(void)
{misc_deregister(&misc_dev);printk(KERN_EMERG"baibai\r\n");
}module_init(misc_init);
module_exit(misc_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("zhouxianjie0716@qq.com");
編譯傳送到開(kāi)發(fā)板上后,先試用insmod +驅(qū)動(dòng)名.ko
掛載驅(qū)動(dòng),其結(jié)果為:
上述驅(qū)動(dòng)代碼的測(cè)試代碼如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main(int argc,char *argv[])
{char filePath[] = "/dev/hello_misc";// 打開(kāi)文件int fd = open(filePath,O_RDWR);if(fd < 0){printf("opening is failed.\n");return -1;}elseprintf("opening is successful.\n");// 讀取char buff1[32],buff2[32] = "hello this is app";read(fd,buff1,sizeof(buff1));printf("buff1 is %s.\n",buff1);// 寫(xiě)入write(fd,buff2,sizeof(buff2)); close(fd);return 0;
}
使用./+程序名
運(yùn)行測(cè)試代碼后,得結(jié)果如下:
驅(qū)動(dòng)模塊傳參
總所周知,應(yīng)用程序傳參是通過(guò)shell終端傳,只要將main函數(shù)按照下面格式書(shū)寫(xiě)即可完成傳參操作
int main(int argc ,char *argv[])
{return 0;
}
相比之下,驅(qū)動(dòng)模塊傳遞參數(shù)需要借助其他函數(shù)完成傳參操作:
1. 傳遞單個(gè)參數(shù)給內(nèi)核
module_param(name, type, perm)
參數(shù)解釋:
-
name:參數(shù)名,既是外部參數(shù)名,又是內(nèi)部參數(shù)名。
-
type:參數(shù)的數(shù)據(jù)類型,可取int、charp等。
-
perm:訪問(wèn)權(quán)限。八進(jìn)制,如:0777。0表示該參數(shù)在文件系統(tǒng)中不可見(jiàn)。
注意:傳遞字符作為參數(shù)時(shí)數(shù)據(jù)類為charp
,而不是char
.
2.傳遞數(shù)組給內(nèi)核
module_param_array(name, type, nump, perm)
- module_param_array(name,type,nump,perm)
- name:數(shù)組參數(shù)名,既是外部參數(shù),又是內(nèi)部參數(shù)
- type:參數(shù)的數(shù)據(jù)類型
- nump:終端傳給數(shù)組的實(shí)際元素個(gè)數(shù)(指針變量)
- perm:訪問(wèn)權(quán)限,0644。0表示該參數(shù)在文件系統(tǒng)中不可見(jiàn)
3.傳遞字符串給內(nèi)核
module_param_string(name, string, len, perm)
- name:參數(shù)名,外部參數(shù)名
- string:內(nèi)部參數(shù)名(內(nèi)部字符數(shù)組名)
- len:數(shù)組長(zhǎng)度
- perm:訪問(wèn)權(quán)限,0644。0表示該參數(shù)在文件系統(tǒng)中不可見(jiàn)
傳遞參給內(nèi)核的作用:
- 1.設(shè)置驅(qū)動(dòng)的相關(guān)參數(shù),如:設(shè)備數(shù)量、設(shè)備緩沖區(qū)大小等等。
- 2.可進(jìn)行安全校驗(yàn),放置驅(qū)動(dòng)被他人盜用。
說(shuō)明:
參數(shù)傳遞的適用時(shí)機(jī)為 加載驅(qū)動(dòng)到內(nèi)核時(shí),命令形式為:insmod +驅(qū)動(dòng)名.ko +參數(shù)1名=參數(shù)值 參數(shù)2名=參數(shù)值 ……
。例如下面示例中使用insmod file.ko date=12
傳遞參數(shù):
#include <linux/module.h>
#include <linux/init.h>// 保存參數(shù)
static int date;
static int date1;
static int data[5];
static int count;
static char str[32];
static char *strData;// 傳遞單個(gè)參數(shù)
module_param(date,int,S_IRUGO|S_IWUSR); // 可讀可寫(xiě)
module_param(date1,int,S_IRUGO); // 可讀可寫(xiě)
module_param(strData,charp,S_IRUGO); // 可讀// 傳遞多個(gè)參數(shù)
module_param_array(data,int,&count,S_IRUGO); // 可讀
module_param_string(str,str,sizeof(str),S_IRUGO); // 可讀// 驅(qū)動(dòng)的入口函數(shù)
static int __init dev_init(void)
{int i=0;if(strcmp(str,"myTest")!=0){printk("dev_init error\r\n");return -1;}printk("---------------------------------------\r\n");printk(KERN_EMERG"dev_init is successful!\r\n");for(i=0;i<count;++i)printk("data[%d] = %d \r\n",i,data[i]);printk("str:%s strData:%s\r\n",str,strData);printk("date:%d count:%d\r\n",date,count);data[1] = 111;date = 10;date1 = 111;return 0;
}//驅(qū)動(dòng)的出口函數(shù)
static void __exit dev_exit(void)
{int i=0;for( i=0;i<count;++i)printk("data[%d] = %d \r\n",i,data[i]);printk("date:%d count:%d\r\n",date,count);printk(KERN_EMERG"dev_exit is successful\r\n");
}module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("zhouxianjie0716@qq.com");
注冊(cè)字符設(shè)備
步驟一:驅(qū)動(dòng)初始化,需要申請(qǐng)?jiān)O(shè)備號(hào),初始化并且注冊(cè)cdev結(jié)構(gòu)體,初始化硬件;
可使用動(dòng)態(tài)申請(qǐng)或靜態(tài)申請(qǐng)?jiān)O(shè)備號(hào),其中動(dòng)態(tài)申請(qǐng)?jiān)O(shè)備號(hào)一般在235-255,靜態(tài)申請(qǐng)則一般由用戶手動(dòng)輸入。
靜態(tài)申請(qǐng)的函數(shù)原型為:
int register_chrdev_region(dev_t, unsigned, const char *);
參數(shù)含義:
- from: 自定義的 dev_t 類型設(shè)備號(hào)。
- count: 申請(qǐng)?jiān)O(shè)備的數(shù)量。
- name: 申請(qǐng)的設(shè)備名稱。
函數(shù)返回值:申請(qǐng)成功返回 0,申請(qǐng)失敗返回負(fù)數(shù)。
動(dòng)態(tài)申請(qǐng)的函數(shù)原型為:
int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *);
參數(shù)含義:
- dev : 會(huì)將申請(qǐng)完成的設(shè)備號(hào)保存在 dev 變量中。
- baseminor: 次設(shè)備號(hào)可申請(qǐng)的最小值。
- count: 申請(qǐng)?jiān)O(shè)備的數(shù)量。
- name: 申請(qǐng)的設(shè)備名稱。
函數(shù)返回值:申請(qǐng)成功返回 0,申請(qǐng)失敗返回負(fù)
Linux 內(nèi)核中將字符設(shè)備抽象成一個(gè)具體的數(shù)據(jù)結(jié)構(gòu) (struct cdev), 我們可以理解為字符設(shè)備對(duì)象,cdev 記錄了字符設(shè)備號(hào)、內(nèi)核對(duì)象、文件操作 file_operations 結(jié)構(gòu)體(設(shè)備的打開(kāi)、讀寫(xiě)、關(guān)閉等操作接口)等信息:
struct cdev {struct kobject kobj; //內(nèi)嵌的內(nèi)核對(duì)象.struct module *owner; //該字符設(shè)備所在的內(nèi)核模塊的對(duì)象指針. const struct file_operations *ops; //該結(jié)構(gòu)描述了字符設(shè)備所能實(shí)現(xiàn)的方法,是極為關(guān)鍵的一個(gè)結(jié)構(gòu)體.struct list_head list; //用來(lái)將已經(jīng)向內(nèi)核注冊(cè)的所有字符設(shè)備形成鏈表. dev_t dev; //字符設(shè)備的設(shè)備號(hào),由主設(shè)備號(hào)和次設(shè)備號(hào)構(gòu)成. unsigned int count; //隸屬于同一主設(shè)備號(hào)的次設(shè)備號(hào)的個(gè)數(shù).
};
初始化設(shè)備描述集cdev結(jié)構(gòu)體的函數(shù)原型為:
void cdev_init(struct cdev *, const struct file_operations *);
參數(shù)含義:
- 參數(shù)1:表示是抽象設(shè)備結(jié)構(gòu)體;
- 參數(shù)2:表示文件操作集;
注冊(cè)設(shè)備到內(nèi)驅(qū)使用下面函數(shù)
int cdev_add(struct cdev *, dev_t, unsigned);
參數(shù)含義:
- 參數(shù)1:為要添加的 struct cdev 類型的結(jié)構(gòu)體
- 參數(shù)2:為申請(qǐng)的字符設(shè)備號(hào)
- 參數(shù)3:為和該設(shè)備關(guān)聯(lián)的設(shè)備編號(hào)的數(shù)量
若函數(shù)在內(nèi)核中添加成功返回 0,添加失敗返回負(fù)數(shù)。
步驟二:構(gòu)建設(shè)備文件操作描述集file_operations
也就是read、write、open、close等函數(shù)。
步驟三:生成并且添加設(shè)備節(jié)點(diǎn)
- 手動(dòng)添加設(shè)備節(jié)點(diǎn):也就是在加載驅(qū)動(dòng)到內(nèi)核時(shí)添加,即
mknod + 路徑/設(shè)備名 +設(shè)備類型 + 主設(shè)備號(hào) + 次設(shè)備號(hào)
- 自動(dòng)添加設(shè)備節(jié)點(diǎn):初始化內(nèi)核時(shí),使用函數(shù)自動(dòng)添加。即先試用函數(shù)
class_create
創(chuàng)建一個(gè)類,在使用函數(shù)device_create
創(chuàng)建并且添加設(shè)備節(jié)點(diǎn)。
class_create
函數(shù)說(shuō)明:
#define class_create(owner, name) \
({ \
static struct lock_class_key __key; \ __class_create(owner, name, &__key); \
})
函數(shù)作用:
用于動(dòng)態(tài)創(chuàng)建設(shè)備的邏輯類,并完成部分字段的初始化,然后將其添加進(jìn) Linux 內(nèi)核系統(tǒng)。
參數(shù)含義:
- owner:指向函數(shù)即將創(chuàng)建的這個(gè) struct class 的模塊。一般為 THIS_MODULE。
- name:代表即將創(chuàng)建的 struct class 變量的名字。
返回值:struct class * 類型的類。
device_create
函數(shù)說(shuō)明:
struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt,...);
函數(shù)作用:
用來(lái)在 class 類中下創(chuàng)建一個(gè)設(shè)備屬性文件,udev 會(huì)自動(dòng)識(shí)別從而進(jìn)行設(shè)備節(jié)點(diǎn)的創(chuàng)建。
參數(shù)含義:
- cls:指定所要?jiǎng)?chuàng)建的設(shè)備所從屬的類。
- parent:指定該設(shè)備的父設(shè)備,如果沒(méi)有就指定為 NULL。
- devt:指定創(chuàng)建設(shè)備的設(shè)備號(hào)。
- drvdata:被添加到該設(shè)備回調(diào)的數(shù)據(jù),沒(méi)有則指定為 NULL。
- fmt:添加到系統(tǒng)的設(shè)備節(jié)點(diǎn)名稱。
返回值:struct device * 類型結(jié)構(gòu)體的設(shè)備
步驟四:注銷字符設(shè)備驅(qū)動(dòng),
- 步驟一:使用函數(shù)
unregister_chrdev_region
釋放設(shè)備號(hào)
void unregister_chrdev_region(dev_t, unsigned)
該函數(shù)只有一個(gè)參數(shù),為要?jiǎng)h除設(shè)備的設(shè)備號(hào),并且函數(shù)無(wú)返回值。
- 步驟二:使用函數(shù)
cdev_del
步驟二:刪除設(shè)備操作集卸載cdev
void cdev_del(struct cdev *);
該函數(shù)只有一個(gè)參數(shù),為要?jiǎng)h除的 struct cdev 類型的結(jié)構(gòu)體,并且函數(shù)無(wú)返回值。
- 步驟三:使用函數(shù)
device_destroy
卸載設(shè)備
void device_destroy(struct class *cls, dev_t devt);
用來(lái)刪除 cls 類中的devt設(shè)備屬性文件,udev 會(huì)自動(dòng)識(shí)別從而進(jìn)行設(shè)備節(jié)點(diǎn)的刪除。
- 步驟四:使用函數(shù)
class_destroy
刪除類class
void class_destroy(struct class *cls);
該函數(shù)只有一個(gè)參數(shù),為要?jiǎng)h除的類,并且函數(shù)無(wú)返回值。
示例代碼
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>#define DEVICE_NUMBER 1 // 設(shè)備數(shù)量
#define DEVICE_SNAME "schrdev" // 靜態(tài)申請(qǐng)時(shí)設(shè)備名
#define DEVICE_ANAME "achrdev" // 動(dòng)態(tài)申請(qǐng)時(shí)設(shè)備名
#define DEVICE_MINOR_NUM 0 // 次設(shè)備號(hào)起始地址
#define DEVICE_CLASS_NAME "myTestClass" // 類名
#define DEVICE_MYNAME "mytest"// 打開(kāi)設(shè)備
int chrdev_open(struct inode*inode,struct file*file)
{printk("chrdev_open is opened\r\n");return 0;
}// 保存設(shè)備號(hào) 其中前12位為主設(shè)備號(hào) 后20位為次設(shè)備號(hào)
static dev_t dev_num;// 定義主設(shè)備號(hào) 次設(shè)備號(hào)
static int major_num,minor_num; // 設(shè)備信息描述集
struct cdev cdev;// 類描述集
struct class *cls;// 設(shè)備描述集
struct device*device;// 傳遞單個(gè)參數(shù)
module_param(major_num,int,S_IRUGO); // 可讀
module_param(minor_num,int,S_IRUGO); // 可讀// 文件操作集
struct file_operations chrdev_opr = {.owner = THIS_MODULE,.open = chrdev_open
};// 驅(qū)動(dòng)的入口函數(shù)
static int __init dev_init(void)
{int ret;/* 步驟一:申請(qǐng)?jiān)O(shè)備號(hào) */// 有傳遞主設(shè)備號(hào)就靜態(tài)申請(qǐng)if(major_num){ dev_num = MKDEV(major_num, minor_num);//將主設(shè)備號(hào) 次設(shè)備號(hào)合并成設(shè)備號(hào)//參數(shù)分別表示 設(shè)備號(hào) 設(shè)備數(shù)量 設(shè)備名稱ret = register_chrdev_region(dev_num, DEVICE_NUMBER, DEVICE_SNAME); if(ret < 0){printk("dev_init error\r\n");return -1;}} // 否則就動(dòng)態(tài)申請(qǐng)else{// 參數(shù):設(shè)備號(hào) 次設(shè)備號(hào)起始地址 設(shè)備數(shù)量 設(shè)備名稱ret = alloc_chrdev_region(&dev_num , DEVICE_MINOR_NUM, DEVICE_NUMBER, DEVICE_ANAME);if(ret < 0){printk("dev_init error\r\n");return -1;}// 獲取主設(shè)備號(hào) 次設(shè)備號(hào)major_num = MAJOR(dev_num);minor_num = MINOR(dev_num);}printk("---------------------------------------\r\n");printk("dev_num:%d major_num:%d minor_num:%d\r\n",dev_num,major_num,minor_num);/* 步驟二:初始化設(shè)備 */// 初始化cdevcdev.owner = THIS_MODULE;// 初始化設(shè)備 cdev_init(&cdev, &chrdev_opr);/* 步驟三:注冊(cè)設(shè)備到內(nèi)核 *///添加(注冊(cè))到內(nèi)核 參數(shù): 設(shè)備 設(shè)備號(hào) 設(shè)備數(shù)量cdev_add(&cdev, dev_num, DEVICE_NUMBER);/* 步驟四:先創(chuàng)建類再自動(dòng)創(chuàng)建添加設(shè)備名稱*/// 創(chuàng)建類 參數(shù)1: 類的歸屬 參數(shù)2: 類名cls = class_create(THIS_MODULE,DEVICE_CLASS_NAME);// 創(chuàng)建設(shè)備 參數(shù)1: 歸屬到類 參數(shù)2:設(shè)備的父設(shè)備 參數(shù)3:設(shè)備號(hào) 參數(shù)4:添加到設(shè)備的回調(diào)數(shù)據(jù) 參數(shù)5:設(shè)備名device = device_create(cls,NULL,dev_num,NULL,DEVICE_MYNAME);printk("auto add device name\r\n");return 0;
}//驅(qū)動(dòng)的出口函數(shù)
static void __exit dev_exit(void)
{/* 步驟一:注銷設(shè)備號(hào) 參數(shù):設(shè)備號(hào) 設(shè)備數(shù)量 */ unregister_chrdev_region(MKDEV(major_num, minor_num), DEVICE_NUMBER);/* 步驟二:刪除設(shè)備操作集 */cdev_del(&cdev);/* 步驟三:刪除設(shè)備*/device_destroy(cls,dev_num);/* 步驟四: 刪除類*/class_destroy( cls);printk(KERN_EMERG"dev_exit is successful\r\n");
}module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("zhouxianjie0716@qq.com");
使用加載驅(qū)動(dòng)到內(nèi)核insmod file.ko命令,得結(jié)果
在測(cè)試驅(qū)動(dòng)前需要使用mknod /dev/mytest c 236 0
創(chuàng)建設(shè)備文件,命令格式為:mknod + /路徑/設(shè)備名稱 +設(shè)備類型+主設(shè)備號(hào) + 次設(shè)備號(hào)
。
然后就可寫(xiě)一個(gè)應(yīng)用程序來(lái)測(cè)試我們的字符驅(qū)動(dòng)是否成功注冊(cè),測(cè)試源碼如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main(int argc,char* argv[])
{char name[] = "/dev/mytest";int fd = open(name,O_RDONLY); // 僅讀if(fd < 0){printf("open is failed\n");return -1;}close(fd);return 0;
}
執(zhí)行測(cè)試程序后結(jié)果如下:
注意:在運(yùn)行測(cè)試程序時(shí),一定要先創(chuàng)建驅(qū)動(dòng)文件,否則就會(huì)報(bào)段錯(cuò)誤,具體如下:
雜項(xiàng)設(shè)備與字符設(shè)備的比較:
- 雜項(xiàng)設(shè)備的主設(shè)備號(hào)固定為10,而字符設(shè)備的主設(shè)備號(hào)需要?jiǎng)?chuàng)建。
- 雜項(xiàng)設(shè)備的創(chuàng)建相對(duì)簡(jiǎn)單,只需要填充設(shè)備操作集結(jié)構(gòu)體、雜項(xiàng)設(shè)備結(jié)構(gòu)體再注冊(cè)即可。而字符設(shè)備需要經(jīng)過(guò) 申請(qǐng)?jiān)O(shè)備號(hào)、初始化并且注冊(cè)cdev結(jié)構(gòu)體、初始化硬件、構(gòu)建設(shè)備文件操作描述集、生成并且添加設(shè)備節(jié)點(diǎn)。
- 雜項(xiàng)設(shè)備與字符設(shè)備都需要構(gòu)建文件操作描述集。(應(yīng)用層調(diào)用驅(qū)動(dòng)的核心)