qifei 2011-12-10
/*Linux字符设备驱动源代码scdd.c*/
#include <linux/init.h> /*模块头文件*/
#include <linux/module.h>
#include <linux/types.h> /*dev_t头文件*/
#include <linux/kdev_t.h> /*MAJOR和MINOR宏头文件*/
#include <linux/fs.h> /*register_chrdev_region等函数
file_operations结构体*/
#include <linux/cdev.h> /*struct cdev结构体*/
#include <asm/uaccess.h> /*copy_to_user函数*/
#define DEVICE_NAME "scdd" /*定义设备名*/
#define DEVICE_MAJOR 250
struct cdev my_cdev;
int scdd_open(struct inode *inode,structfile *filp)
{
return0;
}
int scdd_close(struct inode *inode,structfile *filp)
{
return0;
}
ssize_t scdd_read(struct file *filp,char__user *buff,size_t size,loff_t *offp)
{
intleft;
chardata=1;
for(left=size;left>0;left--)
{
/*拷贝数据到用户空间*/
copy_to_user(buff,&data,1);
buff++;
}
returnsize;
}
ssize_t scdd_write(struct file *filp,char__user *buff,size_t size,loff_t *offp)
{
return0;
}
/*file_operations结构体*/
struct file_operations scdd_fops={
.owner=THIS_MODULE,
.read=scdd_read,
.write=scdd_write,
.open=scdd_open,
.release=scdd_close,
};
static int __init scdd_init(void)
{ /*模块初始化函数*/
intsmajor;
smajor=DEVICE_MAJOR;
dev_tdev_n=MKDEV(smajor,0);
/*申请设备号*/
if(!register_chrdev_region(dev_n,1,DEVICE_NAME))
{ /*静态申请*/
printk("registersuccess\n");
}else
{
gotoregister_error;
}
/*else
{ /*动态申请*/
/*alloc_chrdev_region(&dev_n,0,1,DEVICE_NAME);
smajor=MAJOR(dev_n);
}*/
/*初始化cdev结构体*/
cdev_init(&my_cdev,&scdd_fops);
my_cdev.owner=THIS_MODULE;
my_cdev.ops=&scdd_fops;
/*注册字符设备*/
cdev_add(&my_cdev,dev_n,1);
return0;
register_error:
unregister_chrdev_region(MKDEV(DEVICE_MAJOR,0),1);
return0;
}
static void __exit scdd_exit(void)
{ /*模块卸载函数*/
cdev_del(&my_cdev);
unregister_chrdev_region(MKDEV(DEVICE_MAJOR,0),1);
}
module_init(scdd_init);
module_exit(scdd_exit);
MODULE_LICENSE("Dual BSD/GPL");
这个程序只是简单演示字符注册的一个完整过程,并不带有复杂的操作,调用read时向用户空间写全1