日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 嵌入式 > 嵌入式教程
[導(dǎo)讀]該實驗是編寫最簡單的字符驅(qū)動程序,這里的設(shè)備也就是一段內(nèi)存,實現(xiàn)簡單的讀寫功能,并列出常用格式的Makefile以及驅(qū)動的加載和卸載腳本。讀者可以熟悉字符設(shè)備驅(qū)動的整個編寫流程。

11.7實驗內(nèi)容——test驅(qū)動1.實驗?zāi)康?p>該實驗是編寫最簡單的字符驅(qū)動程序,這里的設(shè)備也就是一段內(nèi)存,實現(xiàn)簡單的讀寫功能,并列出常用格式的Makefile以及驅(qū)動的加載和卸載腳本。讀者可以熟悉字符設(shè)備驅(qū)動的整個編寫流程。

2.實驗內(nèi)容

該實驗要求實現(xiàn)對虛擬設(shè)備(一段內(nèi)存)的打開、關(guān)閉、讀寫的操作,并要通過編寫測試程序來測試虛擬設(shè)備及其驅(qū)動運行是否正常。

3.實驗步驟

(1)編寫代碼。

這個簡單的驅(qū)動程序的源代碼如下所示:

/*test_drv.c*/

#include<linux/module.h>

#include<linux/init.h>

#include<linux/fs.h>

#include<linux/kernel.h>

#include<linux/slab.h>

#include<linux/types.h>

#include<linux/errno.h>

#include<linux/cdev.h>

#include<asm/uaccess.h>

#defineTEST_DEVICE_NAME"test_dev"

#defineBUFF_SZ1024

/*全局變量*/

staticstructcdevtest_dev;

unsignedintmajor=0;

staticchar*data=NULL;

/*讀函數(shù)*/

staticssize_ttest_read(structfile*file,

char*buf,size_tcount,loff_t*f_pos)

{

intlen;

if(count<0)

{

return-EINVAL;

}

len=strlen(data);

count=(len>count)?count:len;

if(copy_to_user(buf,data,count))/*將內(nèi)核緩沖的數(shù)據(jù)拷貝到用戶空間*/

{

return-EFAULT;

}

returncount;

}

/*寫函數(shù)*/

staticssize_ttest_write(structfile*file,constchar*buffer,

size_tcount,loff_t*f_pos)

{

if(count<0)

{

return-EINVAL;

}

memset(data,0,BUFF_SZ);

count=(BUFF_SZ>count)?count:BUFF_SZ;

if(copy_from_user(data,buffer,count))/*將用戶緩沖的數(shù)據(jù)復(fù)制到內(nèi)核空間*/

{

return-EFAULT;

}

returncount;

}

/*打開函數(shù)*/

staticinttest_open(structinode*inode,structfile*file)

{

printk("Thisisopenoperation\n");

/*分配并初始化緩沖區(qū)*/

data=(char*)kmalloc(sizeof(char)*BUFF_SZ,GFP_KERNEL);

if(!data)

{

return-ENOMEM;

}

memset(data,0,BUFF_SZ);

return0;

}

/*關(guān)閉函數(shù)*/

staticinttest_release(structinode*inode,structfile*file)

{

printk("Thisisreleaseoperation\n");

if(data)

{

kfree(data);/*釋放緩沖區(qū)*/

data=NULL;/*防止出現(xiàn)野指針*/

}

return0;

}

/*創(chuàng)建、初始化字符設(shè)備,并且注冊到系統(tǒng)*/

staticvoidtest_setup_cdev(structcdev*dev,intminor,

structfile_operations*fops)

{

interr,devno=MKDEV(major,minor);

cdev_init(dev,fops);

dev->owner=THIS_MODULE;

dev->ops=fops;

err=cdev_add(dev,devno,1);

if(err)

{

printk(KERN_NOTICE"Error%daddingtest%d",err,minor);

}

}

/*虛擬設(shè)備的file_operations結(jié)構(gòu)*/

staticstructfile_operationstest_fops=

{

.owner=THIS_MODULE,

.read=test_read,

.write=test_write,

.open=test_open,

.release=test_release,

};

/*模塊注冊入口*/

intinit_module(void)

{

intresult;

dev_tdev=MKDEV(major,0);

if(major)

{/*靜態(tài)注冊一個設(shè)備,設(shè)備號先前指定好,并設(shè)定設(shè)備名,用cat/proc/devices來查看*/

result=register_chrdev_region(dev,1,TEST_DEVICE_NAME);

}

else

{

result=alloc_chrdev_region(&dev,0,1,TEST_DEVICE_NAME);

}

if(result<0)

{

printk(KERN_WARNING"Testdevice:unabletogetmajor%d\n",major);

returnresult;

}

test_setup_cdev(&test_dev,0,&test_fops);

printk("Themajorofthetestdeviceis%d\n",major);

return0;

}

/*卸載模塊*/

voidcleanup_module(void)

{

cdev_del(&test_dev);

unregister_chrdev_region(MKDEV(major,0),1);

printk("Testdeviceuninstalled\n");

}

(2)編譯代碼。

虛擬設(shè)備的驅(qū)動程序的Makefile如下所示:

ifeq($(KERNELRELEASE),)

KERNELDIR?=/lib/modules/$(shelluname-r)/build/*內(nèi)核代碼編譯路徑*/

PWD:=$(shellpwd)

modules:

$(MAKE)-C$(KERNELDIR)M=$(PWD)modules

modules_install:

$(MAKE)-C$(KERNELDIR)M=$(PWD)modules_install

clean:

rm-rf*.o*~core.depend.*.cmd*.ko*.mod.c.tmp_versions

.PHONY:modulesmodules_installclean

else

obj-m:=test_drv.o/*將生成的模塊為test_drv.ko*/

endif

(3)加載和卸載模塊。

通過下面兩個腳本代碼分別實現(xiàn)驅(qū)動模塊的加載和卸載。

加載腳本test_drv_load如下所示:

#!/bin/sh

#驅(qū)動模塊名稱

module="test_drv"

#設(shè)備名稱。在/proc/devices中出現(xiàn)

device="test_dev"

#設(shè)備文件的屬性

mode="664"

group="david"

#刪除已存在的設(shè)備節(jié)點

rm-f/dev/${device}

#加載驅(qū)動模塊

/sbin/insmod-f./$module.ko$*||exit1

#查到創(chuàng)建設(shè)備的主設(shè)備號

major=`cat/proc/devices|awk"\\$2==\"$device\"{print\\$1}"`

#創(chuàng)建設(shè)備文件節(jié)點

mknod/dev/${device}c$major0

#設(shè)置設(shè)備文件屬性

chgrp$group/dev/${device}

chmod$mode/dev/${device}

卸載腳本test_drv_unload如下所示:

#!/bin/sh

module="test_drv"

device="test_dev"

#卸載驅(qū)動模塊

/sbin/rmmod$module$*||exit1

#刪除設(shè)備文件

rm-f/dev/${device}

exit0

(6)編寫測試代碼。

最后一步是編寫測試代碼,也就是用戶空間的程序,該程序調(diào)用設(shè)備驅(qū)動來測試驅(qū)動的運行是否正常。以下實例只實現(xiàn)了簡單的讀寫功能,測試代碼如下所示:

/*test.c*/

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<sys/stat.h>

#include<sys/types.h>

#include<unistd.h>

#include<fcntl.h>

#defineTEST_DEVICE_FILENAME"/dev/test_dev"/*設(shè)備文件名*/

#defineBUFF_SZ1024/*緩沖大小*/

intmain()

{

intfd,nwrite,nread;

charbuff[BUFF_SZ];/*緩沖區(qū)*/

/*打開設(shè)備文件*/

fd=open(TEST_DEVICE_FILENAME,O_RDWR);

if(fd<0)

{

perror("open");

exit(1);

}

do

{

printf("Inputsomewordstokernel(enter'quit'toexit):");

memset(buff,0,BUFF_SZ);

if(fgets(buff,BUFF_SZ,stdin)==NULL)

{

perror("fgets");

break;

}

buff[strlen(buff)-1]='\0';

if(write(fd,buff,strlen(buff))<0)/*向設(shè)備寫入數(shù)據(jù)*/

{

perror("write");

break;

}

if(read(fd,buff,BUFF_SZ)<0)/*從設(shè)備讀取數(shù)據(jù)*/

{

perror("read");

break;

}

else

{

printf("Thereadstringisfromkernel:%s\n",buff);

}

}while(strncmp(buff,"quit",4));

close(fd);

exit(0);

}

4.實驗結(jié)果

首先在虛擬設(shè)備驅(qū)動源碼目錄下編譯并加載驅(qū)動模塊。

$makeclean;make

$./test_drv_load

接下來,編譯并運行測試程序

$gcc–otesttest.c

$./test

測試程序運行效果如下:

Inputsomewordstokernel(enter'quit'toexit):Hello,everybody!

Thereadstringisfromkernel:Hello,everybody!/*從內(nèi)核讀取的數(shù)據(jù)*/

Inputsomewordstokernel(enter'quit'toexit):Thisisasimpledriver

Thereadstringisfromkernel:Thisisasimpledriver

Inputsomewordstokernel(enter'quit'toexit):quit

Thereadstringisfromkernel:quit

最后,卸載驅(qū)動程序

$./test_drv_unload

通過dmesg命令可以查看內(nèi)核打印的信息:

$dmesg|tail–n10

……

Themajorofthetestdeviceis250/*當(dāng)加載模塊時打印*/

Thisisopenoperation/*當(dāng)打開設(shè)備時打印*/

Thisisreleaseoperation/*關(guān)閉設(shè)備時打印*/

Testdeviceuninstalled/*當(dāng)卸載設(shè)備時打印*/

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當(dāng)下,工業(yè)電機作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅(qū)動電源設(shè)計中至關(guān)重要的兩個環(huán)節(jié),集成化方案的設(shè)計成為提升電機驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設(shè)備的使用壽命。然而,在實際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設(shè)計、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉