框架加载流程
/**********************************************
*** 一个简单的linux字符设备驱动示例
*** Autor: ybdesire
*** Create Date: 2012-11-12
*** Completion Date:2012-11-25
**********************************************/
#include //模块init/exti必备
#include //同上
#include //struct task_struct *current
#include //file_operation, file, inode
#include //设备号相关,eg MAJOR, MINOR, MKDEV
#include //字符设备相关操作,init,add,del
#include //kmalloc, kfree
#include //copy_to_user, copy_from_user
//各个file operation之间可用struct file中的private_data传递参数
int chardd_open( struct inode *inode, struct file *filp)
{
printk(KERN_EMERG "chardd_open\n");
printk(KERN_EMERG "chardd open thread pid: %d\n", current->pid);//显示当前open设备的进程号
return 0;
}
int chardd_release( struct inode *inode, struct file *flip )
{
printk(KERN_EMERG "chardd_release\n");
return 0;
}
int chardd_read( struct file *filp, char *buf, size_t count, loff_t *ppos )
{
if(filp->private_data==NULL)
printk(KERN_EMERG "in read: private data in file struct is NULL\n");
else
{
printk(KERN_EMERG "in read: private data in file struct is not NULL\n");
copy_to_user(buf, filp->private_data, count);//将内核空间中filp->private_data指向的数据拷贝到用户空间buf
}
kfree(filp->private_data); //拷贝完后释放kmalloc出来的堆空间
filp->private_data = NULL;
return 0;
}
int chardd_write( struct file *filp, const char *buf, size_t count, loff_t *offp )
{
if(filp->private_data==NULL)//若指针为空,为其分配空间
{
printk(KERN_EMERG "in write: private data in file struct is NULL\n");
filp->private_data = (void*)kmalloc(100, GFP_KERNEL);
}
else
printk(KERN_EMERG "in write: private data in file struct is not NULL\n");
copy_from_user(filp->private_data, buf, count);//将用户空间buf中的数据拷贝到内核空间filp->private_data
return 0;
}
struct file_operations chardd_fops =
{
.owner = THIS_MODULE,
.open = chardd_open,
.release = chardd_release,
.read = chardd_read,
.write = chardd_write,
};
dev_t dev; //device number
struct cdev *chardd_dev = NULL;
static int __init initchardd(void)
{
int rt;
int chardd_minor = 5;
int chardd_count = 2;
//动态申请主设备号,为chardd_count个设备申请,得到的主设备号依次递增
//若返回主设备号为200,则设备1的设备号(主200, 从5),设备2的设备号(主200, 从6)
//本例设备名为chardd,注册成功可用cat /proc/devices查看
rt = alloc_chrdev_region(&dev, chardd_minor, chardd_count, "chardd");
if(rt==0)
{
printk(KERN_INFO "char device driver init ok");
printk(KERN_INFO "char device drive major device num: %d\n", MAJOR(dev));
printk(KERN_INFO "char device drive minor device num: %d\n", MINOR(dev));
}
else
printk(KERN_INFO "char device driver init NOT ok");
chardd_dev = cdev_alloc();//为字符设备申请空间
if(chardd_dev==NULL)
printk(KERN_INFO "cdev alloc error");
else
printk(KERN_INFO "cdev alloc ok");
chardd_dev->ops = &chardd_fops;//绑定fileoepration操作
cdev_init(chardd_dev, &chardd_fops);
printk(KERN_INFO "cdev init ok");
rt = cdev_add(chardd_dev, dev, 1); //添加字符设备
if(rt==0)
printk(KERN_INFO "cdev add ok");
else
printk(KERN_INFO "cdev add error");
return 0;
}
static void __exit exitchardd(void)
{
int chardd_count = 2;
//释放设备号
unregister_chrdev_region(dev, chardd_count);
//删除字符设备
cdev_del(chardd_dev);
printk(KERN_INFO "char device driver exit");
}
module_init(initchardd);
module_exit(exitchardd);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("ybdesire");
MODULE_DESCRIPTION("a .ko character device driver demo");
MODULE_VERSION("v10");
【使用】编译(make),加载(insmod),mknod 到/dev/chardd
/**********************************************
*** 字符设备驱动测试程序
*** Autor: ybdesire
*** Create Date: 2012-11-23
*** Completion Date:2012-11-25
**********************************************/
#include
#include
#include
#include
#include
#include
#include
int main()
{
int fp, ret;
unsigned char ch[]="hello kernel device driver!";
unsigned char *buf1 = (unsigned char *)malloc(sizeof(ch)+1);
unsigned char *buf2 = (unsigned char *)malloc(sizeof(ch)+1);
//init buff
memset(buf1, 0, sizeof(ch)+1);
memset(buf2, 0, sizeof(ch)+1);
strcpy(buf1, ch);//ch to buf1
//打开设备驱动,前提是用mknode把字符设备建立为/dev/chardd
fp = open("/dev/chardd", O_RDONLY);
printf("fp is %d\n", fp);
ret = write(fp, buf1, sizeof(ch));//write buf1 to fp
printf("write return : %d\n", ret);
ret = read(fp, buf2, sizeof(ch));//read fp to buf2
printf("read return : %d\n", ret);
printf("read data:%s\n", buf2);
close(fp);
return 0;
}
ybde @ubuntu:~/Test/Driver/ch3/chardd$ sudo insmod chardd.ko
ybde @ubuntu:~/Test/Driver/ch3/chardd$ mknod /dev/chardd c 250 5
ybde: "/dev/chardd": 权限不够
ybde @ubuntu:~/Test/Driver/ch3/chardd$ sudo mknod /dev/chardd c 250 5
ybde @ubuntu:~/Test/Driver/ch3/chardd$ cd main/ (main中为测试代码)
ybde @ubuntu:~/Test/Driver/ch3/chardd/main$ gcc main.c
ybde @ubuntu:~/Test/Driver/ch3/chardd/main$ ./a.out
fp is -1
write return : -1
read return : -1
read data:
ybde @ubuntu:~/Test/Driver/ch3/chardd/main$ sudo ./a.out
fp is 3
write return : 0
read return : 0
read data:hello kernel device driver!
ybde @ubuntu:~/Test/Driver/ch3/chardd/main$