免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
2.制作第一個驅(qū)動程序

先講解驅(qū)動框架,然后寫出first_drv驅(qū)動程序,來打印一些信息

寫出first_drv驅(qū)動程序需要以下幾步:

(1)寫出驅(qū)動程序first_drv_open first_drv_write

(2)需要定義file_operations結(jié)構(gòu)體來封裝驅(qū)動函數(shù)first_drv_open first_drv_write

對于字符設(shè)備來說,常用file_operations以下幾個成員:

(3) 模塊加載函數(shù),通過函數(shù) register_chrdev(major, “first_drv”, &first_drv_fops) 來

注冊字符設(shè)備

(4)寫驅(qū)動的first_drv_init 入口函數(shù)來調(diào)用這個register_chrdev()注冊函數(shù),

(5)通過module_init()來修飾入口函數(shù),使內(nèi)核知道有這個函數(shù)

(6)寫驅(qū)動的first_drv_exit出口函數(shù),調(diào)用這個unregister_chrdev()函數(shù)卸載,

(7) 通過module_exit()來修飾出口函數(shù)

(8) 模塊許可證聲明, 最常見的是以MODULE_LICENSE( 'GPL v2' )來聲明

1.首先創(chuàng)建first_drv.c文件

代碼如下:

#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <asm/irq.h>#include <asm/arch/regs-gpio.h>#include <asm/hardware.h>#include <asm/uaccess.h>#include <asm/io.h> /*1寫出驅(qū)動程序first_drv_open first_drv_write *//* inode結(jié)構(gòu)表示具體的文件,file結(jié)構(gòu)體用來追蹤文件在運(yùn)行時的狀態(tài)信息。*/static int first_drv_open(struct inode *inode, struct file *file){ printk(“first_drv_open\n”); //打印,在內(nèi)核中打印只能用printk() return 0;}/*參數(shù)filp為目標(biāo)文件結(jié)構(gòu)體指針,buffer為要寫入文件的信息緩沖區(qū),count為要寫入信息的長度,ppos為當(dāng)前的偏移位置,這個值通常是用來判斷寫文件是否越界*/static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos){ printk(“first_drv_write\n”); //打印,在內(nèi)核中打印只能用printk() return 0;} /*2定義file_operations結(jié)構(gòu)體來封裝驅(qū)動函數(shù)first_drv_open first_drv_write */ static struct file_operations first_drv_fops = { .owner = THIS_MODULE, //被使用時阻止模塊被卸載 .open = first_drv_open, .write = first_drv_write, }; /*4寫first_drv_init入口函數(shù)來調(diào)用這個register_chrdev()注冊函數(shù)*/int first_drv_init(void){ /*3 register_chrdev注冊字符設(shè)備,并設(shè)置major=111*/ /*如果設(shè)置major為0,表示由內(nèi)核動態(tài)分配主設(shè)備號,函數(shù)的返回值是主設(shè)備號*/register_chrdev (111, “first_drv”, &first_drv_fops); //111:主設(shè)備號,”first_drv”:設(shè)備名/*register_chrdev作用:在VFS虛擬文件系統(tǒng)中找到字符設(shè)備,然后通過主設(shè)備號找到內(nèi)核數(shù)組里對應(yīng)的位置,最后將設(shè)備名字和fops結(jié)構(gòu)體填進(jìn)去*/ return 0;}/*5 module_init修飾入口函數(shù)*/module_init(first_drv_init); /*6 寫first_drv_exit出口函數(shù)*/void first_drv_exit(void){unregister_chrdev (111, “first_drv”); //卸載驅(qū)動,只需要主設(shè)備號和設(shè)備名就行 }/*7 module_exit修飾出口函數(shù)*/module_exit(first_drv_exit);/*8許可證聲明, 描述內(nèi)核模塊的許可權(quán)限,如果不聲明LICENSE,模塊被加載時,將收到內(nèi)核被污染 (kernel tainted)的警告。*/MODULE_LICENSE( 'GPL v2' );

2然后寫Makefile編譯腳本:

KERN_DIR = /work/system/linux-2.6.22.6 //依賴的內(nèi)核目錄,前提內(nèi)核是編譯好的 all:  make -C $(KERN_DIR) M=`pwd` modules // M=`pwd`:指定當(dāng)前目錄//make -C $(KERN_DIR) 表示將進(jìn)入(KERN_DIR)目錄,執(zhí)行該目錄下的Makefile//等價于在linux-2.6.22.6目錄下執(zhí)行: make M=(當(dāng)前目錄) modules// modules:要編譯的目標(biāo)文件  clean: make -C $(KERN_DIR) M=`pwd` modules clean rm -rf modules.orderobj-m += frist_drv.o //obj-m:內(nèi)核模塊文件,指將myleds.o編譯成myleds.ko

3. make,編譯生成frist_drv.ko文件

4.然后開發(fā)板通過nfs網(wǎng)絡(luò)文件系統(tǒng)來加載frist_drv.ko

加載之前首先通過 cat /proc/devices來查看字符主設(shè)備號111是否被占用

然后通過 insmod first_drv.ko來掛載, 通過 cat /proc/devices就能看到first_drv已掛載好

5.通過測試程序測試frist_drv模塊

測試程序first_driver_text.c代碼如下

#include <sys/types.h> //調(diào)用sys目錄下types.h文件#include <sys/stat.h> //stat.h獲取文件屬性#include <fcntl.h>#include <stdio.h>/*輸入”./first_driver_text”, agc就等于1, argv[0]= first_driver_text *//*輸入”./first_driver_text on”, agc就等于2, argv[0]= first_driver_text,argv[1]=on; */int main(int argc,char **argv) {int fd1, fd2;int val=1;fd1 = open('/dev/xxx',O_RDWR); //打開/dev/xxx設(shè)備節(jié)點(diǎn)if(fd1<0) //無法打開,返回-1 printf('can't open%d!\n', fd1);else printf('can open%d!\n', fd1); //打開,返回文件描述符write(fd1, &val, 4);    //寫入數(shù)據(jù)1return 0;}

6.然后arm-linux-gcc -o first_driver_text first_driver_text.c生成執(zhí)行文件

回到板子串口上使用./first_driver_text來運(yùn)行,發(fā)現(xiàn)如果open()打不開,會返回-1

是因?yàn)槲覀儧]有創(chuàng)建dev/xxx這個設(shè)備節(jié)點(diǎn),然后我們來創(chuàng)建,使它等于剛剛掛載好的first_drv模塊

mknod -m 660 /dev/xxx c 111 0 // first_drv模塊的主設(shè)備號=111

./first_driver_text

結(jié)果如上圖,發(fā)現(xiàn)測試程序里的open()函數(shù)調(diào)用了驅(qū)動中的first_drv_open()

write()函數(shù)調(diào)用了驅(qū)動中的first_drv_write(),

其中open()函數(shù)返回值為3,是因?yàn)槊枋龇?,1,2都已經(jīng)被控制臺占用了,所以從3開始

7.改進(jìn)底層驅(qū)動,使用動態(tài)裝載:

除了靜態(tài)裝載驅(qū)動外,還可以動態(tài)裝載,讓系統(tǒng)自動為我們驅(qū)動設(shè)備自動分配設(shè)備號

7.1 修改first_drv_init入口函數(shù)和first_drv_exit 出口函數(shù):

代碼如下:

int major; //定義一個全局變量,用來保存主設(shè)備號int first_drv_init(void){ /*設(shè)置major為0,由內(nèi)核動態(tài)分配主設(shè)備號,函數(shù)的返回值是主設(shè)備號*/ major =register_chrdev (0, “first_drv”, &first_drv_fops);  return 0;}void first_drv_exit(void){unregister_chrdev (major, “first_drv”); //卸載驅(qū)動, 將major填入即可}

如下圖,通過動態(tài)分配得出它的主設(shè)備號是252,然后重創(chuàng)252的測試程序

rm dev/xxx

mknod -m 660 /dev/xxx c 252 0

./first_driver_text

7.2 每次都要手工創(chuàng)建設(shè)備節(jié)點(diǎn),大家肯定也會覺得這樣做太麻煩了。

可以使用自動創(chuàng)建設(shè)備節(jié)點(diǎn),Linux有udev、mdev的機(jī)制,而我們的ARM開發(fā)板上移植的busybox有mdev機(jī)制,然后mdev機(jī)制會通過class類來找到相應(yīng)類的驅(qū)動設(shè)備來自動創(chuàng)建設(shè)備節(jié)點(diǎn) (前提需要有mdev)

在哪里設(shè)置了mdev機(jī)制?

制作根文件系統(tǒng)之使用里有介紹

7.3 接下來使用insmod自動創(chuàng)建設(shè)備節(jié)點(diǎn), rmmod自動注銷設(shè)備節(jié)點(diǎn)

(1)首先創(chuàng)建一個class設(shè)備類,class是一個設(shè)備的高級視圖,它抽象出低級的實(shí)現(xiàn)細(xì)節(jié),然后在class類下,創(chuàng)建一個class_device,即類下面創(chuàng)建類的設(shè)備:(在C語言中class就是個結(jié)構(gòu)體)

static struct class *firstdrv_class; //創(chuàng)建一個class類static struct class_device *firstdrv_class_devs; //創(chuàng)建類的設(shè)備

(2)在first_drv_init入口函數(shù)中添加:

firstdrv_class= class_create(THIS_MODULE,'firstdrv'); //創(chuàng)建類,它會在sys/class目錄下創(chuàng)建firstdrv_class這個類 firstdrv_class_devs=class_device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,'xyz');//創(chuàng)建類設(shè)備,會在sys/class/firstdrv_class類下創(chuàng)建xyz設(shè)備,然后mdev通過這個自動創(chuàng)建/dev/xyz這個設(shè)備節(jié)點(diǎn), 

(3)在first_drv_exit出口函數(shù)中添加:

class_device_unregister(firstdrv_class_devs); //注銷類設(shè)備,與class_device_create對應(yīng) class_destroy(firstdrv_class); //注銷類,與class_create對應(yīng)

重新編譯insmod后,會發(fā)現(xiàn)在/dev下自動的創(chuàng)建了xyz設(shè)備節(jié)點(diǎn)

其中在sys/class里有各種類的設(shè)備, 比如sys/class/fristdev下就有xyz

然后mdv通過insmod xxx 就去class找到相應(yīng)類的驅(qū)動設(shè)備來自動創(chuàng)建設(shè)備節(jié)點(diǎn)

為什么內(nèi)容一更改,mdv就能自動運(yùn)行創(chuàng)建設(shè)備節(jié)點(diǎn)呢?

是因?yàn)橐郧?strong>創(chuàng)建根文件系統(tǒng)時候,

在etc/init.d/rcS里添加了這么一段:

1

echo /sbin/mdev > /proc/sys/kernel/hotplug //支持熱拔插

然后kernel每當(dāng)設(shè)備出現(xiàn)變動時,調(diào)用/sbin/mdev來處理對應(yīng)的信息,使mdev應(yīng)用程序操作/dev目錄下的設(shè)備,進(jìn)行添加或刪除

(4).再修改測試程序里open函數(shù),將/dev/xxx改為/dev/xyz,這樣就測試模塊,就不需要再mknod了.

驅(qū)動程序first_drv_open first_drv_write中只是打印數(shù)據(jù),接下來下一節(jié)便開始來點(diǎn)亮LED.

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
教你寫第一個Linux設(shè)備驅(qū)動程序
Linux中級“驅(qū)動”控制硬件必須學(xué)會的底層知識
關(guān)于cdev platform以及class的一點(diǎn)見解-steven
網(wǎng)卡驅(qū)動注冊到PCI總線這一過程的分析
Linux驅(qū)動的platform機(jī)制
Linux設(shè)備驅(qū)動簡析--dm9000網(wǎng)卡驅(qū)動 - Network - Neil Chiao's Blog
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服