怎么安裝pos機(jī)驅(qū)動(dòng),字符設(shè)備驅(qū)動(dòng)

 新聞資訊  |   2023-05-04 09:57  |  投稿人:pos機(jī)之家

網(wǎng)上有很多關(guān)于怎么安裝pos機(jī)驅(qū)動(dòng),字符設(shè)備驅(qū)動(dòng)的知識(shí),也有很多人為大家解答關(guān)于怎么安裝pos機(jī)驅(qū)動(dòng)的問(wèn)題,今天pos機(jī)之家(www.afbey.com)為大家整理了關(guān)于這方面的知識(shí),讓我們一起來(lái)看下吧!

本文目錄一覽:

1、怎么安裝pos機(jī)驅(qū)動(dòng)

怎么安裝pos機(jī)驅(qū)動(dòng)

前言

字符設(shè)備驅(qū)動(dòng)是Linux最基本的驅(qū)動(dòng),很多學(xué)習(xí)驅(qū)動(dòng)的朋友都是從這個(gè)開(kāi)始的,比如LED,或者按鍵驅(qū)動(dòng)等。但是很多時(shí)候你看一些視頻教程或書(shū)籍時(shí),會(huì)發(fā)現(xiàn)其實(shí)不是很完整,特別是既看書(shū)又看視頻教程的,會(huì)發(fā)現(xiàn)好像不怎么一樣。接下來(lái)一起來(lái)總結(jié)一下!

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

在Linux內(nèi)核中, 使用cdev結(jié)構(gòu)體來(lái)描述一個(gè)字符設(shè)備。

struct cdev { struct kobject kobj; //內(nèi)嵌的kobject對(duì)象 struct module *owner;//所屬模塊 const struct file_operations *ops; //文件操作結(jié)構(gòu)體 struct list_head list; dev_t dev; //設(shè)備號(hào) unsigned int count;};

cdev結(jié)構(gòu)體的dev_t成員定義了設(shè)備號(hào),為32位,其中12位為主設(shè)備號(hào),20位為次設(shè)備號(hào)。

使用下面的宏來(lái)定義dev_t

MKDEV(int major, int minor)

使用下面的宏來(lái)獲取主設(shè)備號(hào)和次設(shè)備號(hào)

MAJOR(dev_t dev)MINOR(dev_t dev)字符設(shè)備API

/*函數(shù)功能:分配一些設(shè)備號(hào)參數(shù)說(shuō)明: from:起始設(shè)備號(hào),必須要包含主設(shè)備號(hào) count: 連續(xù)分配的數(shù)量 name: 設(shè)備或驅(qū)動(dòng)的名稱(chēng)*/int register_chrdev_region(dev_t from, unsigned count, const char *name)/*函數(shù)功能:分配一些字符設(shè)備號(hào)參數(shù)說(shuō)明: dev:第一個(gè)被分配的設(shè)備號(hào) baseminor:起始次設(shè)備號(hào) count:分配的次設(shè)備號(hào)數(shù)(分配的設(shè)備號(hào)數(shù)) name: 相關(guān)設(shè)備或驅(qū)動(dòng)的名稱(chēng)*/int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)/*函數(shù)功能: 釋放一些設(shè)備號(hào)參數(shù)說(shuō)明: from:釋放的起始設(shè)備號(hào) count: 釋放的設(shè)備號(hào)數(shù)*/ void unregister_chrdev_region(dev_t from, unsigned count)

/*函數(shù)功能:初始化一個(gè)cdev結(jié)構(gòu)體參數(shù)說(shuō)明: cdev:要初始化的cdev結(jié)構(gòu)體 fops:該字符設(shè)備的file_operations (操作函數(shù))*/void cdev_init(struct cdev *cdev, const struct file_operations *fops)/*函數(shù)功能:動(dòng)態(tài)分配一個(gè)cdev結(jié)構(gòu)體說(shuō)明:該函數(shù)不常用,因?yàn)樽址O(shè)備都會(huì)封裝一個(gè)新的結(jié)構(gòu)體, 然后使用kzalloc來(lái)分配內(nèi)存(結(jié)構(gòu)體)*/struct cdev *cdev_alloc(void)/*函數(shù)功能: 添加一個(gè)字符設(shè)備到系統(tǒng)參數(shù)說(shuō)明: p:設(shè)備的cdev結(jié)構(gòu)體 dev:第一個(gè)設(shè)備的設(shè)備號(hào) count:連續(xù)的次設(shè)備號(hào)數(shù)*/int cdev_add(struct cdev *p, dev_t dev, unsigned count)/*函數(shù)功能: 從系統(tǒng)中移除一個(gè)cdev參數(shù)說(shuō)明: p:要移除的cdev結(jié)構(gòu)體*/void cdev_del(struct cdev *p)

把上面的API分成兩段,一段是分配和釋放設(shè)備號(hào)的,另一段就是分配字符設(shè)備和注冊(cè)到系統(tǒng)中的。

register_chrdev_region() 和 alloc_chrdev_region() 的區(qū)別:

register_chrdev_region() 函數(shù)用于已知起始設(shè)備的設(shè)備號(hào)的情況,而alloc_chrdev_region() 用于設(shè)備號(hào)未知,向系統(tǒng)動(dòng)態(tài)申請(qǐng)未被占用的設(shè)備號(hào)的情況。alloc_chrdev_region() 相比于 register_chrdev_region() 的優(yōu)點(diǎn)就在于它會(huì)自動(dòng)避開(kāi)設(shè)備號(hào)重復(fù)的沖突。

字符設(shè)備的驅(qū)動(dòng)架構(gòu)

下面是寫(xiě)一個(gè)字符設(shè)備驅(qū)動(dòng)的一般步驟:

(1) 為設(shè)備定義一個(gè)設(shè)備相關(guān)的結(jié)構(gòu)體(包含設(shè)備所涉及的cdev,私有數(shù)據(jù)及鎖等信息)

(2) 初始化函數(shù)xxx_init的定義

1. 向系統(tǒng)申請(qǐng)?jiān)O(shè)備號(hào)(register_chrdev_region()或alloc_chrdev_region())

2. 使用kzalloc申請(qǐng)?jiān)O(shè)備內(nèi)存(為(1)中定義的結(jié)構(gòu)體申請(qǐng)存儲(chǔ)空間)

3. 調(diào)用cdev_init()初始化cdev

4. 調(diào)用cdev_add()向系統(tǒng)注冊(cè)設(shè)備

(3) 卸載函數(shù)xxx_exit的定義

1. 釋放設(shè)備號(hào)(unregister_chrdev_region())

2. 調(diào)用cdev_del()注銷(xiāo)設(shè)備

(4) 定義file_operations

1. 實(shí)現(xiàn)write()函數(shù) (copy_to_user())

2. 實(shí)現(xiàn)read()函數(shù)(copy_from_user())

3. 根據(jù)需要實(shí)現(xiàn)其他函數(shù)....

模板程序

/*設(shè)備結(jié)構(gòu)體*/struct xxx_dev_t{ struct cdev cdev; ...};struct xxx_dev_t *dev;dev_t devno;//讀設(shè)備ssize_t xxx_read(struct file *filp, char __user *buf, size_t count, loff_t* f_pos){ ... copy_to_user(buf, ..., ...);}//寫(xiě)設(shè)備ssize_t xxx_write(struct file *filp, const char __user *buf, size_t count, loff_t* f_pos){ ... copy_from_user(..., buf, ...);}//操作函數(shù)file_operationsstruct file_operations xxx_fops = { .owner = THIS_MODULE, .read = xxx_read, .write = xxx_write, ...};//設(shè)備驅(qū)動(dòng)模塊加載函數(shù)static int __init xxx_init(void){ ... devno = MKDEV(xxx_major, 0); //(1)申請(qǐng)?jiān)O(shè)備號(hào) if(xxx_major) { register_chrdev_region(devno, 1, "xxx_dev"); } else { alloc_chrdev_region(&devno, 0, 1, "xxx_dev"); } //(2)為設(shè)備結(jié)構(gòu)體申請(qǐng)內(nèi)存(推薦使用devm_kzalloc) dev = kzalloc(sizeof(struct xxx_dev_t), GFP_KERNEL); //(3)初始化cdev cdev_init(&dev.cdev, &xxx_fops); dev.cdev.owner = THIS_MODULE; //(4)向系統(tǒng)注冊(cè)設(shè)備 cdev_add(dev.cdev, dev_no, 1);}module_init(xxx_init);//設(shè)備驅(qū)動(dòng)模塊卸載函數(shù)static void __exit xxx_exit(void){ //釋放設(shè)備號(hào) unregister_chrdev_region(dev_no, 1); //注銷(xiāo)設(shè)備 cdev_del(&dev.cdev); ...}module_exit(xxx_exit);MODULE_LICENSE("GPL v2");簡(jiǎn)化字符設(shè)備驅(qū)動(dòng)架構(gòu)

每次編寫(xiě)初始化函數(shù)都要一步一步寫(xiě),為了簡(jiǎn)化這個(gè)流程,Linux提供了一些封裝的接口函數(shù)來(lái)讓我們調(diào)用。

/*函數(shù)功能:注冊(cè)字符設(shè)備參數(shù)說(shuō)明:major:主設(shè)備號(hào),0表示動(dòng)態(tài)分配 name: 設(shè)備名 fops: 操作函數(shù)返回值: 申請(qǐng)的主設(shè)備號(hào) */static inline int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)/*函數(shù)功能:注銷(xiāo)字符設(shè)備參數(shù)說(shuō)明:major:主設(shè)備號(hào) name: 設(shè)備名*/static inline void unregister_chrdev(unsigned int major, const char *name)

分析一下上面兩個(gè)函數(shù)的源碼

//register_chrdev調(diào)用了__register_chrdevint __register_chrdev(unsigned int major, unsigned int baseminor, unsigned int count, const char *name, const struct file_operations *fops){ struct char_device_struct *cd; struct cdev *cdev; int err = -ENOMEM; //1. 申請(qǐng)?jiān)O(shè)備號(hào) cd = __register_chrdev_region(major, baseminor, count, name); if (IS_ERR(cd)) return PTR_ERR(cd); //2. 為設(shè)備結(jié)構(gòu)體申請(qǐng)內(nèi)存 cdev = cdev_alloc(); if (!cdev) goto out2; // 3. 初始化cdev cdev->owner = fops->owner; cdev->ops = fops; kobject_set_name(&cdev->kobj, "%s", name); //4. 向系統(tǒng)注冊(cè)設(shè)備 err = cdev_add(cdev, MKDEV(cd->major, baseminor), count); if (err) goto out; cd->cdev = cdev; return major ? 0 : cd->major;out: kobject_put(&cdev->kobj);out2: kfree(__unregister_chrdev_region(cd->major, baseminor, count)); return err;}//unregister_chrdev調(diào)用__unregister_chrdevvoid __unregister_chrdev(unsigned int major, unsigned int baseminor, unsigned int count, const char *name){ struct char_device_struct *cd; //釋放設(shè)備號(hào) cd = __unregister_chrdev_region(major, baseminor, count); if (cd && cd->cdev) cdev_del(cd->cdev); //注銷(xiāo)設(shè)備 kfree(cd);}

通過(guò)上面的分析發(fā)現(xiàn)和上面的驅(qū)動(dòng)框架是一樣的,只是做了個(gè)封裝罷了。這時(shí)候是不是發(fā)現(xiàn)了兩者之間的關(guān)系,是不是很多驅(qū)動(dòng)都是用這兩個(gè)函數(shù)來(lái)注冊(cè)的。有些書(shū)就只講前面的,而有些教程又只講后面。所以搞得云里霧里的。

簡(jiǎn)化上面的驅(qū)動(dòng)模板

/*設(shè)備結(jié)構(gòu)體*/struct xxx_dev_t{ struct cdev cdev; ...};struct xxx_dev_t *dev;dev_t devno;//讀設(shè)備ssize_t xxx_read(struct file *filp, char __user *buf, size_t count, loff_t* f_pos){ ... copy_to_user(buf, ..., ...);}//寫(xiě)設(shè)備ssize_t xxx_write(struct file *filp, const char __user *buf, size_t count, loff_t* f_pos){ ... copy_from_user(..., buf, ...);}//操作函數(shù)file_operationsstruct file_operations xxx_fops = { .owner = THIS_MODULE, .read = xxx_read, .write = xxx_write, ...};//設(shè)備驅(qū)動(dòng)模塊加載函數(shù)static int __init xxx_init(void){ ... //注冊(cè)字符設(shè)備 xxx_major = register_chrdev(0, "xxx_dev", &xxx_fops);}module_init(xxx_init);//設(shè)備驅(qū)動(dòng)模塊卸載函數(shù)static void __exit xxx_exit(void){ //注銷(xiāo)字符設(shè)備 unregister_chrdev(major, "xxx_dev"); ...}module_exit(xxx_exit);MODULE_LICENSE("GPL v2");

喜歡這篇文章,歡迎點(diǎn)贊,分享,關(guān)注

更多精彩文章,歡迎關(guān)注微信公眾號(hào)"嵌入式軟件開(kāi)發(fā)交流"

以上就是關(guān)于怎么安裝pos機(jī)驅(qū)動(dòng),字符設(shè)備驅(qū)動(dòng)的知識(shí),后面我們會(huì)繼續(xù)為大家整理關(guān)于怎么安裝pos機(jī)驅(qū)動(dòng)的知識(shí),希望能夠幫助到大家!

轉(zhuǎn)發(fā)請(qǐng)帶上網(wǎng)址:http://www.afbey.com/news/36572.html

你可能會(huì)喜歡:

版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶(hù)自發(fā)貢獻(xiàn),該文觀點(diǎn)僅代表作者本人。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請(qǐng)發(fā)送郵件至 babsan@163.com 舉報(bào),一經(jīng)查實(shí),本站將立刻刪除。