字符设备驱动
/*demo.c--动态注册设备号--自动创建设备文件*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#define COUNT 3
#define BASEMINOR 0
#define NAME "demo_dev"
struct cdev *cdevp = NULL;
dev_t devno;
struct class *class = NULL;
struct device *device = NULL;
int major = 0;
int demo_open(struct inode *inode, struct file *file)
{
printk("----open----\n");
return 0;
}
int demo_close(struct inode *inode, struct file *file)
{
printk("----close----\n");
return 0;
}
ssize_t demo_read(struct file *file, char __user *user, size_t size, loff_t *lof)
{
printk("----read----\n");
return 0;
}
ssize_t demo_write(struct file *fiel, const char __user *user, size_t size, loff_t *lof)
{
printk("----write----\n");
return 0;
}
struct file_operations fops = {
.open = demo_open,
.read = demo_read,
.write = demo_write,
.release = demo_close
};
static int __init demo_init(void)
{
int ret = 0;
int i = 0;
//0、动态注册设备号
ret = alloc_chrdev_region(&devno, BASEMINOR, COUNT, NAME);
if(ret < 0)
{
printk("fail to alloc_chrdev_region\n");
return -EAGAIN;
}
major = MAJOR(devno);
printk(KERN_INFO "----major = %d----\n", major);
//1、申请设备结构体cdev_alloc
cdevp = cdev_alloc();
if(NULL == cdevp)
{
printk("fail to cdev_alloc\n");
ret = -ENOMEM;
goto err;
}
//2、初始化设备结构体cdev_init
cdev_init(cdevp, &fops);
//3、向内核注册设备结构体cdev_add
ret = cdev_add(cdevp, devno, COUNT);
if(ret < 0)
{
printk("fail to cdev_add\n");
ret = -EAGAIN;
goto err1;
}
//4、自动创建设备文件
class = class_create(THIS_MODULE, NAME);
if(IS_ERR(class)){
printk(KERN_INFO "fail to class_creat\n");
ret = PTR_ERR(class);
goto err1;
}
for(i = 0;i < 3; i++){
device = device_create(class, NULL, MKDEV(major, i), NULL, "%s%d",NAME, i);
if(IS_ERR(device)){
printk(KERN_INFO "fail to device_creat\n");
ret = PTR_ERR(device);
return ret;
}
}
printk("--%d--%s--%s\n",__LINE__, __FILE__, __func__);
return 0;
err2:
for(--i;i>=0;i--)
{
device_destroy(class,MKDEV(major,i));
}
class_destroy(class);
err1:
cdev_del(cdevp);
err:
unregister_chrdev_region(devno, COUNT);
return ret;
}
static void __exit demo_exit(void)
{
int i = 0;
for(i = 0;i < 3;i++)
{
device_destroy(class,MKDEV(major,i));
}
class_destroy(class);
cdev_del(cdevp);
unregister_chrdev_region(devno, COUNT);
printk("--%d--%s--%s\n",__LINE__, __FILE__, __func__);
}
module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");
Makefile
1 KERNELDIR:=/lib/modules/$(shell uname -r)/build/
2 #KERNELDIR:=/home/linux/yudw2018/1_test_yu/4_18051/kernel-3.4.39/
3 PWD:=$(shell pwd)
4
5 all:
6 make -C $(KERNELDIR) M=$(PWD) modules
7 clean:
8 make -C $(KERNELDIR) M=$(PWD) clean
9 obj-m:=demo.o
应用程序--测试调用open close 函数时,linux内核调用相应的demo_open,demo_close函数接口
/*demo_test.c*/
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5
6 int main(int argc, const char *argv[])
7 {
8 int fd = 0;
9
10 fd = open("/dev/demo_dev0", O_RDWR);
11 if(fd < 0){
12 perror("fail to open");
13 }
14
15 close(fd);
16
17 return 0;
18 }
执行步骤
linux@ubuntu:~/yudw2018/1_test_yu/4_18051/1_drivers/3_demo_dev$ make
linux@ubuntu:~/yudw2018/1_test_yu/4_18051/1_drivers/3_demo_dev$ sudo insmod demo.ko
linux@ubuntu:~/yudw2018/1_test_yu/4_18051/1_drivers/3_demo_dev$ sudo chmod 777 /dev/demo_dev0
linux@ubuntu:~/yudw2018/1_test_yu/4_18051/1_drivers$ gcc demo_test.c
linux@ubuntu:~/yudw2018/1_test_yu/4_18051/1_drivers$ dmesg
[24185.030974] ----major = 250----
[24185.033879] --100--/home/linux/yudw2018/1_test_yu/4_18051/1_drivers/3_demo_dev/demo.c--demo_init
[24284.165385] ----open----
[24284.165392] ----close----
linux@ubuntu:~/yudw2018/1_test_yu/4_18051/1_drivers$
//卸载
linux@ubuntu:~/yudw2018/1_test_yu/4_18051/1_drivers/3_demo_dev$ sudo rmmod demo
linux@ubuntu:~/yudw2018/1_test_yu/4_18051/1_drivers/3_demo_dev$ sudo dmesg -c
[24185.030974] ----major = 250----
[24185.033879] --100--/home/linux/yudw2018/1_test_yu/4_18051/1_drivers/3_demo_dev/demo.c--demo_init
[24284.165385] ----open----
[24284.165392] ----close----
[24353.027150] --128--/home/linux/yudw2018/1_test_yu/4_18051/1_drivers/3_demo_dev/demo.c--demo_exit
linux@ubuntu:~/yudw2018/1_test_yu/4_18051/1_drivers/3_demo_dev$