字符设备驱动程序之LED驱动程序_测试改进(三)

字符设备驱动程序之LED驱动程序_测试改进


在加载驱动之前,先来看一下/proc/devices,里面是现在内核所支持的设备。

第一列是主设备号,对应的是内核数组chrdevs的下标,第二列是它的名字。



加载驱动的命令:insmod first_drv.ko

                          cat /proc/devices



写个测试驱动程序来测试它。(见代码二)



mknod /dev/xxx c 主设备号 次设备号

register_chrdev(111,"first_drv",&first_drv_fops);

                 怎么确定这设备号111?

            1、先cat /proc/devices,有哪一个空缺项,然后选取那个空缺项。(1~255)。

             2、也可以写为0,系统会自动给我们分配一个主设备号,它在数组chrdevs找一个空缺项,给你返回主设备号。

                               major=register_chrdev(0,...,...);



1、驱动的主设备号:自动分配主设备号;手工指定主设备号。

2、应用:open("/dev/xxx");

                                 xxx文件怎么来的?

                        a.mknod /dev/xxx c 主设备号 次设备号(手工建立,需要先知道主设备号)

                       b.自动创建:对于应用程序,udev机制;对于busybox来说,mdev程序

cd /sys(系统目录下的信息)。注册驱动时,先会在sys目录下生成设备信息


mdev:会根据系统的信息,创建设备节点。(驱动程序里,如果能提供系统的信息,mdev就能自动帮我们创建设备节点)


★★★

为什么sys目录下的信息一更改,mdev就会自动运行、生成呢?

vi /etc/init.d/rcS:
    在创建根文件系统时:

        

内核里一旦有设备加载进去或者卸载之后,就会根据调用/proc/sys/kernel/hotplug所指示的应用程序。



程序一:first_dev.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>

static struct class *firstdrv_class;	//一个类
static struct class_device	*firstdrv_class_dev;	//一个类里面再建立一个设备

static int first_drv_open(struct inode *inode, struct file *file)
{
	printk("first_drv_open\n");
	return 0;
}

static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
	printk("first_drv_write\n");
	return 0;
}

static struct file_operations first_drv_fops = {
    .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
    .open   =   first_drv_open,     
	.write	=	first_drv_write,	   
};

int major;

int first_drv_init(void)
{
	//0:让系统给我们自动分配一个主设备号,在数组中找个空缺,返回主设备号
	major = register_chrdev(0, "first_drv", &first_drv_fops); //注册驱动程序,告诉内核,再内核数组里,把fops结构填充进去

	/* 下面这两条代码就会在sys目录下,class目录下,建立firstdrv这个类,再firstdrv这个类下,会创建xyz这个设备,再xyz目录下有个dev文件,里面有主设备号:次设备号 */
	/* 然后mdev根据上面的系统信息,就会创建/dev/xyz这个设备节点 */
        /* ★★下面两条代码会根据自动分配的主设备号,生成设备文件,并且生成系统信息 */
	//先建立一个类
	firstdrv_class = class_create(THIS_MODULE, "firstdrv");

	//在这个类下面建立一个设备
	firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz");

	return 0;
}

void first_drv_exit(void)
{
	unregister_chrdev(major, "first_drv"); //卸载驱动

	
	class_device_unregister(firstdrv_class_dev);
	class_destroy(firstdrv_class);
}


module_init(first_drv_init);
module_exit(first_drv_exit);

MODULE_LICENSE("GPL");    //license,可以解决class_device_unregister和class_destory不能识别的问题


程序二:测试程序firstdrvtest.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>


int main(int argc, char **argv)
{
	int fd;
	int val = 1;
	fd = open("/dev/xyz", O_RDWR);    //无论主设备号怎么变,/dev/xyz都是系统为我们创建的
	if (fd < 0)
	{
		printf("can't open!\n");
	}
	write(fd, &val, 4);
	return 0;
}

编译程序:arm-linux-gcc -o fristdrvtest fristdrvtest.c


猜你喜欢

转载自blog.csdn.net/xiaodingqq/article/details/80254714