日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux设备驱动入门----globalmem字符设备驱动

發(fā)布時間:2023/12/9 linux 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux设备驱动入门----globalmem字符设备驱动 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1、什么是globalmem虛擬設備

(1)、globalmem字符設備驅動中,分配一片內(nèi)存大小為GLOBALMEM_SIZE(4K)的空間

(2)、提供對該片內(nèi)存的讀寫、控制和定位函數(shù)

(3)、用戶進程能夠通過linux系統(tǒng)調(diào)用訪問這篇內(nèi)存

[cpp]?view plaincopy
  • #include?<linux/module.h>??
  • #include?<linux/init.h>??
  • #include?<linux/types.h>??
  • #include?<linux/fs.h>??
  • #include?<linux/errno.h>??
  • #include?<linux/mm.h>??
  • #include?<linux/sched.h>??
  • #include?<linux/cdev.h>??
  • #include?<asm/io.h>??
  • #include?<asm/system.h>??
  • #include?<asm/uaccess.h>??
  • ??
  • #define?GLOBALMEM_SIZE?0X1000?/*全局內(nèi)存最大4KB*/??
  • #define?MEM_CLEAR?0x1?/*清零全局內(nèi)存*/??
  • #define?GLOBALMEM_MAJOR?254??/*?預設的globalmem?的主設備號?*/
  • ??
  • static?globalmem_major?=?GLOBALMEM_MAJOR;/*預設的globalmem的主設備號*/??
  • ??
  • /*globalmem的設備結構體:包含了對應于globalmem字符設備的cdev?和?使用內(nèi)存mem[GLOBALMEM_SIZE]*/??
  • struct?globalmem_dev??
  • {??
  • ?struct?cdev?cdev;??//cdev結構體??
  • ?unsigned?char?mem[GLOBALMEM_SIZE);??//全局內(nèi)存??
  • };??
  • ??
  • struct?globalmem_dev?*globalmem_devp;??//設備結構體指針??
  • ??
  • /*文件打開函數(shù)*/??
  • int?globalmem_open(struct?inode?*inode,struct?file?*filp)??
  • {??
  • ?filp->private_data?=?globalmem_devp;?//將設備結構體指針賦值給文件私有數(shù)據(jù)指針??
  • ?return?0??
  • }??
  • ??
  • /*文件釋放函數(shù)*/??
  • int?globalmem_release(struct?inode?*inode,struct?file?*filp)??
  • {??
  • ?return?0;??
  • }??
  • ??
  • /*設備控制函數(shù):ioctl()函數(shù)接受的MEM_CLEAR命令,這個命令將全局內(nèi)存的有效數(shù)據(jù)長度清零,對于設備不支持的命令,ioctl()函數(shù)應該返回-EINVAL*/??
  • static?int?globalmen_ioctl(struct?inode?*inodep,struct?file?*filp,unsigned?int?cmd,unsigned?long?arg)??
  • {??
  • ?struct?globalmen_dev?*dev?=?filp->private_data;?//獲得設備結構體指針??
  • ?switch(cmd)??
  • ?{??
  • ??case??MEE_CLEAR:??
  • ???memset(dev->mem,0,GLOBALMEM_SIZE);??
  • ???printk(KERN_INFO"globalmem?is?set?to?zero\n);??
  • ???break;??
  • ??default:??
  • ???return?-EINVAL;??
  • ?}??
  • ?return?0;??
  • }??
  • ??
  • /*讀函數(shù):讀寫函數(shù)主要是讓設備結構體的mem[]數(shù)組與用戶空間交互數(shù)據(jù),并隨著訪問字節(jié)數(shù)變更返回用戶的文件讀寫偏移位置*/??
  • static?ssizez_t?globalmem_read(struct?file?*filp,char?__user?*buf,size_t?size,loff_t?*opps)??
  • {??
  • ?unsigned?long?p?=?*ppos;??
  • ?unsigned?int?count?=?size;??
  • ?int?ret?=?0;??
  • ?struct?globalmem_dev?*dev?=?filp->private_data;?//獲得設備結構體指針??
  • ???
  • ?if(p?>=?GLOBALMEM_SIZE)??//分析和獲取有效的寫長度??
  • ?{??
  • ??return?count???-ENXIO:0;??
  • ?}??
  • ?if(count?>?GLOBAL_SIZE?-?P)??
  • ?{??
  • ??count?=?GLOBALMEN_SIZE?-?P;??
  • ?}??
  • ???
  • ?if(copy_to_user(buf,(void?*)(dev->mem+p),count))??//內(nèi)核空間->用戶空間??
  • ?{??
  • ??ret?=?-ENAU;T;??
  • ?}??
  • ?else??
  • ?{??
  • ??*oppos?+=?count;??
  • ??ret?=?count;??
  • ??printk(KERN_INFO"read?%d?bytes(s)?from?%d\n",count,p);??
  • ?}??
  • ?return?ret;??
  • }??
  • ??
  • /*寫函數(shù)*/??
  • static?ssize_t?globalmem_write(struct?file?*filp,const?char?__user?*buf,size_t?size,loff_t?*ppos)??
  • {??
  • ?unsigned?long?*p?=?*ppos;??
  • ?unsigned?int?count?=?size;??
  • ?int?ret;??
  • ???
  • ?struct?globalmem_dev?*dev?=?filp->private_data;??
  • ???
  • ?if(p?>=?CLOBALMEM_SIZE)??//分析和獲取有效的寫長度??
  • ?{??
  • ??return?count??-ENXIO:0;??
  • ?}??
  • ???
  • ?if(count?>?GLOBALMEN_SIZE?-?P)??//?要寫的字節(jié)數(shù)太多?
  • ?{??
  • ??count?=?CLOBALMEN_SIZE?-?P;??
  • ?}??
  • ???
  • ?if(copy_from_user(dev->mem?+?p,buf,count))?//?用戶空間->內(nèi)核空間??
  • ?{??
  • ??ret?=?-ENAULT;??
  • ?}??
  • ?else??
  • ?{??
  • ??*ppos?=+?count;??
  • ??ret?=?count;??
  • ??printk(KERN_INFO"written?%d?bytes(s)?from?%d\n",count,p);??
  • ?}??
  • ?return?ret;??
  • }??
  • ??
  • /*seek文件定位函數(shù):seek()函數(shù)對文件定位的起始地址可以是文件開頭(SEEK_SET,0)、當前位置(SEEK_CUR,1)、文件尾(SEEK_END,2)*/??
  • static?loff_t?globalmem_llseek(struct?file?*filp,loff_t?offset,int?orig)??
  • {??
  • ?loff_t?ret?=?0;??
  • ?switch(orig)??
  • ?{??
  • ??case?0:???//相對文件開始位置偏移??
  • ???if(offset?<0?)??
  • ???{??
  • ????ret?=?-EINVAL;??
  • ????break;??
  • ???}??
  • ?????
  • ???if((unsigned?int?)offset?>?GLOBALMEM_SIZE)??
  • ???{??
  • ????ret?=?-?EINVAL;??
  • ????break;??
  • ???}??
  • ???filp->f_ops?=?(unsigned?int)offset;??
  • ???ret?=?filp->f_pos;??
  • ???break;??
  • ?????
  • ??case?1:???//相對文件當前位置偏移??
  • ???if((filp->f_ops?+?offset)?>?GLOBALMEMSIZE)??
  • ???{??
  • ????ret?=?-EINVAL;??
  • ????break;??
  • ???}??
  • ???if((filp->f_ops?+?offset)<0)??
  • ???{??
  • ????ret?=?-ENVAL;??
  • ????break;??
  • ???}??
  • ???filp->f_ops?+=offset;??
  • ???ret?=?filp->f_ops;??
  • ???break;??
  • ??default:??
  • ???ret?=?-EINVAL;??
  • ???break;???
  • ?}??
  • ?return?ret;??
  • }??
  • ??
  • /*文件操作結構體*/??
  • static?const?struct?file_operations?globalmem_fops=??
  • {??
  • ?.owner?=?THIS_MODULE;??
  • ?.llseek?=?globalmem_llseek;??
  • ?.read?=?globalmem_read;??
  • ?.write?=?globalmem_write;??
  • ?.ioctl?=?globalmem_ioctl;??
  • ?.open?=?globalmem_open;??
  • ?.release?=?globalmem_release;??
  • };??
  • ??
  • /*初始化并注冊cdev*/??
  • static?void?globalmem_setup_cdev(struct?globalmem_dev?*dev,int?index)??
  • {??
  • ?int?err,devno?=?MKDEV(globalmen_major,index);??
  • ?cdev_init(&dev->cdev,&globalmem_fops);??
  • ?dev->cdev.owner?=?THIS_MOUDEL;??
  • ?dev->cdev.ops?=?&golbalmem_fops;??
  • ?err?=?cdev_add(&dev->cdev,devno,1);??
  • ?if(err)??
  • ?{??
  • ??printk(KERN_NOTICE"Error?%d?adding?LED%d",err,index);??
  • ?}??
  • ???
  • }??
  • ??
  • /*設備驅動模塊加載函數(shù)*/??
  • static?int?__init?globalmem_init(void)??
  • {??
  • ?int?result;??
  • ?dev_t?devno?=?MKDEV(globalmem_major,0);??
  • ???
  • ?if(globalmem_major)?//申請設備號??
  • ?{??
  • ??result?=?register_chrdev-region(devno,1,"globalmem");??
  • ?}??
  • ?else??//動態(tài)申請設備號??
  • ?{??
  • ??result?=?alloc_chrdev_region(&devno,0,1,"globalmem");??
  • ??globalmem_major?=?MAJOR(devno);??
  • ?}??
  • ???
  • ?if(result?<?0)??
  • ?{??
  • ??return?result;??
  • ?}??
  • ???
  • ?globalmem_devp?=?kmalloc(sizeof(struct?globalmem_dev),GFP_KERNEL);?//申請設備結構體的內(nèi)存??
  • ?if(!globalmem_devp)??
  • ?{??
  • ??result?=?-ENOMEM;??
  • ??goto?fail_malloc;??
  • ?}??
  • ???
  • ?memset(globalmem_devp,0,sizeof(struct?globalmem_dev));??
  • ?globalmem_setup_cdev(globalmem_devp,0);??
  • ?return?0;??
  • ???
  • ?fail_malloc:unregister_chrdev_region(devno,1);??
  • ?return?result;??
  • }??
  • ??
  • /*模塊卸載函數(shù)*/??
  • void?__eixt?globalmem_exit(void)??
  • {??
  • ?cdev_del(&globalmem_devp->cdev);?//注銷cdev??
  • ?kfree(globalmem_devp);??????????//釋放設備結構體內(nèi)存??
  • ?unregister_chrdev_region(MKDEV(globalmem_major,0),1);?//釋放設備號??
  • }??
  • ??
  • MODULE_AUTHOR("NOODLE");??
  • MODULE_LICENSE("GPL");??
  • ??
  • mdule_param(globalmem_major,int,S_IRUGO);??
  • ??
  • module_init(globalmem_init);??
  • module_exit(globalmem_exit); ??
  • 總結

    以上是生活随笔為你收集整理的Linux设备驱动入门----globalmem字符设备驱动的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。