Linux 2.6.32内核字符设备驱…

原创 2013年12月02日 09:13:08

引言:Linux驱动中,字符设备的设计一般会占产品驱动开发的90%以上,作者根据驱动开发的实际经验,总结了一个标准的字符设备驱动的模板,仅供参考。

//=======================字符设备驱动模板开始 ===========================//

#define CHAR_DEV_DEVICE_NAME   "char_dev"   // 设备名

struct class *char_dev _class;  // class结构用于自动创建设备结点 
static int major = 0;

static struct cdev char_dev_devs;// 定义一个cdev结构

// 设备建立子函数,被char_dev_init函数调用  
static void char_dev_setup_cdev(struct cdev *dev, int minor, struct file_operations *fops)
{
    int err, devno = MKDEV(major, minor);
    
    cdev_init(dev, fops);
    dev->owner = THIS_MODULE;
    dev->ops = fops;
    
    err = cdev_add(dev, devno, 1);
    if( err )
    {
        printk(KERN_NOTICE "Error %d adding char_dev %d\n", err, minor);
    }
}

//  file_operations 结构体设置,该设备的所有对外接口在这里明确,此处只写出了几常用的 
static struct file_operations char_dev_fops =
{
    .owner = THIS_MODULE,
    .open  = char_dev_open,      //
 打开设备 
    .release = char_dev_release, //
 关闭设备 
    .read  = char_dev_read,      //
 实现设备读功能 
    .write = char_dev_write,     //
 实现设备写功能 
    .ioctl = char_dev_ioctl,     //
实现设备控制功能 
};

// 进行初始化设置,打开设备,对应应用空间的open 系统调用 
int char_dev_open (struct inode *inode, struct file *filp)

{

...   //  这里可以进行一些初始化

return 0;

}

 

// 释放设备,关闭设备,对应应用空间的close 系统调用

static int char_dev_release (struct inode *node, struct file *file)

{

...    //  这里可以进行一些资源的释放

return 0;

}

// 实现读功能,读设备,对应应用空间的read 系统调用

ssize_t char_dev_read (struct file *file,char __user *buff,size_t count,loff_t *offp)

{

     ...

return 0;

}

// 实现写功能,写设备,对应应用空间的write 系统调用

ssize_t char_dev_write(struct file *file,const char __user *buff,size_t count,loff_t *offp)

{

    ...

    return 0;

}

 

// 实现主要控制功能,控制设备,对应应用空间的ioctl 系统调用

static int char_dev _ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)

{  

    ...

    return 0;

}

//   设备初始化 
static int char_dev_init(void)
{
    int result;
    dev_t dev = MKDEV(major, 0);
    
    if( major )
    {

// 给定设备号注册 
        result = register_chrdev_region(dev, 1, CHAR_DEV_DEVICE_NAME);
    }

else
    {

// 动态分配设备号 
        result = alloc_chrdev_region(&dev, 0, 1, CHAR_DEV_DEVICE_NAME);
        major = MAJOR(dev);
    }
    
    char_dev_setup_cdev(&char_dev_devs, 0, &char_dev_fops);
    printk("The major of the char_dev device is %d\n", major);

//==== 有中断的可以在此注册中断:request_irq,并要实现中断服务程序 ===//

// 创建设备结点

char_dev _class = class_create(THIS_MODULE,"ad_class");

if (IS_ERR(char_dev _class))

{

    printk("Err: failed in creating class.\n");

    return 0;

}

device_create(char_dev_class, NULL, dev, NULL, "char_dev");
    return 0;
}

// 设备注销 
static void char_dev_cleanup(void)
{

device_destroy(adc_class,dev);

class_destroy(adc_class);
    cdev_del(&char_dev_devs);//
字符设备的注销*/
    unregister_chrdev_region(MKDEV(major, 0), 1);//
设备号的注销

//========  有中断的可以在此注销中断:free_irq  ======//


    printk("char_dev device uninstalled\n");
}

module_init(char_dev_init);//
模块初始化接口
module_exit(char_dev_cleanup);//
模块注销接口

// 以下两句不能省略,否则编译不通过 
MODULE_AUTHOR("www.embedhq.org");
MODULE_LICENSE("GPL");

//==================== 字符设备驱动模板结束 ========================//


Makefile模板编译,Makefile如下:

//======================= Makefile开始 ===========================//

ifeq ($(KERNELRELEASE),)

#KERNELDIR ?= /your/target/source/directory/

KERNELDIR ?= /opt/kernal/linux-2.6.32.10/

PWD := $(shell pwd)

modules:

    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

modules_install:

    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

clean:

    rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

.PHONY: modules modules_install clean

//========================= Makefile结束 =============================//

make编译后生成char_dev.ko,控制台输入加载和卸载命令,还可以使用lsmod查看已经加载的模块信息。
insmod char_dev.ko #
加载驱动,会执行module_init中的语句
rmmod char_dev     #
卸载驱动,会执行module_exit中的语句

(原文出处:http://www.embedhq.org/, 转载请注明出处)

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Linux 2.6.32内核字符设备驱…

引言:Linux驱动中,字符设备的设计一般会占产品驱动开发的90%以上,作者根据驱动开发的实际经验,总结了一个标准的字符设备驱动的模板,仅供参考。 //=======================字...

Linux2.6.32驱动笔记(2)字符设备驱动编程模型

摘要:如何安装使用字符设备驱动,总结了字符设备驱动编程模型,初始化,注册等,最后分析了file_operations。 一、如何安装使用字符设备驱动     参见内核模块,比如有一个驱动叫...

Linux内核编程七:字符设备驱动

个人总结PDF截图,特此声明!

linux内核cdev_init系列函数(字符设备的注册)

内核中每个字符设备都对应一个 cdev 结构的变量,下面是它的定义: linux-2.6.22/include/linux/cdev.h struct cdev {    struct kobj...

Linux内核学习-字符设备驱动学习(一)

Linux内核学习-字符驱动学习(一) 现在学习一下Linux的字符设备驱动,参考的样本应该就是ldd3这书大概第3章的内容吧。下面的所说的字符设备都是基于2.6内核的,一般的流程都是,呵呵,其实也不...

linux驱动开发--字符设备:内核等待队列

在Linux驱动程序中,可以使用等待队列(wait queue)来实现阻塞进程的唤醒。等待队列可以用来同步对系统资源的访问。 1.定义和初始化队列头 wait_queue_head_t wqh; in...
  • waldmer
  • waldmer
  • 2014年01月24日 15:05
  • 1710

Linux内核大讲堂 (二) 传说中的字符设备(4)

Linux内核大讲堂 (二) 传说中的字符设备(4)经过前面的学习,我们发现有一个东西像恶梦一样挥之不去,无论是讲驱动模型中的sysfs还是讲字符驱动的file,这些文件系统内的概念和模块已经让我们达...
  • z2007b
  • z2007b
  • 2011年06月13日 00:52
  • 18332

Linux内核大讲堂 (二) 传说中的字符设备(3)

Linux内核大讲堂 (二) 传说中的字符设备(3)       接下来讲的是字符设备的重点,就是从用户空间调用open最到终调用我们写的字符驱动中的open的整个过程。下面的讨论将会非常有意思,请大...
  • z2007b
  • z2007b
  • 2011年06月06日 23:22
  • 11585

Linux内核学习-字符设备驱动学习(二)

在Linux内核学习-字符设备驱动学习(一)中编写字符设备驱动的一种方法,但是需要手动创建设备节点。有没有能够自动的创建设备节点的呢?有!使用class_create()和device_create(...

linux驱动开发之字符设备--内核和用户空间数据的交换(read write)

前边给出了字符设备的框架,内核和用户空间进行交流的时候,离不来数据的交换;内核实现read、wriet 、ioctl是常用的交互手段。...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux 2.6.32内核字符设备驱…
举报原因:
原因补充:

(最多只允许输入30个字)