字符设备驱动的框架和理解(一)

本文的目的是为了掌握字符设备驱动的第一原理,掌握字符设备的基本框架。

下面写出最基本的框架:

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


static struct class *forthdrv_class;
static struct class_device *forthdrv_class_dev;

volatile unsigned long *gpfcon;
volatile unsigned long *gpfdat;

volatile unsigned long *gpgcon;
volatile unsigned long *gpgdat;

 

 


static int forth_drv_open(struct inode *inode, struct file *file)
{
printk("this is the open function\r\n");
return 0;
}

ssize_t forth_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{

printk("this is the read function\r\n");
return 0;
}

 

 

 

static struct file_operations sencod_drv_fops = {
.owner = THIS_MODULE, /* ����һ���꣬�������ģ��ʱ�Զ�������__this_module���� */
.open = forth_drv_open,
.read = forth_drv_read,


};


int major;
static int forth_drv_init(void)
{
major = register_chrdev(0, "forth_drv", &sencod_drv_fops);

forthdrv_class = class_create(THIS_MODULE, "forth_drv");

forthdrv_class_dev = class_device_create(forthdrv_class, NULL, MKDEV(major, 0), NULL, "buttons"); /* /dev/buttons */


return 0;
}

static void forth_drv_exit(void)
{
unregister_chrdev(major, "forth_drv");

return 0;
}


module_init(forth_drv_init);

module_exit(forth_drv_exit);

MODULE_LICENSE("GPL");

 

 

首先第一个结构体

static struct file_operations sencod_drv_fops = {
    .owner   =  THIS_MODULE,   
    .open    =  forth_drv_open,     
    .read     =    forth_drv_read,       
    
    
};

这个结构体是字符设备和内核之间的入口函数。其中.open 函数是当测试的应用程序程序调用open("XXX.txt",XXX)的时候应该调用驱动程序的哪个函数
read也是如此 当测试的应用程序调用read("XXX.txt")的时候应该调用的驱动的程序程序。

那么如何注册一个字符设备呢?
就是要利用
register_chrdev 函数。

register_chrdev 的函数原型是:

/**
* register_chrdev() - Register a major number for character devices.
* @major: major device number or 0 for dynamic allocation
* @name: name of this range of devices
* @fops: file operations associated with these devices
*
* If @major == 0 this functions will dynamically allocate a major and return
* its number.
*
* If @major > 0 this function will attempt to reserve a device with the given
* major number and will return zero on success.
*
* Returns a -ve errno on failure.
*
* The name of this device has nothing to do with the name of the device in
* /dev. It only helps to keep track of the different owners of devices. If
* your module name has only one type of devices it's ok to use e.g. the name
* of the module here.u
* This function registers a range of 256 minor numbers. The first minor number
* is 0.
*/


int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)

上面的注释说明了 此函数是给字符设备设置一个主设备号,但是不生成相应的设备。如果第一个参数给0 这个值,则设备会自动分配一个主设备号。

 forthdrv_class = class_create(THIS_MODULE, "forth_drv");

    forthdrv_class_dev = class_device_create(forthdrv_class, NULL, MKDEV(major, 0), NULL, "buttons"); /* /dev/buttons */

这两个函数一个是建立一个类 这个类的返回值是为了给下面的class_device_create 函数提供一个指针。 下面的class_device_create 是真正的把设备创建了出来我们在/dev下面可以看到这个设备。

 

首先我们先写出这么一个程序 在板子中试验一下:

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

int fd;

int main(int argc, char **argv)
{
    int flags;
    fd = open("/dev/buttons", O_RDWR);
    if (fd < 0)
    {
        printf("can't open!\n");
        return -1;
    }
}

最终得到的结果是:

字符设备驱动的框架和理解(一)

 

上一篇:信号发生器


下一篇:LVGL初步移植