⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 demo.c

📁 Linux 2.6核下的字符驱动示例。以简单的代码表现Linux的驱动程序结构
💻 C
字号:
*********************************************************************//demo.c/** This file is subject to the terms and conditions of the GNU General Public* License. See the file "COPYING" in the main directory of this archive* for more details.** Copyright (C) 2007, 2010 fengGuojin(fgjnew@163.com)*/#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/cdev.h>#include <linux/version.h>#include <linux/vmalloc.h>#include <linux/ctype.h>#include <linux/pagemap.h>#include "demo.h"MODULE_AUTHOR("GuoSong");MODULE_LICENSE("Dual BSD/GPL");struct DEMO_dev *DEMO_devices;//申明自己定义的设备结构的指针static unsigned char demo_inc=0;//计数 记录此设备被打开的次数static char demoBuffer[256];  //模拟存储器int DEMO_open(struct inode *inode, struct file *filp){    struct DEMO_dev *dev;    //只允许打开设备一次    if(demo_inc>0)return -ERESTARTSYS;    demo_inc++;    /*container_of 宏 通过结构中的某个变量获取结构本身的指针*/    dev = container_of(inode->i_cdev, struct DEMO_dev, cdev);    filp->private_data = dev;    return 0;}int DEMO_release(struct inode *inode, struct file *filp){    demo_inc--;    return 0;}ssize_t DEMO_read(struct file *filp, char __user *buf, size_t count,loff_t *f_pos){    int result;    if (copy_to_user(buf,demoBuffer+*f_pos,count))    {       return -EFAULT; /* 把数据写到应用程序空间 */    }        *f_pos = pos; /* 改变文件的读写位置 */    return count;}ssize_t DEMO_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos){    ssize_t retval = -ENOMEM; /* value used in "goto out" statements */    if (copy_from_user(demoBuffer+*f_pos, buf, count)) {       return  -EFAULT;;    }    *f_pos = pos;    return count;}/* ioctl是用来控制设备的 ,unsigned int cmd就是发给设备的命令 ioctl()或许是Linux下最庞杂的函数*/int DEMO_ioctl(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg){    if(cmd==COMMAND1)    {           printk("ioctl command1 successfully\n");           return 0;    }    if(cmd==COMMAND2)    {           printk("ioctl command2 successfully\n");           return 0;    }        printk("ioctl error\n");          return -EFAULT;}//file_operations设备操作集 struct file_operations DEMO_fops = {    .owner =    THIS_MODULE,    .read =     DEMO_read,    .write =    DEMO_write,    .ioctl =    DEMO_ioctl,    .open =     DEMO_open,    .release = DEMO_release,};/*******************************************************                MODULE ROUTINE*******************************************************/void DEMO_cleanup_module(void){    //通过主、次编号算出设备号    dev_t devno = MKDEV(DEMO_MAJOR, DEMO_MINOR);    if (DEMO_devices)     {        cdev_del(&DEMO_devices->cdev);        //内核下的内存操作函数还真怪异 习惯就好        kfree(DEMO_devices);    }    //调用unregister_chrdev_region()函数释放分配的一系列设备号    unregister_chrdev_region(devno,1);}int DEMO_init_module(void){    int result;    /* 在内核中,dev_t类型(在<linux/types.h>中定义)用来保存设备编号——包括主设备号和次设备号*/    dev_t dev = 0;    dev = MKDEV(DEMO_MAJOR, DEMO_MINOR);   /*获取一个或多个设备编号来使用   如果分配成功进行, register_chrdev_region 的返回值是 0. 出错的情况下, 返回一个负的错误码, 你不能存取请求的区域. */    result = register_chrdev_region(dev, 1, "DEMO");    if (result < 0)     {        printk(KERN_WARNING "DEMO: can't get major %d\n", DEMO_MAJOR);        return result;    }    //为自定义的设备结构申请空间    DEMO_devices = kmalloc(sizeof(struct DEMO_dev), GFP_KERNEL);    if (!DEMO_devices)    {        result = -ENOMEM;        goto fail;      }    //为新申请的空间清零    memset(DEMO_devices, 0, sizeof(struct DEMO_dev));    //初始化一个字符驱动    cdev_init(&DEMO_devices->cdev, &DEMO_fops);    DEMO_devices->cdev.owner = THIS_MODULE;    DEMO_devices->cdev.ops = &DEMO_fops;    //在内核中添加字符驱动    result = cdev_add (&DEMO_devices->cdev, dev, 1);    if(result)    {        printk(KERN_NOTICE "Error %d adding DEMO\n", result);        goto fail;    }    return 0;fail:    DEMO_cleanup_module();    return result;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -