当前位置: 首页 > news >正文

江西网站备案要求新乐网站制作价格

江西网站备案要求,新乐网站制作价格,微信推广引流加精准客户,西安 房产网站建设mmap在linux哪里#xff1f; 什么是mmap#xff1f; 上图说了#xff0c;mmap是操作这些设备的一种方法#xff0c;所谓操作设备#xff0c;比如IO端口#xff08;点亮一个LED#xff09;、LCD控制器、磁盘控制器#xff0c;实际上就是往设备的物理地址读写数据。 但…mmap在linux哪里 什么是mmap 上图说了mmap是操作这些设备的一种方法所谓操作设备比如IO端口点亮一个LED、LCD控制器、磁盘控制器实际上就是往设备的物理地址读写数据。 但是由于应用程序不能直接操作设备硬件地址所以操作系统提供了这样的一种机制——内存映射把设备地址映射到进程虚拟地址mmap就是实现内存映射的接口。 操作设备还有很多方法如ioctl、ioremap mmap的好处是mmap把设备内存映射到虚拟内存则用户操作虚拟内存相当于直接操作设备了省去了用户空间到内核空间的复制过程相对IO操作来说增加了数据的吞吐量。 什么是内存映射 既然mmap是实现内存映射的接口那么内存映射是什么呢看下图 每个进程都有独立的进程地址空间通过页表和MMU可将虚拟地址转换为物理地址每个进程都有独立的页表数据这可解释为什么两个不同进程相同的虚拟地址却对应不同的物理地址。 什么是虚拟地址空间 每个进程都有4G的虚拟地址空间其中3G用户空间1G内核空间linux每个进程共享内核空间独立的用户空间下图形象地表达了这点 驱动程序运行在内核空间所以驱动程序是面向所有进程的。 用户空间切换到内核空间有两种方法 1系统调用即软中断 2硬件中断 虚拟地址空间里面是什么 了解了什么是虚拟地址空间那么虚拟地址空间里面装的是什么看下图 虚拟空间装的大概是上面那些数据了内存映射大概就是把设备地址映射到上图的红色段了暂且称其为“内存映射段”至于映射到哪个地址是由操作系统分配的操作系统会把进程空间划分为三个部分 1未分配的即进程还未使用的地址 2缓存的缓存在ram中的页 3未缓存的没有缓存在ram中 操作系统会在未分配的地址空间分配一段虚拟地址用来和设备地址建立映射至于怎么建立映射后面再揭晓。 现在大概明白了“内存映射”是什么了那么内核是怎么管理这些地址空间的呢任何复杂的理论最终也是通过各种数据结构体现出来的而这里这个数据结构就是进程描述符。从内核看进程是分配系统资源CPU、内存的载体为了管理进程内核必须对每个进程所做的事情进行清楚的描述这就是进程描述符内核用task_struct结构体来表示进程并且维护一个该结构体链表来管理所有进程。该结构体包含一些进程状态、调度信息等上千个成员我们这里主要关注进程描述符里面的内存描述符struct mm_struct mm 相关视频推荐 90分钟搞懂Linux内核MMU机制 Linux内核源码之地址映射机制 剖析Linux内核设备驱动程序 免费学习地址Linux C/C开发后端/音视频/游戏/嵌入式/高性能网络/存储/基础架构/安全 需要C/C Linux服务器架构师学习资料加qun579733396获取资料包括C/CLinuxgolang技术NginxZeroMQMySQLRedisfastdfsMongoDBZK流媒体CDNP2PK8SDockerTCP/IP协程DPDKffmpeg等免费分享 内存描述符 具体的结构请参考下图 现在已经知道了内存映射是把设备地址映射到进程空间地址注意并不是所有内存映射都是映射到进程地址空间的ioremap是映射到内核虚拟空间的mmap是映射到进程虚拟地址的实质上是分配了一个vm_area_struct结构体加入到进程的地址空间也就是说把设备地址映射到这个结构体映射过程就是驱动程序要做的事了。 内存映射的实现 以字符设备驱动为例一般对字符设备的操作都如下框图 而内存映射的主要任务就是实现内核空间中的mmap()函数先来了解一下字符设备驱动程序的框架 以下是mmap_driver.c的源代码 //所有的模块代码都包含下面两个头文件 #include linux/module.h #include linux/init.h #include linux/types.h //定义dev_t类型 #include linux/cdev.h //定义struct cdev结构体及相关操作 #include linux/slab.h //定义kmalloc接口 #include asm/io.h//定义virt_to_phys接口 #include linux/mm.h//remap_pfn_range #include linux/fs.h #define MAJOR_NUM 990 #define MM_SIZE 4096 static char driver_name[] mmap_driver1;//驱动模块名字 static int dev_major MAJOR_NUM; static int dev_minor 0; char *buf NULL; struct cdev *cdev NULL; static int device_open(struct inode *inode, struct file *file) { printk(KERN_ALERTdevice open\n); buf (char *)kmalloc(MM_SIZE, GFP_KERNEL);//内核申请内存只能按页申请申请该内存以便后面把它当作虚拟设备 return 0; } static int device_close(struct inode *indoe, struct file *file) { printk(device close\n); if(buf) { kfree(buf); } return 0; } static int device_mmap(struct file *file, struct vm_area_struct *vma) { vma-vm_flags | VM_IO;//表示对设备IO空间的映射 vma-vm_flags | VM_RESERVED;//标志该内存区不能被换出在设备驱动中虚拟页和物理页的关系应该是长期的应该保留起来不能随便被别的虚拟页换出 if(remap_pfn_range(vma,//虚拟内存区域即设备地址将要映射到这里 vma-vm_start,//虚拟空间的起始地址 virt_to_phys(buf)PAGE_SHIFT,//与物理内存对应的页帧号物理地址右移12位 vma-vm_end - vma-vm_start,//映射区域大小一般是页大小的整数倍 vma-vm_page_prot))//保护属性 { return -EAGAIN; } return 0; } static struct file_operations device_fops { .owner THIS_MODULE, .open device_open, .release device_close, .mmap device_mmap, }; static int __init char_device_init( void ) { int result; dev_t dev;//高12位表示主设备号低20位表示次设备号 printk(KERN_ALERTmodule init2323\n); printk(dev%d, dev); dev MKDEV(dev_major, dev_minor); cdev cdev_alloc();//为字符设备cdev分配空间 printk(KERN_ALERTmodule init\n); if(dev_major) { result register_chrdev_region(dev, 1, driver_name);//静态分配设备号 printk(result %d\n, result); } else { result alloc_chrdev_region(dev, 0, 1, driver_name);//动态分配设备号 dev_major MAJOR(dev); } if(result 0) { printk(KERN_WARNINGCantt get major %d\n, dev_major); return result; } cdev_init(cdev, device_fops);//初始化字符设备cdev cdev-ops device_fops; cdev-owner THIS_MODULE; result cdev_add(cdev, dev, 1);//向内核注册字符设备 printk(dffd %d\n, result); return 0; } static void __exit char_device_exit( void ) { printk(KERN_ALERTmodule exit\n); cdev_del(cdev); unregister_chrdev_region(MKDEV(dev_major, dev_minor), 1); } module_init(char_device_init);//模块加载 module_exit(char_device_exit);//模块退出 MODULE_LICENSE(GPL); MODULE_AUTHOR(ChenShengfa); 下面是测试代码test_mmap.c #include stdio.h #include fcntl.h #include sys/mman.h #include stdlib.h #include string.h int main( void ) { int fd; char *buffer; char *mapBuf; fd open(/dev/mmap_driver, O_RDWR);//打开设备文件内核就能获取设备文件的索引节点填充inode结构 if(fd0) { printf(open device is error,fd %d\n,fd); return -1; } /*测试一查看内存映射段*/ printf(before mmap\n); sleep(15);//睡眠15秒查看映射前的内存图cat /proc/pid/maps buffer (char *)malloc(1024); memset(buffer, 0, 1024); mapBuf mmap(NULL, 1024, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);//内存映射会调用驱动的mmap函数 printf(after mmap\n); sleep(15);//睡眠15秒在命令行查看映射后的内存图如果多出了映射段说明映射成功 /*测试二往映射段读写数据看是否成功*/ strcpy(mapBuf, Driver Test);//向映射段写数据 memset(buffer, 0, 1024); strcpy(buffer, mapBuf);//从映射段读取数据 printf(buf %s\n, buffer);//如果读取出来的数据和写入的数据一致说明映射段的确成功了 munmap(mapBuf, 1024);//去除映射 free(buffer); close(fd);//关闭文件最终调用驱动的close return 0; } 下面是makefile文件 ifneq ($(KERNELRELEASE),) obj-m : mmap_driver.o else KDIR : /lib/modules/3.2.0-52-generic/build all: make -C $(KDIR) M$(PWD) modules clean: rm -f *.ko *.o *.mod.o *.mod.c *~ *.symvers *.order endif 下面命令演示一下驱动程序的编译、安装、测试过程注其他用户在mknod之后还需要chmod改变权限 # make //编译驱动# insmod mmap_driver.ko //安装驱动# mknod /dev/mmap_driver c 999 0 //创建设备文件# gcc test_mmap.c -o test.o //编译应用程序# ./test.o //运行应用程序来测试驱动程序 拓展 关于这个过程涉及一些术语 1设备文件linux中对硬件虚拟成设备文件对普通文件的各种操作均适用于设备文件 2索引节点linux使用索引节点来记录文件信息如文件长度、创建修改时间它存储在磁盘中读入内存后就是一个inode结构体文件系统维护了一个索引节点的数组每个元素都和文件或者目录一一对应。 3主设备号如上面的999表示设备的类型比如该设备是lcd还是usb等 4次设备号如上面的0表示该类设备上的不同设备 5文件普通文件或设备文件的三个结构 ①文件操作struct file_operations ②文件对象struct file ③文件索引节点struct inode 关于驱动程序中内存映射的实现先了解一下open和close的流程 1设备驱动open流程 ①应用程序调用open(/dev/mmap_driver, O_RDWR); ②Open就会通过VFS找到该设备的索引节点inodemknod的时候会根据设备号把驱动程序的file_operations结构填充到索引节点中关于mknod /dev/mmap_driver c 999 0这条指令创建了设备文件在安装驱动insmod的时候会运行驱动程序的初始化程序module_init在初始化程序中会注册它的主设备号到系统中cdev_add如果mknod时的主设备号999在系统中不存在即和注册的主设备号不同则上面的指令会执行失败就创建不了设备文件 ③然后根据设备文件的索引节点中的file_operations中的open指针就调用驱动的open方法了。 ④生成一个文件对象files_struct结构系统维护一个files_struct的链表表示系统中所有打开的文件 ⑤返回文件描述符fd把fd加入到进程的文件描述符表中 2设备驱动close流程 应用程序调用close(fd)最终可调用驱动的close为什么根据一个简单的int型fd就可以找到驱动的close函数这就和上面说的三个结构struct file_operations、struct file、struct inode息息相关了假如fd 3 3设备驱动mmap流程 由open和close得知同理应用程序调用mmap最终也会调用到驱动程序中mmap方法 ①应用程序test.mmap.c中mmap函数 void* mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); addr映射后虚拟地址的起始地址通常为NULL内核自动分配 length映射区的大小 prot页面访问权限PROT_READ、PROT_WRITE、PROT_EXEC、PROT_NONE flags参考网络资料 fd文件描述符 offset文件映射开始偏移量 ②驱动程序的mmap_driver.c中mmap函数 上面说了mmap的主要工作是把设备地址映射到进程虚拟地址也即是一个vm_area_struct的结构体这里说的映射是一个很悬的东西那它在程序中的表现是什么呢——页表没错就是页表映射就是要建立页表。进程地址空间就可以通过页表软件和MMU硬件映射到设备地址上了 添加图片注释不超过 140 字可选 virt_to_phys(buf)buf是在open时申请的地址这里使用virt_to_phys把buf转换成物理地址是模拟了一个硬件设备即把虚拟设备映射到虚拟地址在实际中可以直接使用物理地址。 总结 ①从以上看到内核各个模块错综复杂、相互交叉 ②单纯一个小小驱动模块就涉及了进程管理进程地址空间、内存管理页表与页帧映射、虚拟文件系统structfile、structinode ③并不是所有设备驱动都可以使用mmap来映射比如像串口和其他面向流的设备并且必须按照页大小进行映射。
http://www.zqtcl.cn/news/57651/

相关文章:

  • 造纸公司网站建设点广告挣钱网站有哪些
  • 郑州北环网站建设培训左右悬停代码网站
  • 西安知名的集团门户网站建设公司三个关键词介绍自己
  • 外贸站seo运城网站建设哪个好
  • wix建设网站教程郑州英语网站建设
  • 域名申请好怎么做网站甘肃肃第八建设集团网站
  • 免费网站建设软件有哪些网站功能报价
  • 手机网站架构海口企业做网站设计
  • 单个页面的网站企业网站运营推广难做吗
  • 建设网站要服务器吗网站运营与管理的内容有哪些
  • 怎么把代码添加网站服务器租用哪家好
  • 移动互联网 传统网站做网站阿里云买哪个服务器好点
  • 聚商网络营销公司服务内容seo快速排名是什么
  • 网站开发需要什么专业知识门户网站开发平台
  • 做网站抬头网页设计欣赏怎么做
  • 做动画 的 网站企业简介怎么写吸引人
  • 响应式机械类网站市场营销课程
  • WordPress建站主机推荐网络营销的基本职能有哪些
  • 山西建设厅官方网站网站策划与建设阶段的推广的目标
  • 株洲市建设局官方网站制作动画的软件
  • 设计好用的网站恋家网邯郸房产
  • 摄影网站介绍曲靖做网站价格
  • 网站建设首选银川网站建设多少钱
  • 动漫网站设计报告新手wordpress添加注册表
  • 余姚做百度网站建设推广app软件
  • 网站建设是什么岗位网站设计策划方案
  • c h5网站开发开发一款彩票app需要多少钱
  • WordPress全站展示torrent种子搜索引擎
  • 有了云服务器怎么做网站飞浪网站建设
  • 京东网站建设策略做企业内部管理网站要多久