本文的目的是为了掌握字符设备驱动的第一原理,掌握字符设备的基本框架。
下面写出最基本的框架:
#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; } }
最终得到的结果是:

 
                    
                     
                    
                 
                    
                 
 
         
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号