一、这里博主用的是Ubuntu12.04版本、内核是2.6.35.
我简单写了个驱动程序,命名为charDev.c
这个代码是错误的,更改后的在最下面。
#include <linux/module.h>
#include <linux/moduleparam.h>
#indclude <linux/cdev.h>
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/sched.h>
#define BUFFER_MAX (10)
#define OK (0)
#define ERROR (-1)
struct cdev *gDev;
struct file_operations *gFile;
dev_t devNum;
unsigned int subDevNum = 1;
int reg_major=232;
int reg_minor = 0;
char *buffer;
int flag = 0;
int testOpen(struct inode *p, struct file *f)
{
printk(KERN_EMERG" testOpen\r\n");
return 0;
}
25 ssize_t testWrite(struct file *f, const char __user *u,size_t s,loff_t *l)
26 {
27 printk(KERN_EMERG"testWrite\r\n");
28 return 0;
29 }
30 ssize_t testRead(struct file *f, char __user *u, size_t s, loff_t *l)
31 {
32 printk(KERN_EMERG"testRead\r\n");
33 return 0;
34 }
35
36 int charDrvInit(void)
37 {
38 devNum=MKDEV(reg_major,reg_minor);
39 printk(KERN_EMERG"devNum is %d\r\n", devNum);
40 if(OK == register_chrdev_region(devNum,subDevNum,"testchar"))
41 {
42 printk(KERN_EMERG"register_chrdev_region ok\r\n");
43 }
44 else
45 {
printk(KERN_EMERG"register_chrdev_region error\r\n");
47 return ERROR;
48 }
49
50 printk(KERN_EMERG"devNum is %d\r\n", devNum);
51 gDev = kzalloc(sizeof(struct cdev),GFP_KERNEL);
52 gFile =kzalloc(sizeof(struct file_operations),GFP_KERNEL);
53
54 gFile->open=testOpen;
55 gFile->read=testRead;
56 gFile->write=testWrite;
57 gFile->owner=THIS_MODULE;
58 cdev_init(gDev,gFile);
59 cdev_add(gDev,devNum,3);
60 return 0;
61 }
62
63 void __exit charDrvExit(void)
64 {
65 cdev_del(gDev);
66 unregister_chrdev_region(devNum,subDevNum);
67 return ;
}
69 module_init(charDrvInit);
70 module_exit(charDrvExit);
71 MODULE_LICENSE("GPL");
二、编写Makefile文件(也是错误的,正确的在下面)
ifneq ($(KERNELRELEASE),)
obj-m := charDev.o
else
PWD := $(shell pwd)
KDIR := /lib/modules/‘uname -r’/build
all:
make -C $(KDIR) M=$(PWD)
clean:
rm -rf .*.cmd *.o *.ko *.mod.c *.symvers .tmp_versions *.c~ *~
endif
三、这里就开始make了,也是各种报错的开始。
从图片看出/lib/modules/uname -r/build这一行是出错的,在Makefile文件中,去修改:vi Makefile。
发现KDIR := /lib/modules/‘uname -r’/build这一句中需要根据自己内核的目录来更改‘uname -r’。
两种解决方案:
①命令行模式下uname -r 查看内核号,把查到的内核号替换掉‘uname -r’。
②$(shell uname –r)替换掉‘uname -r’。
再make。
发现make结束虽然没有error,但是!这个make过程中并没有生成.ko和.mod.o等文件。
于是百度得知要么我的charDev.c有问题,要么就是我的Makefile有问题。总之一句话,代码没写对。找代码的错。
改过几次书写的错误后make后还是出错。
发现原来kzalloc需要依赖#include <linux/slab.h>头文件。加上。
出错的地方细微,所以在写代码的时候一定要仔细认真。直接正确代码
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/moduleparam.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/sched.h>
#define BUFFER_MAX (10)
#define OK (0)
#define ERROR (-1)
struct cdev *gDev;
struct file_operations *gFile;
dev_t devNum;
unsigned int subDevNum = 1;
int reg_major=232;
int reg_minor = 0;
char *buffer;
int flag = 0;
int testOpen(struct inode *p, struct file *f)
{
printk(KERN_EMERG" testOpen\r\n");
return 0;
}
ssize_t testWrite(struct file *f, const char __user *u,size_t s,loff_t *l)
{
printk(KERN_EMERG"testWrite\r\n");
return 0;
}
ssize_t testRead(struct file *f, char __user *u, size_t s,loff_t *l)
{
printk(KERN_EMERG"testRead\r\n");
return 0;
}
int charDrvInit(void)
{
devNum=MKDEV(reg_major,reg_minor);
printk(KERN_EMERG"devNum is %d\r\n", devNum);
if(OK == register_chrdev_region(devNum,subDevNum,"testchar"))
{
printk(KERN_EMERG"register_chrdev_region ok\r\n");
}
else
{
printk(KERN_EMERG"register_chrdev_region error\r\n");
return ERROR;
}
printk(KERN_EMERG"devNum is %d\r\n", devNum);
gDev = kzalloc(sizeof(struct cdev),GFP_KERNEL);
gFile =kzalloc(sizeof(struct file_operations),GFP_KERNEL);
gFile->open=testOpen;
gFile->read=testRead;
gFile->write=testWrite;
gFile->owner=THIS_MODULE;
cdev_init(gDev,gFile);
cdev_add(gDev,devNum,3);
return 0;
}
void __exit charDrvExit(void)
{
cdev_del(gDev);
unregister_chrdev_region(devNum,subDevNum);
return ;
}
module_init(charDrvInit);
module_exit(charDrvExit);
MODULE_LICENSE("GPL");
make 还是同样的错误,改Makefile去掉错误的书写格式。
Makefile的书写格式是:依赖命令行的需要按下tab键,才能开始写,不依赖的可以tab也可以不tab,这也是Makefile规则是为了区分。比如:我的Makefile里的
all:
make -C
(
K
D
I
R
)
M
=
(KDIR) M=
(KDIR)M=(PWD)
第二行就是需要先按tab键,不能是空格键!在Makefile里,要么按tab键要么别按,不能按空格。
ifneq ($(KERNELRELEASE),)
obj-m := charDev.o
else
PWD := $(shell pwd)
KDIR := /lib/modules/2.6.35/build
all:
make -C $(KDIR) M=$(PWD)
clean:
rm -rf .*.cmd *.o *.ko *.mod.c *.symvers .tmp_versions *.c~ *~
endif
这是修改正确后的Makefile文件。
四、这下再make就ok了。
五、清除dmesg信息:dmesg -c
insmod charDev.ko打印出的三条信息是charDrvInit(初始化)函数里的。
也就验证了驱动初始化成功,也说明insmod 就会初始化程序。