热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

字符设备驱动程序学习笔记三

memdev.h文件示例代码如下:#ifndef_MEMDEV_H#define_MEMDEV_H采用静态分配设备号#ifndefMEMDEV_MAJOR#defin





memdev.h文件示例代码如下:
  #ifndef _MEMDEV_H
#define _MEMDEV_H


//采用静态分配设备号
#ifndef MEMDEV_MAJOR
#define MEMDEV_MAJOR 260
#endif


#ifndef MEMDEV_NR_DEVS
#define MEMDEV_NR_DEVS 2
#endif


#ifndef MEMEV_SIZE
#define MEMDEV_SIZE 4096
#endif


struct mem_dev{
        char *data;
        unsigned long size;
};


#endif




memdev.c文件示例代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include


#include "memdev.h"


MODULE_LICENSE("GPL");
MODULE_AUTHOR("Retacn Yue");
MODULE_DESCRIPTION("memdev module");
MODULE_ALIAS("memdev module");


static int mem_major=MEMDEV_MAJOR;
module_param(mem_major,int,S_IRUGO);


struct mem_dev *mem_devp;
struct cdev cdev;


/*初始化*/
int mem_open(struct inode *inode,struct file *filp){
        struct mem_dev *dev;
        int num=MINOR(inode->i_rdev);


        if(num>MEMDEV_NR_DEVS){
                return -ENODEV;
        }
        dev=&mem_devp[num];
        filp->private_data=dev;
        return 0;
}


/*关闭释主资源*/
int mem_release(struct inode *inode,struct file *flip){
        return 0;
}


/*从字符设备读取数据*/
static ssize_t mem_read(struct file *filp,char __user *buff,size_t 


size,loff_t *poss){
        unsigned long p=*poss;
        unsigned int count=size;
        int ret=0;
        struct mem_dev *dev=filp->private_data;


        if(p>=MEMDEV_SIZE)
                return 0;
        if(count>MEMDEV_SIZE-p)
                count=MEMDEV_SIZE-p;
        if(copy_to_user(buff,(void*)(dev->data+p),count)){
                ret=-EFAULT;
        }else{
                *poss+=count;
                ret=count;
                printk(KERN_INFO "read %d bytes form %lu\n",count,p);
        }
     return 0;
}
/*向字符设备发送数据*/
static ssize_t mem_write(struct file *filp,const char __user 


*buf,size_t size,loff_t *poss){
        unsigned long p=*poss;
        unsigned int count=size;
        int ret=0;
        struct mem_dev *dev=filp->private_data;


        if(p>=MEMDEV_SIZE)
                return 0;
        if(count>MEMDEV_SIZE-p)
                count=MEMDEV_SIZE-p;
        if(copy_from_user(dev->data+p,buf,count)){
                ret=-EFAULT;
        }else{
                *poss+=count;
                ret=count;
                printk(KERN_INFO "write %d bytes from %lu\n",count,p);
        }
      return 0;
}
/*修改文件当前读写位置*/
static loff_t mem_llseek(struct file *filp,loff_t offset, int whence){
        loff_t newpos;


        switch(whence){
                case 0:
                        newpos=offset;
                        break;
                case 1:
                        newpos=filp->f_pos+offset;
                        break;
                case 2:
                        newpos=MEMDEV_SIZE-1+offset;
                        break;
                default:
                        return -EINVAL;
        }
        if((newpos<0)||(newpos>MEMDEV_SIZE))
                return -EINVAL;


        filp->f_pos&#61;newpos;
      return 0;
}
/*应用程序在设备上调用的所有操作*/
static const struct file_operations mem_fops&#61;{
        .owner&#61;THIS_MODULE,
        .llseek&#61;mem_llseek,
        .read&#61;mem_read,
        .write&#61;mem_write,
        .open&#61;mem_open,
        .release&#61;mem_release
};


/*初始化方法 &#xff1a;分配设备号
               字符设备注册
*/
static int memdev_init(void){
        int result;
        int i;
        dev_t devno&#61;MKDEV(mem_major,0);


        /*静态分配*/
        if(mem_major){
                result&#61;register_chrdev_region(devno,2,"memdev");
        }
        /*动态分配*/
        else{
                result&#61;alloc_chrdev_region(&devno,0,2,"memdev");
                mem_major&#61;MAJOR(devno);
        }
 if(result<0)
                return result;


        /*初始化*/
        cdev_init(&cdev,&mem_fops);
        cdev.owner&#61;THIS_MODULE;
        cdev.ops&#61;&mem_fops;


/*添加设备文件*/
        cdev_add(&cdev,MKDEV(mem_major,0),MEMDEV_NR_DEVS);


        mem_devp&#61;kmalloc(MEMDEV_NR_DEVS * sizeof(struct 


mem_dev),GFP_KERNEL);
        if(!mem_devp){
                result&#61;-ENOMEM;
                goto fail_malloc;
        }
        memset(mem_devp,0,MEMDEV_NR_DEVS * sizeof(struct mem_dev));


        for(i&#61;0;i                 mem_devp[i].size&#61;MEMDEV_SIZE;
                mem_devp[i].data&#61;kmalloc(MEMDEV_SIZE,GFP_KERNEL);
                memset(mem_devp[i].data,0,MEMDEV_SIZE);
        }
        return 0;
fail_malloc:
        unregister_chrdev_region(devno,2);
        return result;
}
static void memdev_exit(void){
        cdev_del(&cdev);
        kfree(mem_devp);
        unregister_chrdev_region(MKDEV(mem_major,0),2);
}




module_init(memdev_init);
module_exit(memdev_exit);




makefile文件示例代码如下&#xff1a;
ifneq ($(KERNELRELEASE),)
obj-m:&#61;memdev.o
else
KERNELDIR:&#61;/opt/FriendlyARM/mini6410/linux/linux-2.6.38
PWD:&#61;$(shell pwd)
all:
        make -C $(KERNELDIR) M&#61;$(PWD) modules ARCH&#61;arm 


CROSS_COMPILE&#61;arm-linux-
clean:
        rm -fr *.ko *.o *.mod.c *mod.o *.symvers
endif


编译&#xff1a;make 
生成memdev.ko文件下载到开发板/lib/modules/
加载模块
[root&#64;FriendlyARM modules]# lnsmod memdev.ko
查看设备节点
[root&#64;FriendlyARM modules]# cat /proc/devices
创建设备文件
[root&#64;FriendlyARM modules]# cd /dev
[root&#64;FriendlyARM dev]# mknod memdev0 c 260 0
  








测试字符设备驱动


示例代码如下&#xff1a;
/*测试字符设备驱动*/
int main(){
        int fd;
        char buf[4096];


        strcpy(buf,"this is  a example of charactar devices driver");
        printf("buf:%s\n",buf);


        fd&#61;open("/dev/memdev0",O_RDWR);
        if(fd&#61;&#61;-1){
                printf("open memdev failed!\n");
                return -1;
        }


        write(fd,buf,sizeof(buf));
        lseek(fd,0,SEEK_SET);
        strcpy(buf,"nothing");
        read(fd,buf,sizeof(buf));
        printf("buf:%s\n",buf);


        return 0;
}


编译&#xff1a;
[root&#64;localhost memdev]# arm-linux-gcc -o memdevapp memdevapp.c
将生成的memdevapp下载到开发板&#xff0c;运行应用程序
[root&#64;FriendlyARM plg]# ./memdev/app 
运行结果如下&#xff1a;
[root&#64;FriendlyARM plg]# ./memdevapp 
buf:this is  a example of charactar devices driverwrite 4096 bytes from 


0
read 4096 bytes form 0


buf:this is  a example of charactar devices driver


转载于:https://www.cnblogs.com/retacn-yue/archive/2013/04/04/3263123.html



推荐阅读
  • 本文详细解析了 MySQL 5.7.20 版本中二进制日志(binlog)崩溃恢复机制的工作流程。假设使用 InnoDB 存储引擎,并且启用了 `sync_binlog=1` 配置,文章深入探讨了在系统崩溃后如何通过 binlog 进行数据恢复,确保数据的一致性和完整性。 ... [详细]
  • 本书详细介绍了在最新Linux 4.0内核环境下进行Java与Linux设备驱动开发的全面指南。内容涵盖设备驱动的基本概念、开发环境的搭建、操作系统对设备驱动的影响以及具体开发步骤和技巧。通过丰富的实例和深入的技术解析,帮助读者掌握设备驱动开发的核心技术和最佳实践。 ... [详细]
  • POJ 1696: 空间蚂蚁算法优化与分析
    针对 POJ 1696 的空间蚂蚁算法进行了深入的优化与分析。本研究通过改进算法的时间复杂度和空间复杂度,显著提升了算法的效率。实验结果表明,优化后的算法在处理大规模数据时表现优异,能够有效减少计算时间和内存消耗。此外,我们还对算法的收敛性和稳定性进行了详细探讨,为实际应用提供了可靠的理论支持。 ... [详细]
  • 深入解析十大经典排序算法:动画演示、原理分析与代码实现
    本文深入探讨了十种经典的排序算法,不仅通过动画直观展示了每种算法的运行过程,还详细解析了其背后的原理与机制,并提供了相应的代码实现,帮助读者全面理解和掌握这些算法的核心要点。 ... [详细]
  • 如何使用 net.sf.extjwnl.data.Word 类及其代码示例详解 ... [详细]
  • Prim算法在处理稠密图时表现出色,尤其适用于边数远多于顶点数的情形。传统实现的时间复杂度为 \(O(n^2)\),但通过引入优先队列进行优化,可以在点数为 \(m\)、边数为 \(n\) 的情况下显著降低时间复杂度,提高算法效率。这种优化方法不仅能够加速最小生成树的构建过程,还能在大规模数据集上保持良好的性能表现。 ... [详细]
  • BZOJ4240 Gym 102082G:贪心算法与树状数组的综合应用
    BZOJ4240 Gym 102082G 题目 "有趣的家庭菜园" 结合了贪心算法和树状数组的应用,旨在解决在有限时间和内存限制下高效处理复杂数据结构的问题。通过巧妙地运用贪心策略和树状数组,该题目能够在 10 秒的时间限制和 256MB 的内存限制内,有效处理大量输入数据,实现高性能的解决方案。提交次数为 756 次,成功解决次数为 349 次,体现了该题目的挑战性和实际应用价值。 ... [详细]
  • 本文作为“实现简易版Spring系列”的第五篇,继前文深入探讨了Spring框架的核心技术之一——控制反转(IoC)之后,将重点转向另一个关键技术——面向切面编程(AOP)。对于使用Spring框架进行开发的开发者来说,AOP是一个不可或缺的概念。了解AOP的背景及其基本原理,对于掌握这一技术至关重要。本文将通过具体示例,详细解析AOP的实现机制,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 在Unity中进行3D建模的全面指南,详细介绍了市场上三种主要的3D建模工具:Blender 3D、Maya和3ds Max。每种工具的特点、优势及其在Unity开发中的应用将被深入探讨,帮助开发者选择最适合自己的建模软件。 ... [详细]
  • 本文深入探讨了 MXOTDLL.dll 在 C# 环境中的应用与优化策略。针对近期公司从某生物技术供应商采购的指纹识别设备,该设备提供的 DLL 文件是用 C 语言编写的。为了更好地集成到现有的 C# 系统中,我们对原生的 C 语言 DLL 进行了封装,并利用 C# 的互操作性功能实现了高效调用。此外,文章还详细分析了在实际应用中可能遇到的性能瓶颈,并提出了一系列优化措施,以确保系统的稳定性和高效运行。 ... [详细]
  • 在稀疏直接法视觉里程计中,通过优化特征点并采用基于光度误差最小化的灰度图像线性插值技术,提高了定位精度。该方法通过对空间点的非齐次和齐次表示进行处理,利用RGB-D传感器获取的3D坐标信息,在两帧图像之间实现精确匹配,有效减少了光度误差,提升了系统的鲁棒性和稳定性。 ... [详细]
  • Go语言实现Redis客户端与服务器的交互机制深入解析
    在前文对Godis v1.0版本的基础功能进行了详细介绍后,本文将重点探讨如何实现客户端与服务器之间的交互机制。通过具体代码实现,使客户端与服务器能够顺利通信,赋予项目实际运行的能力。本文将详细解析Go语言在实现这一过程中的关键技术和实现细节,帮助读者深入了解Redis客户端与服务器的交互原理。 ... [详细]
  • 本文介绍了一种简化版的在线购物车系统,重点探讨了用户登录和购物流程的设计与实现。该系统通过优化界面交互和后端逻辑,提升了用户体验和操作便捷性。具体实现了用户注册、登录验证、商品浏览、加入购物车以及订单提交等功能,旨在为用户提供高效、流畅的购物体验。 ... [详细]
  • 题目《UVa 11978 福岛核爆问题》涉及圆与多边形交集面积的计算及二分法的应用。该问题的核心在于通过精确的几何运算与高效的算法实现来解决复杂图形的面积计算。在实现过程中,特别需要注意的是对多边形顶点的平移处理,确保所有顶点包括最后一个顶点 \( p[n] \) 都经过正确的位移,以避免因细节疏忽导致的错误。此外,使用循环次数为50次的二分法能够有效提高算法的精度和稳定性。 ... [详细]
  • 优化后的标题:校园互联新方案:10397连接教育未来 ... [详细]
author-avatar
支着儿traister_107
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有