Linux 2.6.32内核字符设备驱动模板

原文转自(http://www.embedhq.org/html/jsbw/2011/0214/1066.html)

//=======================字符设备驱动模板开始===========================//

#defineCHAR_DEV_DEVICE_NAME"char_dev"//设备名

structclass*char_dev_class;//class结构用于自动创建设备结点

staticintmajor=0;/*0表示动态分配主设备号,可以设置成未被系统分配的具体的数字。*/

staticstructcdevchar_dev_devs;//定义一个cdev结构

//设备建立子函数,被char_dev_init函数调用

staticvoidchar_dev_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%daddingchar_dev%d\n",err,minor);

}

}

//file_operations结构体设置,该设备的所有对外接口在这里明确,此处只写出了几常用的

staticstructfile_operationschar_dev_fops=

{

.owner=THIS_MODULE,

.open=char_dev_open,//打开设备

.release=char_dev_release,//关闭设备

.read=char_dev_read,//实现设备读功能

.write=char_dev_write,//实现设备写功能

.ioctl=char_dev_ioctl,//实现设备控制功能

};

//进行初始化设置,打开设备,对应应用空间的open系统调用

intchar_dev_open(structinode*inode,structfile*filp)

{

...//这里可以进行一些初始化

return0;

}

//释放设备,关闭设备,对应应用空间的close系统调用

staticintchar_dev_release(structinode*node,structfile*file)

{

...//这里可以进行一些资源的释放

return0;

}

//实现读功能,读设备,对应应用空间的read系统调用

ssize_tchar_dev_read(structfile*file,char__user*buff,size_tcount,loff_t*offp)

{

...

return0;

}

//实现写功能,写设备,对应应用空间的write系统调用

ssize_tchar_dev_write(structfile*file,constchar__user*buff,size_tcount,loff_t*offp)

{

...

return0;

}

//实现主要控制功能,控制设备,对应应用空间的ioctl系统调用

staticintchar_dev_ioctl(structinode*inode,structfile*file,unsignedintcmd,unsignedlongarg)

{

...

return0;

}

//设备初始化

staticintchar_dev_init(void)

{

intresult;

dev_tdev=MKDEV(major,0);

if(major)

{

//给定设备号注册

result=register_chrdev_region(dev,1,CHAR_DEV_DEVICE_NAME);

}

else

{

//动态分配设备号

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

major=MAJOR(dev);

}

char_dev_setup_cdev(&char_dev_devs,0,&char_dev_fops);

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

//====有中断的可以在此注册中断:request_irq,并要实现中断服务程序===//

//创建设备结点

char_dev_class=class_create(THIS_MODULE,"ad_class");

if(IS_ERR(char_dev_class))

{

printk("Err:failedincreatingclass.\n");

return0;

}

device_create(char_dev_class,NULL,dev,NULL,"char_dev");

return0;

}

//设备注销

staticvoidchar_dev_cleanup(void)

{

device_destroy(adc_class,dev);

class_destroy(adc_class);

cdev_del(&char_dev_devs);//字符设备的注销*/

unregister_chrdev_region(MKDEV(major,0),1);//设备号的注销

//========有中断的可以在此注销中断:free_irq======//

printk("char_devdeviceuninstalled\n");

}

module_init(char_dev_init);//模块初始化接口

module_exit(char_dev_cleanup);//模块注销接口

//以下两句不能省略,否则编译不通过

MODULE_AUTHOR("www.embedhq.org");

MODULE_LICENSE("GPL");

//====================字符设备驱动模板结束========================//

用Makefile模板编译,Makefile如下:

//=======================Makefile开始===========================//

ifeq($(KERNELRELEASE),)

#KERNELDIR?=/your/target/source/directory/

KERNELDIR?=/opt/kernal/linux-2.6.32.10/

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

//=========================Makefile结束=============================//

make编译后生成char_dev.ko,控制台输入加载和卸载命令,还可以使用lsmod查看已经加载的模块信息。

insmodchar_dev.ko#加载驱动,会执行module_init中的语句

rmmodchar_dev#卸载驱动,会执行module_exit中的语句

相关推荐