关于那个什么 Unknown symbol platform_driver_unregister (err 0) 等之类的错误,如果内核里有这个函数,比如platform_driver_unregister这个函数在内核代码中有定义(/drivers/base/Platform.c中)但是还是报错,因为有这一行:EXPORT_SYMBOL_GPL(platform_driver_unregister);
所以为了这个JB许可证,要在我们的代码中加入MODULE_LICENSE("GPL");
1.申请设备号
2.注册设备
3.添加设备
4.实现设备操作方法
Allocates major/minor numbers via alloc_chrdev_region() and friends
Creates /dev and /sys nodes using class_create() and device_create() //这个是自动创建设备文件,否则就要到/dev/目录下mknod手动创建文件..
Registers itself as a char driver using cdev_init() and cdev_add()
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#ifndef MEMDEV_SIZE
#define MEMDEV_SIZE 1024
#endif
struct mymemdev
{
unsigned int size;
char *data;
};
struct mymemdev memdev;
char *devname="mydev0";
struct cdev chardev; // 如果定义成 指针 则要用 cdev_alloc(void);进行分配.....
int major_num;
dev_t mydev;
int mem_open(struct inode *inode, struct file *filp)
{
filp->private_data=&memdev;
return 0;
}
int mem_release(struct inode *inode, struct file *filp)
{
kfree(memdev.data);
return 0;
}
static loff_t mem_llseek(struct file *filp, loff_t offset, int whence)
{
loff_t newpos;
switch(whence) {
case 0: /* SEEK_SET */
newpos = offset;
break;
case 1: /* SEEK_CUR */
newpos = filp->f_pos + offset;
break;
case 2: /* SEEK_END */
newpos = MEMDEV_SIZE -1 + offset;
break;
default: /* can't happen */
return -EINVAL;
}
if ((newpos<0) || (newpos>MEMDEV_SIZE))
return -EINVAL;
filp->f_pos = newpos;
return newpos;
}
static mem_read(struct file *filp,char __user *buff,size_t size ,loff_t *fops)
{
int count;
if (*fops >= MEMDEV_SIZE)
return 0;
if (size > MEMDEV_SIZE - *fops)
size = MEMDEV_SIZE - *fops;
printk("<0> This in write function!!!! \n");
if(count=copy_to_user(buff,(void*)(memdev.data + *fops) , size))
{
printk("<0> write error");
return 0;
}
else
{
*fops+=size;
printk("<0> copy %d size data ,fops is %d \n",size,*fops);
}
return size; //remember this line,,, for the linux standard API interface retrun result and for write function tooooooooooooooo......
}
static mem_write(struct file *filp,char __user *buff,size_t size,loff_t *fops)
{
int count;
if (*fops >= MEMDEV_SIZE) // Check the parament legal or not
return 0;
if (size> MEMDEV_SIZE - *fops)
size = MEMDEV_SIZE - *fops;
printk("<0> This in write function!!!! \n");
if(count=copy_from_user(memdev.data + *fops,buff, size))
{
printk("<0> write error");
return 0;
}
else
{
*fops+=size;
printk("<0> copy %d size data ,fops is %d \n",size,*fops);
}
return size;
}
struct file_operations fops=
{
.owner = THIS_MODULE,
.llseek = mem_llseek,
.read = mem_read,
.write = mem_write,
.open = mem_open,
.release = mem_release,
};
static int __init mydev_init(void)
{
printk("<0> go to dirctory /proc/devices to find mydev\n");
if(alloc_chrdev_region(&mydev,0,1,devname)<0)
{
return(-1);
}
printk("<0> we get char dev num is %d \n",MAJOR(mydev));
memdev.data=kmalloc(MEMDEV_SIZE, GFP_KERNEL); // This is extremely importmant ...................................................
if(memdev.data==NULL) //Check kmalloc sucess.....
{
printk("<0> error\n");
return 0;
}
// 现在进行字符设备的初始化.......
cdev_init(&chardev,&fops);
chardev.owner = THIS_MODULE;
chardev.ops = &fops;
//添加设备....
cdev_add(&chardev,mydev,1);
return 0;
}
static void mydev_exit(void)
{
cdev_del(&chardev);
unregister_chrdev_region(mydev,1);
printk("<0> Goodbye...\n");
}
module_init(mydev_init);
module_exit(mydev_exit);
MODULE_LICENSE("GPL");