網(wǎng)上有很多關(guān)于pos機(jī)一直初始化怎么辦,Linux字符設(shè)備驅(qū)動(dòng)模型之字符設(shè)備初始化的知識(shí),也有很多人為大家解答關(guān)于pos機(jī)一直初始化怎么辦的問(wèn)題,今天pos機(jī)之家(www.afbey.com)為大家整理了關(guān)于這方面的知識(shí),讓我們一起來(lái)看下吧!
本文目錄一覽:
pos機(jī)一直初始化怎么辦
因?yàn)長(zhǎng)inux字符設(shè)備驅(qū)動(dòng)主要依賴(lài)于struct cdev結(jié)構(gòu),原型為:
所以我們需要對(duì)所使用到的結(jié)構(gòu)成員進(jìn)行配置,驅(qū)動(dòng)開(kāi)發(fā)所使用到的結(jié)構(gòu)成員分別為:【unsigned int count;】、【dev_t dev;】、【const struct file_operations *ops;】。
開(kāi)發(fā)流程如下圖:一、字符設(shè)備驅(qū)動(dòng)初始化1、分配設(shè)備cdev
Cdev變量的定義可以采用靜態(tài)和動(dòng)態(tài)兩種方法進(jìn)行分配。靜態(tài)方法直接分配內(nèi)存,而動(dòng)態(tài)方法隨機(jī)分配內(nèi)存。
靜態(tài)分配cdev:
定義:struct cdev mdev;
mdev即代表相應(yīng)的字符設(shè)備空間地址。
動(dòng)態(tài)分配cdev:
定義:struct cdev *pdev = cdev_alloc();
pdev即代表對(duì)于的字符設(shè)備的空間地址。
2、初始化設(shè)備cdev
Linux內(nèi)核中,字符設(shè)備struct cdev的初始化使用cdev_init。其原型如下:
參數(shù):
cdev:待初始化的struct cdev結(jié)構(gòu)
fops:設(shè)備對(duì)應(yīng)的操作函數(shù)集
由原型所要求的參數(shù)可知,需要初始化一個(gè)字符設(shè)備,必須根據(jù)申請(qǐng)一個(gè)struct cdev結(jié)構(gòu)的空間,然后對(duì)其成員進(jìn)行配置。即實(shí)現(xiàn)設(shè)備的操作函數(shù)集、為設(shè)備申請(qǐng)?jiān)O(shè)備號(hào)(包括主設(shè)備號(hào)和次設(shè)備號(hào))、指定此類(lèi)型的字符設(shè)備有多少個(gè)相同設(shè)備。
3、注冊(cè)設(shè)備cdev
Linux內(nèi)核中字符設(shè)備的注冊(cè)使用cdev_add函數(shù)來(lái)進(jìn)行完成注冊(cè)。其原型如下:
其相關(guān)參數(shù)定義為:
p:待添加到內(nèi)核中的字符設(shè)備結(jié)構(gòu),即為struct cdev。
dev:設(shè)備號(hào)
count:該類(lèi)設(shè)備的設(shè)備數(shù)量,各個(gè)設(shè)備的區(qū)別體現(xiàn)為從設(shè)備號(hào)。
在開(kāi)發(fā)驅(qū)動(dòng)時(shí),當(dāng)確定了字符設(shè)備的結(jié)構(gòu),主設(shè)備號(hào)和從設(shè)備號(hào)、設(shè)備的數(shù)量,就可以使用cdev_add函數(shù)將相應(yīng)的字符設(shè)備添加到Linux內(nèi)核驅(qū)動(dòng)中進(jìn)行注冊(cè)。
4、硬件初始化
關(guān)于硬件的初始化就簡(jiǎn)單了。直接根據(jù)所需要操作的字符設(shè)備,閱讀器Datasheet,然后根據(jù)Datasheet進(jìn)行硬件的配置即可。
二、設(shè)備操作和驅(qū)動(dòng)操作映射從上圖基本可知,在用戶(hù)空間的每一種硬件設(shè)備操作函數(shù),在內(nèi)核空間通用有一個(gè)映射操作函數(shù)實(shí)現(xiàn)。
int (*open) (struct inode *, struct file *):打開(kāi)設(shè)備,響應(yīng)open系統(tǒng)
int (*release) (struct inode *, struct file *):關(guān)閉設(shè)備,響應(yīng)close系統(tǒng)調(diào)用
loff_t (*llseek) (struct file *, loff_t, int):重定位讀寫(xiě)指針,響應(yīng)lseek系統(tǒng)調(diào)用
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *):從設(shè)備讀取數(shù)據(jù),響應(yīng)read系統(tǒng)調(diào)用
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *):向設(shè)備寫(xiě)入數(shù)據(jù),響應(yīng)write系統(tǒng)調(diào)用
從以上函數(shù)指針操作方法中可以提取出兩個(gè)重要的參數(shù)成員,即為struct file和struct inode。
【struct file】:在Linux系統(tǒng)中,每一個(gè)打開(kāi)的文件,在內(nèi)核中都會(huì)對(duì)應(yīng)的關(guān)聯(lián)一個(gè)struct file結(jié)構(gòu)體,它由內(nèi)核在打開(kāi)文件時(shí)創(chuàng)建,在文件關(guān)閉后釋放。
其非常重要的成員有:
loff_t f_pos /*文件讀寫(xiě)指針*/
struct file_operations *f_op /*該文件所對(duì)應(yīng)的操作*/
【struct inode】:每一個(gè)存在于文件系統(tǒng)里面的文件都會(huì)關(guān)聯(lián)一個(gè)inode 結(jié)構(gòu),該結(jié)構(gòu)主要用來(lái)記錄文件物理上的信息。因此, 它和代表打開(kāi)文件的file結(jié)構(gòu)是不同的。一個(gè)文件沒(méi)有被打開(kāi)時(shí)不會(huì)關(guān)聯(lián)file結(jié)構(gòu),但是卻會(huì)關(guān)聯(lián)一個(gè)inode 結(jié)構(gòu)。
在struct inode結(jié)構(gòu)中,dev_t i_rdev尤其重要,表示設(shè)備號(hào)。
三、struct file_operations結(jié)構(gòu)常用設(shè)備操作解析1.open設(shè)備操作
根據(jù)原型可知,open設(shè)備函數(shù)方法是在進(jìn)行開(kāi)始啟用操作設(shè)備時(shí)的初始化工作,與用戶(hù)空間的open函數(shù)對(duì)應(yīng),通常情況下,open函數(shù)實(shí)現(xiàn):
(1)表明次設(shè)備號(hào)
(2)啟用設(shè)備
當(dāng)然,如果在啟用設(shè)備時(shí),不需要任何的準(zhǔn)備操作或者初始化操作,那么open函數(shù)可以為空函數(shù),不實(shí)現(xiàn)。
2.release設(shè)備操作
release函數(shù)方法的作用正好和open函數(shù)方法的作用相反,它在設(shè)備關(guān)閉時(shí)用到,與用戶(hù)空間的close對(duì)應(yīng)。通常用來(lái)進(jìn)行關(guān)閉設(shè)備的實(shí)現(xiàn)。如果所操作的設(shè)備在關(guān)閉時(shí)不需要其他操作,那么使其為空函數(shù)即可。
3.read設(shè)備操作
read方法主要完成兩件事:
(1)訪(fǎng)問(wèn)硬件操作,從設(shè)備中讀取數(shù)據(jù)。
(2)將從設(shè)備端讀取到的數(shù)據(jù)返回給用戶(hù)空間的應(yīng)用程序read函數(shù)。
其read方法的具體原型可分析如下:
ssize_t (*read) (struct file *filp, char __user *buff, size_t count, loff_t *offp)
參數(shù)分析:
filp:與字符設(shè)備文件關(guān)聯(lián)的file結(jié)構(gòu)指針, 由內(nèi)核創(chuàng)建。
buff : 從設(shè)備讀取到的數(shù)據(jù),需要保存到的位置。由read系統(tǒng)調(diào)用提供該參數(shù)。
count: 請(qǐng)求傳輸?shù)臄?shù)據(jù)量,由read系統(tǒng)調(diào)用提供該參數(shù)。
offp: 文件的讀寫(xiě)位置,由內(nèi)核從file結(jié)構(gòu)中取出后,傳遞進(jìn)來(lái)。
那么實(shí)際上在這里就存在了一個(gè)問(wèn)題,從內(nèi)核空間如何將數(shù)據(jù)返回給用戶(hù)空間???
在Linux內(nèi)核中,為從內(nèi)核空間將數(shù)據(jù)返回到用戶(hù)空間提供了函數(shù)方法,即為:copy_to_user。其原型如下:
之所以采用copy_to_user函數(shù)的原因是,buff參數(shù)來(lái)源于用戶(hù)空間的指針,這類(lèi)指針在內(nèi)核空間中不能直接被內(nèi)核代碼直接引用,所以必須采用拷貝的方式進(jìn)行數(shù)據(jù)的傳遞。具體的操作過(guò)程如下圖表示:
4.write設(shè)備操作
write函數(shù)方法也主要完成兩件事:
(1)從應(yīng)用程序提供的地址中取出數(shù)據(jù)到內(nèi)核空間。
(2)訪(fǎng)問(wèn)硬件設(shè)備,將數(shù)據(jù)寫(xiě)入到設(shè)備中。
write函數(shù)方法直接對(duì)應(yīng)于用戶(hù)空間的write函數(shù)。
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *)
write函數(shù)方法的參數(shù)基本上和read函數(shù)方法類(lèi)似,在此不再做解釋。
那么實(shí)際上在此也存在一個(gè)問(wèn)題,如何將數(shù)據(jù)從用戶(hù)空間取出到內(nèi)核空間使用???
實(shí)際上Linux內(nèi)核中也提供了相應(yīng)的方法函數(shù),將用戶(hù)空間的數(shù)據(jù)拷貝到內(nèi)核空間進(jìn)行使用,其方法為:copy_from_user。原型如下:
四、設(shè)備驅(qū)動(dòng)注銷(xiāo)當(dāng)內(nèi)核中不再需要使用一個(gè)字符設(shè)備時(shí),我們可以在內(nèi)核中將相應(yīng)的設(shè)備驅(qū)動(dòng)程序進(jìn)行卸載。那么就需要對(duì)其字符設(shè)備進(jìn)行注銷(xiāo)。Linux內(nèi)核中為我們提供了cdev_del函數(shù)來(lái)完成字符設(shè)備的注銷(xiāo)。其原型如下:
本文為連載內(nèi)容,如覺(jué)得不錯(cuò),請(qǐng)點(diǎn)個(gè)贊吧!
以上就是關(guān)于pos機(jī)一直初始化怎么辦,Linux字符設(shè)備驅(qū)動(dòng)模型之字符設(shè)備初始化的知識(shí),后面我們會(huì)繼續(xù)為大家整理關(guān)于pos機(jī)一直初始化怎么辦的知識(shí),希望能夠幫助到大家!
