驱动初步

驱动分为:字符设备驱动,块设备驱动和网络设备驱动。

字符设备驱动是操作字节流,不允许随机访问。

块设备允许随机访问。

字符设备比较基础,下面给出编写字符驱动的方法。

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

MODULE_LICENSE ("GPL");

static int __init hello_2_init (void)
{
printk (KERN_INFO "Hello world\n");
return 0;
}

static void __exit hello_2_exit (void)
{
printk (KERN_INFO "Goodbye world\n");
}

module_init (hello_2_init);
module_exit (hello_2_exit);

最简单的驱动模型:1.加载模块 2.卸载模块 3.许可证声明

以下是典型的字符设备驱动的编写:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>

MODULE_LICENSE ("GPL");

int hello_major = 250;
int hello_minor = 0;
int number_of_devices = 1;

struct cdev cdev;
dev_t dev = 0;

struct file_operations hello_fops = {
.owner = THIS_MODULE
};

static void char_reg_setup_cdev (void)
{
int error, devno = MKDEV (hello_major, hello_minor);
cdev_init (&cdev, &hello_fops);
cdev.owner = THIS_MODULE;
// cdev.ops = &hello_fops;
error = cdev_add (&cdev, devno , 1);
if (error)
printk (KERN_NOTICE "Error %d adding char_reg_setup_cdev", error);

}

static int __init hello_2_init (void)
{
int result;
dev = MKDEV (hello_major, hello_minor);
result = register_chrdev_region (dev, number_of_devices, "hello");
if (result<0) {
printk (KERN_WARNING "hello: can't get major number %d\n", hello_major);
return result;
}

char_reg_setup_cdev ();
printk (KERN_INFO "Registered character driver\n");
return 0;
}

static void __exit hello_2_exit (void)
{
dev_t devno = MKDEV (hello_major, hello_minor);

cdev_del (&cdev);

unregister_chrdev_region (devno, number_of_devices);

printk (KERN_INFO "char driver cleaned up\n");
}

module_init (hello_2_init);
module_exit (hello_2_exit);

 

 

第一步:在加载函数中首先申请设备

dev = MKDEV (hello_major, hello_minor);

这是个宏函数#define MKDEV(major,minor) (((major) << MINORBITS) | (minor))

返回一个dev_t类型的数据,它是主设备号和此设备号的拼接,内核中定义前12位是主设备号,后20位是次设备号。

第二步:注册设备节点号

result = register_chrdev_region (dev, number_of_devices, "hello");静态申请

alloc_chrdev_region动态创建节点。

第一个参数是链接的设备号,第二个是有几个设备,第三个参数数设备的名称

第三步:注册设备

char_reg_setup_cdev ();

static void char_reg_setup_cdev (void)
{
int error, devno = MKDEV (hello_major, hello_minor);
cdev_init (&cdev, &hello_fops);
cdev.owner = THIS_MODULE;
error = cdev_add (&cdev, devno , 1);
if (error)
printk (KERN_NOTICE "Error %d adding char_reg_setup_cdev", error);

 }

首先初始化cdev结构体,初始化结构体的函数里面的第二个参数是一个结构体,在此初始化前

要先把这个结构体填充,然后add来注册设备。

struct file_operations hello_fops = {
.owner = THIS_MODULE
};

file_operations类型里有很多操作,包括read,write等

通过这些操作基本上的功能就会实现。

 

 

posted on 2012-07-11 22:10  孟浩依然  阅读(911)  评论(0编辑  收藏  举报