(YDW)字符设备驱动程序实例一

字符设备驱动

/*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$ 

猜你喜欢

转载自blog.csdn.net/weixin_42015463/article/details/82118052