浅谈linux驱动2字符设备驱动程序Word下载.docx

上传人:b****7 文档编号:22022011 上传时间:2023-02-02 格式:DOCX 页数:9 大小:310.76KB
下载 相关 举报
浅谈linux驱动2字符设备驱动程序Word下载.docx_第1页
第1页 / 共9页
浅谈linux驱动2字符设备驱动程序Word下载.docx_第2页
第2页 / 共9页
浅谈linux驱动2字符设备驱动程序Word下载.docx_第3页
第3页 / 共9页
浅谈linux驱动2字符设备驱动程序Word下载.docx_第4页
第4页 / 共9页
浅谈linux驱动2字符设备驱动程序Word下载.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

浅谈linux驱动2字符设备驱动程序Word下载.docx

《浅谈linux驱动2字符设备驱动程序Word下载.docx》由会员分享,可在线阅读,更多相关《浅谈linux驱动2字符设备驱动程序Word下载.docx(9页珍藏版)》请在冰豆网上搜索。

浅谈linux驱动2字符设备驱动程序Word下载.docx

接下来我们看看在内核当中是如何表述设备号的,其实在linux内核当中,这个主次设备号是有规律的,主次设备号加在一起,实质就是unsignedint32位整数,它用dev_t来描述。

其中高12位是主设备号,低20位是次设备号。

一般情况下,我们不会说出现上千个设备的,所有主设备号是够用的,2的12次方是多少?

4096,也就是说最多支持4096种类型的设备。

我们是怎样从dev_t分离出主设备号和次设备号的呢?

用MAJOR(dev_tdev)这个宏分离出主设备号,用MINOR(dev_tdev)这个宏分离出次设备号。

linux内核如何给设备分配设备号呢?

分两种:

静态申请,动态分配。

如何静态申请呢?

首先我们要知道设备号存放在哪里?

我们来看下图

然后打开这个文挡

上面描述可能还有点问题,总之你选用的设备号,是前面没有出现过的才行。

然后使用register_chrdev_region这个函数去注册去申请设备号。

intregister_chrdev_region(dev_from,unsignedcount,constchar*name)

from代表你希望使用的设备号是多少?

比如我选个500,总之前面没出现过就行。

count表示希望申请使用设备号的数目,比如我们申请了5个,那么系统就会给你留5个号出来,打个比方,5000,5001,5002,5003,5004.

name是设备名,比如serial。

接下来我们谈谈动态分配,我们常常会担心自己选的设备号前面已经用过了,担心设备号选错引起不必要的麻烦,那么我们现在就采取动态分配设备号的方式,让内核来分配设备号,内核一定比我们清楚哪些设备号是空闲的.我们用alloc_chrdev_region这个函数来分配设备号。

这里有个需要注意的,这里动态分配设备号,一定是要在驱动安装之后才能执行的。

动态分配intalloc_chrdev_region(dev_t*dev,unsignedbaseminor,unsignedcount,constchar*name),意思就是请求内核分配count个设备号,且次设备号从baseminor开始。

(dev是主设备号,baseminor是起始次设备号,count是分配的设备号数目,name是设备名)。

设备号是相当宝贵的,不用的时候请注销掉,voidunregister_chrdev_region(dev_tfrom,unsignedcount)

有了设备号之后我们要创建设备文件了,创建设备文件的办法有两种:

1.mknod,命令手工创建

2.自动创建

mknod用法,mknodfilenametypemajorminor,这里filename表示设备名,type表示设备类型(比如clock,char啊),major是主设备号,minor是次设备号。

打个比方

在linux字符驱动程序设计中,有三种非常重要的数据结构:

structfile(表示打开的文件,系统每个打开的文件内核都有一个关联的structfile,内核打开文件的时候创建,在文件关闭之后是自动释放)

structinode(记录文件物理信息,比如文件的位置,比如一个设备文件的设备号是多少,一个文件可以有多个file结构,但只有一个inode)

structfile_operations(一个函数指针的集合,定义能在设备上进行的操作,结构中的成员指向驱动中的函数,这些函数实现一个特别的操作,对于不支持的操作,保存为null)打个比方,我们应用程序需要通过驱动程序来对硬件进行操作,比如我们应用程序发出一个read的调用,那么我们驱动程序凭什么对你发出的read做出反应?

那么请看下面的一张图

还是拿read来做例子,应用程序发出read,全凭这张图里函数的转换,驱动程序做出反应,调用memoryread。

我这里拿了个led的例子供大家参考对照理解

#include<

linux/kernel.h>

linux/module.h>

linux/init.h>

linux/proc_fs.h>

linux/seq_file.h>

linux/string.h>

linux/jiffies.h>

linux/timer.h>

linux/uaccess.h>

asm/auxio.h>

#defineLED_MAX_LENGTH8/*maximumcharswrittentoprocfile*/

staticinlinevoidled_toggle(void)

{

unsignedcharval=get_auxio();

unsignedcharon,off;

if(val&

AUXIO_LED){

on=0;

off=AUXIO_LED;

}else{

on=AUXIO_LED;

off=0;

}

set_auxio(on,off);

}

staticstructtimer_listled_blink_timer;

staticvoidled_blink(unsignedlongtimeout)

led_toggle();

/*reschedule*/

if(!

timeout){/*blinkaccordingtoload*/

led_blink_timer.expires=jiffies+

((1+(avenrun[0]>

>

FSHIFT))*HZ);

led_blink_timer.data=0;

}else{/*blinkatuserspecifiedinterval*/

led_blink_timer.expires=jiffies+(timeout*HZ);

led_blink_timer.data=timeout;

add_timer(&

led_blink_timer);

staticintled_proc_show(structseq_file*m,void*v)

if(get_auxio()&

AUXIO_LED)

seq_puts(m,"

on\n"

);

else

off\n"

return0;

staticintled_proc_open(structinode*inode,structfile*file)

returnsingle_open(file,led_proc_show,NULL);

staticssize_tled_proc_write(structfile*file,constchar__user*buffer,

size_tcount,loff_t*ppos)

char*buf=NULL;

if(count>

LED_MAX_LENGTH)

count=LED_MAX_LENGTH;

buf=kmalloc(sizeof(char)*(count+1),GFP_KERNEL);

buf)

return-ENOMEM;

if(copy_from_user(buf,buffer,count)){

kfree(buf);

return-EFAULT;

buf[count]='

\0'

;

/*workaround\nwhenecho'

ingintoproc*/

if(buf[count-1]=='

\n'

buf[count-1]='

/*beforewechangeanythingwewanttostopanyrunningtimers,

*otherwisecallssuchasonwillhavenopersistenteffect

*/

del_timer_sync(&

strcmp(buf,"

on"

)){

auxio_set_led(AUXIO_LED_ON);

}elseif(!

toggle"

led_toggle();

}elseif((*buf>

'

0'

)&

&

(*buf<

='

9'

led_blink(simple_strtoul(buf,NULL,10));

load"

led_blink(0);

auxio_set_led(AUXIO_LED_OFF);

kfree(buf);

returncount;

staticconststructfile_operationsled_proc_fops={

.owner=THIS_MODULE,

.open=led_proc_open,

.read=seq_read,

.llseek=seq_lseek,

.release=single_release,

.write=led_proc_write,

};

staticstructproc_dir_entry*led;

#defineLED_VERSION"

0.1"

staticint__initled_init(void)

init_timer(&

led_blink_timer.function=led_blink;

led=proc_create("

led"

0,NULL,&

led_proc_fops);

led)

led->

owner=THIS_MODULE;

printk(KERN_INFO

"

led:

version%s,LarsKotthoff<

metalhead@metalhead.ws>

\n"

LED_VERSION);

staticvoid__exitled_exit(void)

remove_proc_entry("

NULL);

module_init(led_init);

module_exit(led_exit);

MODULE_AUTHOR("

LarsKotthoff<

"

MODULE_DESCRIPTION("

ProvidescontrolofthefrontLEDonSPARCsystems."

MODULE_LICENSE("

GPL"

MODULE_VERSION(LED_VERSION);

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 成人教育 > 电大

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1