mmap

高级必问:Linux 中的零拷贝技术是什么?

南笙酒味 提交于 2020-04-05 22:57:05
作者:卡巴拉的树 https://www.jianshu.com/p/fad3339e3448 正文 本文探讨Linux中 主要的几种零拷贝技术 以及零拷贝技术 适用的场景 。为了迅速建立起零拷贝的概念,我们拿一个常用的场景进行引入: 01 引文 在写一个服务端程序时(Web Server或者文件服务器),文件下载是一个基本功能。这时候服务端的任务是:将服务端主机磁盘中的文件不做修改地从已连接的socket发出去,我们通常用下面的代码完成: while((n = read(diskfd, buf, BUF_SIZE)) > 0) write(sockfd, buf , n); 基本操作就是循环的从磁盘读入文件内容到缓冲区,再将缓冲区的内容发送到socket。但是由于Linux的I/O操作默认是缓冲I/O。这里面主要使用的也就是read和write两个系统调用,我们并不知道操作系统在其中做了什么。实际上在以上I/O操作中,发生了多次的数据拷贝。 当应用程序访问某块数据时,操作系统首先会检查,是不是最近访问过此文件,文件内容是否缓存在内核缓冲区,如果是,操作系统则直接根据read系统调用提供的buf地址,将内核缓冲区的内容拷贝到buf所指定的用户空间缓冲区中去。如果不是,操作系统则首先将磁盘上的数据拷贝的内核缓冲区,这一步目前主要依靠DMA来传输

Linux 15 进程地址空间

大憨熊 提交于 2020-04-02 13:37:34
15.1 进程只能访问有效内存区域的内存地址,每个内存地址都有相关权限可以让相关进程可读、可写、可执行。如果一个内存访问了不在有效范围内的内存区域时,或以不正确的方式访问内存区域,内核会终止该进程。并报段错误。 有效内存中的对象有: -可执行文件代码的内存映射,称为代码段/文本段。 -已初始化的全局或静态变量的内存映射,称为数据段; -未初始化的全局或静态数据的零页映射,称为bss段; -用于进程用户空间栈的零页内存映射,栈段; -每一个诸如C库或动态链接库等共享库的代码段、数据段和bss段也会被载入进程地址空间; -任何内存映射文件; -任何共享内存段; -任何匿名的内存映射,比如由malloc()申请的内存; 其中后4个都是堆区。 15.2 内存描述符 mm_struct 内核使用内存描述符结构体表示进程的地址空间,该结构包含了和进程地址空间有关的全部信息。用mm_struct表示。 其中mm_users成员表示该地址空间的进程引用数; 其中mmap和mm_rb都表示地址空间的各个内存对象,前者用链表表示,后者用红黑树表示; 所有的mm_struct结构体都通过自身的mmlist域连接在一个双向链表中,该链表首元素是init_mm内存描述符,它表示init的地址空间; mmlist_lock用于访问上述链表时的同步控制。 task_struct的mm域指向了进程的内存描述符

洛谷P1119 灾后重建(Floyd)

给你一囗甜甜゛ 提交于 2020-03-28 19:06:09
题目背景 BB B地区在地震过后,所有村庄都造成了一定的损毁,而这场地震却没对公路造成什么影响。但是在村庄重建好之前,所有与未重建完成的村庄的公路均无法通车。换句话说,只有连接着两个重建完成的村庄的公路才能通车,只能到达重建完成的村庄。 题目描述 给出 BB B地区的村庄数 NN N,村庄编号从 00 0到 N−1N-1 N − 1,和所有 MM M条公路的长度,公路是双向的。并给出第 ii i个村庄重建完成的时间 tit_i t i ​ ,你可以认为是同时开始重建并在第 tit_i t i ​ 天重建完成,并且在当天即可通车。若 tit_i t i ​ 为 00 0则说明地震未对此地区造成损坏,一开始就可以通车。之后有 QQ Q个询问 (x,y,t)(x, y, t) ( x , y , t ),对于每个询问你要回答在第 tt t天,从村庄 xx x到村庄y的最短路径长度为多少。如果无法找到从 xx x村庄到 yy y村庄的路径,经过若干个已重建完成的村庄,或者村庄 xx x或村庄 yy y在第t天仍未重建完成 ,则需要返回 −1-1 − 1。 输入格式 第一行包含两个正整数 N,MN,M N , M,表示了村庄的数目与公路的数量。 第二行包含 NN N个非负整数 t0,t1,…,tN−1t_0, t_1,…, t_{N-1} t 0 ​ , t 1 ​ , … , t N −

在下一篇博文,关于mmap的原理框架

两盒软妹~` 提交于 2020-03-20 23:43:41
3 月,跳不动了?>>> 对磁盘上文件的访问,必须将文件按照一定规则整合并搬运到内存中,然后对这个文件访问。将被访问的文件页的顺序被排列成 radix tree. 假设在文件不大,并且没有内存写回而且访问到整个文件时,那么,这个文件页的在逻辑上的线性组织就在内存中 被完整的转化成了一棵树状的排列——radix tree(这棵树很重要)。但实际中的mmap总会与脏页写回与请求调页的存在 mmap原理:将要访问的文件部分,按照大小,权限,在线性区中开辟出一块一模一样的虚拟空间。也就是说访问这个虚拟空间中的一个位置与访问文件中的相同位置是一样的,只不过mmap映射的区域是一块空白,需要请求调页机制来处理。当访问该线性地址对应的页表时,发现页表项为空,那么就要请求调页,讲该页加入基树中,并进行IO,如果该页是私有映射并进程试图写该页,那么就要重新分配一块匿名线性区,并加入到临近或是自己的anov_vma中。并在分配一页,把上次分配的页框内容copy到此页中,把此页加入lru非活动链表中。 来源: oschina 链接: https://my.oschina.net/u/1375613/blog/480501

V4L2驱动的移植与应用(二)

筅森魡賤 提交于 2020-03-15 10:18:09
二、V4L2的应用 下面简单介绍一下V4L2驱动的应用流程。 1、 视频采集的基本流程 一般的,视频采集都有如下流程: 2、 打开视频设备 在V4L2中,视频设备被看做一个文件。使用open函数打开这个设备: // 用非阻塞模式打开摄像头设备 int cameraFd; cameraFd = open("/dev/video0", O_RDWR | O_NONBLOCK, 0); // 如果用阻塞模式打开摄像头设备,上述代码变为: //cameraFd = open("/dev/video0", O_RDWR, 0); 关于阻塞模式和非阻塞模式:应用程序能够使用阻塞模式或非阻塞模式打开视频设备,如果使用非阻塞模式调用视频设备,即使尚未捕获到信息,驱动依旧会把缓存(DQBUFF)里的东西返回给应用程序。 3、 设定属性及采集方式 打开视频设备后,可以设置该视频设备的属性,例如裁剪、缩放等。这一步是可选的。在Linux编程中,一般使用ioctl函数来对设备的I/O通道进行管理: extern int ioctl (int __fd, unsigned long int __request, ...) __THROW; __fd:设备的ID,例如刚才用open函数打开视频通道后返回的cameraFd; __request:具体的命令标志符。 在进行V4L2开发中

ptmalloc2

拟墨画扇 提交于 2020-03-11 08:04:20
本文参考华庭(庄明强)的ptmalloc2 源码剖析 简介: ptmalloc实现了malloc(),free()以及一组其他函数,以提供动态内存管理,同时支持多线程。分配器处于用户空间和内核空间之间,响应用户的分配请求,向操作系统申请内存。总体思想是先“批发”一块大内存,而后“零售”给用户,同时也实现了高效的回收机制。 Main_area / non_main_area(主分配区和非主分配区): 在linux之前版本使用的内存分配机制只有一个主分配区,然而多线程下访问要加锁,所以在ptmalloc中区分出了主分区和非主分区。主分区只有一个,而非主分区可以有多个,分区一旦增加就不会减少。 主分区可以访问heap和memory mapping segment(可调用brk()/sbrk()/mmap()),而非主分区只能访问memory mapping segment(只可以调用mmap())。 chunk组织 ptmalloc通过chunk来管理内存,给User data前存储了一些信息,使用边界标记区分各个chunk。 这个是一个使用中的chunk,返回给用户的指针是上图的mem,在mem上方分别存放了前一个chunk的大小和本chunk的大小,chunk对齐(alignment = 2 ^n; n>=3),对于默认8字节对齐后10个bit为一定为0

Linux内存管理专题

北城以北 提交于 2020-03-07 14:15:08
专题: Linux内存管理专题 关键词: malloc、brk、VMA、VM_LOCK、normal page、special page 。 每章问答: malloc()函数是C函数库封装的一个核心函数,对应的系统调用是brk()。 1. brk实现 要了解brk的实现首先需要知道进程用户空间的划分,以及struct mm_struct结构体中代码段、数据段、堆相关参数。 然后brk也是基于VMA,找到合适的虚拟地址空间,创建新的VMA并插入VMA红黑树和链表中。 首先看看mm_struct中代码段、数据段相关参数,和 Linux内存管理框架图 结合看。 由于栈向低地址空间增长,堆向高地址空间增长,所以栈的起始地址start_stack和堆的结束地址brk会改变。在栈和堆之间是 struct mm_struct { ... unsigned long start_code, end_code, start_data, end_data;-----代码段从start_code到end_code;数据段从start_code到end_code。 unsigned long start_brk, brk, start_stack;--------------------堆从start_brk开始,brk表示堆的结束地址;栈从start_stack开始。 unsigned long arg

Linux内存分配机制

不羁岁月 提交于 2020-03-07 14:07:34
原文:https://blog.csdn.net/gfgdsg/article/details/42709943 Linux 的虚拟内存管理有几个关键概念: 1、每个进程都有独立的虚拟地址空间,进程访问的虚拟地址并不是真正的物理地址; 2、虚拟地址可通过每个进程上的页表(在每个进程的内核虚拟地址空间)与物理地址进行映射,获得真正物理地址; 3、如果虚拟地址对应物理地址不在物理内存中,则产生缺页中断,真正分配物理地址,同时更新进程的页表;如果此时物理内存已耗尽,则根据内存替换算法淘汰部分页面至物理磁盘中。 基于以上认识,进行了如下分析: 一、Linux 虚拟地址空间如何分布? Linux 使用虚拟地址空间,大大增加了进程的寻址空间,由低地址到高地址分别为: 1、只读段:该部分空间只能读,不可写;(包括:代码段、rodata 段(C常量字符串和#define定义的常量) ) 2、数据段:保存全局变量、静态变量的空间; 3、堆 :就是平时所说的动态内存, malloc/new 大部分都来源于此。其中堆顶的位置可通过函数 brk 和 sbrk 进行动态调整。 4、文件映射区域 :如动态库、共享内存等映射物理空间的内存,一般是 mmap 函数所分配的虚拟地址空间。 5、栈:用于维护函数调用的上下文空间,一般为 8M ,可通过 ulimit –s 查看。 6、内核虚拟空间

Linux的内存共享映射(mmap和munmap)

試著忘記壹切 提交于 2020-03-02 19:14:41
Linux下的进程间通信也可以使用mmap的内存共享映射来实现, mmap的作用就是把磁盘文件的一部分直接映射到进程的内存中 ,那么进程就可以直接对该内存文件进行操作, mmap也设置了两种机制:共享和私有 ,如果是共享映射,那么在内存中对文件进行修改,磁盘中对应的文件也会被修改,相反,磁盘中的文件有了修改,内存中的文件也被修改。如果是私有映射,那么内存中的文件是独立的,二者进行修改都不会对对方造成影响。通过这样的内存共享映射就相当于是进程直接对磁盘中的文件进行读写操作一样,那么如果有两个进程来mmap同一个文件,就实现了进程间的通信。磁盘中的文件通过mmap函数来实现映射,然后通过munmap函数取消映射。先来看一下函数的原型: #include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); int munmap(void *addr, size_t length); 其中对于mmap来说,有6个参数,第一个参数是你要映射的起始地址,这里一般用NULL,这样系统会在0地址附近随机分配一块内存。第二个参数是所要映射的文件长度。第三个参数是所映射的文件的权限,其中包含(PROT_EXEC, PROT_READ, PROT_WRITE,

读取二进制文件并遍历每个字节

☆樱花仙子☆ 提交于 2020-03-02 18:59:46
在Python中,如何读取二进制文件并在该文件的每个字节上循环? #1楼 Python 2.4及更早版本 f = open("myfile", "rb") try: byte = f.read(1) while byte != "": # Do stuff with byte. byte = f.read(1) finally: f.close() Python 2.5-2.7 with open("myfile", "rb") as f: byte = f.read(1) while byte != "": # Do stuff with byte. byte = f.read(1) 请注意,with语句在2.5以下的Python版本中不可用。 要在v 2.5中使用它,您需要导入它: from __future__ import with_statement 在2.6中是不需要的。 Python 3 在Python 3中,这有点不同。 我们将不再以字节模式而是字节对象从流中获取原始字符,因此我们需要更改条件: with open("myfile", "rb") as f: byte = f.read(1) while byte != b"": # Do stuff with byte. byte = f.read(1) 或如benhoyt所说,跳过不等于并利用 b""