Linux内核共享内存原理
在Linux系统中,每个进程都有独立的虚拟内存空间,也就是说不同的进程访问同一段虚拟内存地址所得到的数据是不一样的,这是因为不同进程相同的虚拟内存地址会映射到不同的物理内存地址上。
但有时候为了让不同进程之间进行通信,需要让不同进程共享相同的物理内存,Linux通过 共享内存 来实现这个功能。下面先来介绍一下Linux系统的共享内存的使用。
1、共享内存使用1.1获取共享内存
要使用共享内存,首先需要使用 shmget() 函数获取共享内存,shmget() 函数的原型如下:
1int shmget(key_t key, size_t size, int shmflg);
参数 key 一般由 ftok() 函数生成,用于标识系统的唯一IPC资源。
参数 size 指定创建的共享内存大小。
参数 shmflg 指定 shmget() 函数的动作,比如传入 IPC_CREAT 表示要创建新的共享内存。
函数调用成功时返回一个新建或已经存在的的共享内存标识符,取决于shmflg的参数。失败返回-1,并设置错误码。
1.2关联共享内存
shmget() 函数返回的是一个标识符 ...
Linux内核内存分区式存储管理
前言分区式存储管理最大的缺点是碎片问题严重,内存利用率低。究其原因,主要在于连续分配的限制,即它要求每个作用在内存中必须占一个连续的分区。
如果允许将一个进程分散地装入到许多不相邻的分区中,便可充分地利用内存,而无需再进行“紧凑”。
基于这一思想,产生了“非连续分配方式”,或者称为“离散分配方式”。
连续分配:为用户进程分配的必须是一个连续的内存空间。
非连续分配:为用户进程分配的可以是一些分散的内存空间。
分页存储管理的思想:把内存分为一个个相等的小分区,再按照分区大小把进程拆分成一个个小部分。
分页存储管理分为:实分页存储管理和虚分页存储管理
1、实分页式存储管理实分页式存储最大的优点是内存利用率高,与目前流行的虚分页存储管理相比,具有实现简单,程序运行快的优点。目前,飞速发展的硬件制造技术使得物理内存越来越大,因此我们认为,实分页式存储管理将是一种最有发展前途的存储管理方式。
1.1基本原理假设一个大型饭店,所有的客房都是标准的双人间,部分客房已经住进客人,现在又有一个旅游团要求入住。接待员统计了一下,对旅游团领队说:“贵团全体成员都能住下,两人一个房间,但是不能住在同一楼层了 ...
Linux内核内存管理系统调用
1、什么是系统调用简单来说,系统调用就是用户程序和硬件设备之间的桥梁。
用户程序在需要的时候,通过系统调用来使用硬件设备。
系统调用的存在,有以下重要的意义:
1)用户程序通过系统调用来使用硬件,而不用关心具体的硬件设备,这样大大简化了用户程序的开发。
比如:用户程序通过write()系统调用就可以将数据写入文件,而不必关心文件是在磁盘上还是软盘上,或者其他存储上。
2)系统调用使得用户程序有更好的可移植性。
只要操作系统提供的系统调用接口相同,用户程序就可在不用修改的情况下,从一个系统迁移到另一个操作系统。
3)系统调用使得内核能更好的管理用户程序,增强了系统的稳定性。
因为系统调用是内核实现的,内核通过系统调用来控制开放什么功能及什么权限给用户程序。
这样可以避免用户程序不正确的使用硬件设备,从而破坏了其他程序。
4)系统调用有效的分离了用户程序和内核的开发。
用户程序只需关心系统调用API,通过这些API来开发自己的应用,不用关心API的具体实现。
内核则只要关心系统调用API的实现,而不必管它们是被如何调用的。
用户程序,系统调用,内核,硬件设备的调用关系如下图:
2、Lin ...
Linux内核异常处理
为什么要学习内核:你对技术追求、大厂面试需求、更好地做应用层开发
内核我们要学习内容:内核管理、进程管理、文件系统、操作系统调用、网络协议栈、虚拟化等等。
1、异常及非屏蔽中断
异常就是CPU内核出现的中断,在CPU执行特定指令时出现非法情况。非屏蔽中断就是计算机内部硬件出错时引起的异常情况。
Intel把非屏蔽中断作为异常的一种来处理。IntelX86处理器发布大约20种异常。每种异常都会由专门的异常处理程序来处理操作,它们通常把一个UNIX信号发送到引起异常的进程。具体异常处理程序发送的信号如下:
2、中断请求初始化分析
由于计算机硬件的限制,很多外部设备不共享中断线,例如,PC配置可以把同一条中断线分配给网卡或图形卡。在Linux系统设计中,专门为每个中断请求IRQ设置一个队列,称为中断请求队列。
中断线、中断请求(IRQ)号及中断向量它们之间关系:中断线是中断请求的一种物理描述,逻辑上对应一个中断请求号(中断号),第n个中断号(IRQn)的缺少中向量是n+32。
3、 IRQ队列数据结构
在256个中断向量中,除32个分配给异常以外,还有224个作为中断向量。对 ...
Linux内核空间内存申请函数kmalloc.、kzalloc、 vmalloc的区别
我们都知道在用户空间动态申请内存用的函数是 malloc(),这个函数在各种操作系统上的使用是一致的,对应的用户空间内存释放函数是 free()。注意:动态申请的内存使用完后必须要释放,否则会造成内存泄漏,如果内存泄漏发生在内核空间,则会造成系统崩溃。
那么,在内核空间中如何申请内存呢?一般我们会用到 kmalloc()、kzalloc()、vmalloc() 等,下面我们介绍一下这些函数的使用以及它们之间的区别。
1、kmalloc()
函数原型:
1void *kmalloc(size_t size, gfp_t flags);
kmalloc() 申请的内存位于物理内存映射区域,而且在物理上也是连续的,它们与真实的物理地址只有一个固定的偏移,因为存在较简单的转换关系,所以对申请的内存大小有限制,不能超过128KB。
较常用的 flags(分配内存的方法):
GFP_ATOMIC —— 分配内存的过程是一个原子过程,分配内存的过程不会被(高优先级进程或中断)打断;
GFP_KERNEL —— 正常分配内存;
GFP_DMA —— 给 DMA 控制器分配内存,需要使用该 ...
一文了解,Linux内存管理,malloc、free 实现原理
malloc / free 简介12void *malloc(size_t size)void free(void *ptr)
malloc 分配指定大小的内存空间,返回一个指向该空间的指针。大小以字节为单位。返回 void* 指针,需要强制类型转换后才能引用其中的值。free 释放一个由 malloc 所分配的内存空间。ptr 指向一个要释放内存的内存块,该指针应当是之前调用 malloc 的返回值。
使用示例:
123int* ptr; ptr = (int*)malloc(10 * sizeof(int)); /* 进行强制类型转换 */ free(ptr);
动态内存分配的系统调用:brk / sbrk动态分配的内存都在堆中,堆从低地址向高地址增长:
Linux 提供了两个系统调用 brk 和 sbrk:
12int brk(void *addr);void *sbrk(intptr_t increment);
brk 用于返回堆的顶部地址;sbrk 用于扩展堆,通过参数 increment 指定要增加的大小,如果扩展成功,返回 brk 的旧值。如果 incre ...
其他工程问题以及调优
其他工程问题以及调优
DMA和cache一致性
内存的cgroup
memcg子系统分析
性能方面的调优: page in/out, swap in/out
Dirty ratio的一些设置
swappiness
DMA和cache一致性
工程中,DMA可以直接在内存和外设进行数据搬移,而CPU访问内存时要经过MMU。DMA访问不到CPU内部的cache,所以会出现cache不一致的问题。因为CPU读写内存时,如果在cache中命中,就不会再访问内存。
当CPU 写memory时,cache有两种算法:write_back ,write_through。一般都采用write_back。cache的硬件,使用LRU算法,把cache中的数据替换到磁盘。
cache一致性问题,主要靠以上两类api来解决这个问题。一致性DMA缓冲区api,和流式DMA映射api。CPU通过MMU访问DMA区域,在页表项中可以配置这片区域是否带cache。
现代的SoC,DMA引擎可以自动维护cache的同步。
内存的cgroup进程分group,内存也分group。
进程调度时,把一 ...
内存与IO的交换
内存与I/O的交换堆、栈、代码段是否常驻内存?本文主要介绍两类不同的页面,以及这两类页面如何在内存和磁盘间进行交换?以及内存和磁盘的颠簸行为- swaping,和硬盘的swap分区。
page cachefile-backed的页面:(有文件背景的页面,比如代码段、比如read/write方法读写的文件、比如mmap读写的文件;他们有对应的硬盘文件,因此如果要交换,可以直接和硬盘对应的文件进行交换),此部分页面进page cache。
匿名页:匿名页,如stack,heap,CoW后的数据段等;他们没有对应的硬盘文件,因此如果要交换,只能交换到虚拟内存-swapfile或者Linux的swap硬盘分区),此部分页面,如果系统内存不充分,可以被swap到swapfile或者硬盘的swap分区。
内核通过两种方式打开硬盘的文件,任何时候打开文件,Linux会申请一个page cache,然后把文件读到page cache里。page cache 是内存针对硬盘的缓存。
Linux读写文件有两种方式:read/write 和 mmap
1)read/ ...
内存的动态申请和释放
内存的动态申请和释放内核空间 和用户空间申请的内存最终和buddy怎么交互?以及在页表映射上的区别?虚拟地址到物理地址,什么时候开始映射?
Buddy的问题分配的粒度太大buddy算法把空闲页面分成1,2,4页,buddy算法会明确知道哪一页内存空闲还是被占用?
4k,8k,16k
无论是在应用还是内核,都需要申请很小的内存。
从buddy要到的内存,会进行slab切割。
slab原理:比如在内核中申请8字节的内存,buddy分配4K,分成很多个小的8个字节,每个都是一个object。
slab,slub,slob 是slab机制的三种不同实现算法。
Linux 会针对一些常规的小的内存申请,数据结构,会做slab申请。
cat /proc/slabinfo 可以看到内核空间小块内存的申请情况,也是slab分配的情况。
:每个slab一共可以分出多少个obj, :还可以分配多少个obj,< pagesperslab>:每个slab对应多少个pages,< objperslab>:每个slab可以分出多少个object,< objsize ...
内存管理之内存映射
一. 前言 本文为内存部分最后一篇,介绍内存映射。内存映射不仅是物理内存和虚拟内存间的映射,也包括将文件中的内容映射到虚拟内存空间。这个时候,访问内存空间就能够访问到文件里面的数据。而仅有物理内存和虚拟内存的映射,是一种特殊情况。本文首先分析用户态在堆中申请小块内存的brk和申请大块内存的mmap,之后会分析内核态的内存映射机制vmalloc,kmap_atomic,swapper_pg_dir以及内核态缺页异常。
二. 用户态内存映射 用户态调用malloc()会分配堆内存空间,而实际上则是完成了一次用户态的内存映射,根据分配空间的大小,内存映射对应的系统调用主要有brk()和mmap()(当然我们也可以直接调用mmap()来映射文件)。对小块内存(小于 128K),C 标准库使用 brk() 来分配,也就是通过移动堆顶的位置来分配内存。这些内存释放后并不会立刻归还系统,而是被缓存起来,这样就可以重复使用。而大块内存(大于 128K),则直接使用内存映射 mmap() 来分配,也就是在文件映射段找一块空闲内存分配出去。这两种方式,自然各有优缺点。
brk() 方式的缓存,可以 ...