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

11.7實驗內(nèi)容——test驅(qū)動1.實驗目的

該實驗是編寫最簡單的字符驅(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ù)復制到內(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/*當加載模塊時打印*/

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

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

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

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

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉