- 驱动代码
- Makefile
- 编译和加载驱动
- 编写应用程序测试驱动
驱动程序
// hello.c 驱动程序
#include <linux/module.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>
#include <linux/slab.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 hello_open(struct inode *p, struct file *f)
{
printk(KERN_INFO "hello_open\r\n");
return 0;
}
ssize_t hello_write(struct file *f, const char __user *u, size_t s, loff_t *l)
{
printk(KERN_INFO "hello_write\r\n");
return 0;
}
ssize_t hello_read(struct file *f, char __user *u, size_t s, loff_t *l)
{
printk(KERN_INFO "hello_read\r\n");
return 0;
}
int hello_init(void)
{
devNum = MKDEV(reg_major, reg_minor); // 根据主次设备号生成一个设备号(为一个设备一个设备号)
if(OK == register_chrdev_region(devNum, subDevNum, "helloworld")){ // 将该设备注册到内核
printk(KERN_INFO "register_chrdev_region ok \n");
}else {
printk(KERN_INFO "register_chrdev_region error n");
return ERROR;
}
printk(KERN_INFO " hello driver init \n");
gDev = kzalloc(sizeof(struct cdev), GFP_KERNEL); // 申请一个cdev结构体,用于描述设备
gFile = kzalloc(sizeof(struct file_operations), GFP_KERNEL); // file_operations是设备的操作的抽象函数
// 下面就是将自定义的操作函数赋予该设备的操作列表中
gFile->open = hello_open;
gFile->read = hello_read;
gFile->write = hello_write;
gFile->owner = THIS_MODULE;
cdev_init(gDev, gFile); // 建立dev和操作的联系
cdev_add(gDev, devNum, 1); // 建立设备号和dev结构体联系
return 0;
}
void __exit hello_exit(void)
{
printk(KERN_INFO " hello driver exit \n");
cdev_del(gDev);
kfree(gFile);
kfree(gDev);
unregister_chrdev_region(devNum, subDevNum);
return;
}
module_init(hello_init); // 驱动程序的入口函数,相当于main函数,当insmod就会调用hello_init函数
module_exit(hello_exit); // 当rmmod时,调用hello_exit
MODULE_LICENSE("GPL");
Makefile
ifneq ($(KERNELRELEASE),)
obj-m := helloDev.o
else
PWD := $(shell pwd)
KDIR := /lib/modules/4.4.0-31-generic/build # 内核头文件的目录,如果没有这个目录,需要安装内核开发包
#KDIR := /lib/modules/`uname -r`/build
all:
make -C $(KDIR) M=$(PWD)
clean:
rm -rf *.o *.ko *.mod.c *.symvers *.c~ *~
endif
编译加载驱动
dmesg -c
insmod helloDev.ko
dmesg
测试驱动
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/select.h>
#define DATA_NUM (64)
int main(int argc, char *argv[])
{
int fd, i;
int r_len, w_len;
fd_set fdset;
char buf[DATA_NUM]="hello world";
memset(buf,0,DATA_NUM);
fd = open("/dev/hello", O_RDWR);
printf("%d\r\n",fd);
if(-1 == fd) {
perror("open file error\r\n");
return -1;
}
else {
printf("open successe\r\n");
}
w_len = write(fd,buf, DATA_NUM);
r_len = read(fd, buf, DATA_NUM);
printf("%d %d\r\n", w_len, r_len);
printf("%s\r\n",buf);
return 0;
}
在运行测试程序之前,先手动在/dev创建设备文件:
mknod /dev/hello c 232 0
c:字符设备
232:主设备号
0:次设备号
然后可以运行测试程序进行测试。