精华内容
下载资源
问答
  • linux内核内存分配的方法 用户变量:用户空间定义的变量,地址为前3G 内核变量:内核空间定义的变量,地址为后1G1.1 kmalloc / kfree void *kmalloc(size_t size, gfp_t flags) 函数功能: 1.内核空间分配内存; 2....

    linux内核内存分配的方法

    用户变量:用户空间定义的变量,地址为前3G
    内核变量:内核空间定义的变量,地址为后1G

    1.1 kmalloc / kfree

    void *kmalloc(size_t size, gfp_t flags)
    函数功能:
    1.内核空间分配内存;
    2.从内核1G的直接内存映射区中分配内存
    3.物理地址和虚拟地址都是连续的(一一映射)

    参数:
    size:要分配内存的大小
    最小为32字节
    最大4M (2.6.20之前内核最大128K)
    flags:指定分配内存时的行为
    GFP_KERNEL:告知内核,请努力把内存分配成功,如果内存不足,会进行休眠操作,
    等待空闲内存出现,不能用于中断上下文。

    GFP_ATOMIC:如果内存不足,不会进行休眠操作,可以用于中断上下文;
    返回值:保存分配的虚拟内存的首地址
    例如:
    void *addr;
    addr = kmalloc (0x100000, GFP_KERNEL);


    void kfree(void *addr);
    功能:释放内存
    addr:分配的内存的首地址

    1.2__get_free_pages/free_pages
    明确:linux系统,一页为4K

    unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
    函数功能:
    1.内核空间分配内存
    2.从直接内存映射区分配内存
    3.物理内存和虚拟内存都连续
    4.大小范围:
    最小为1页;
    最大为4M;
    参数:
    gfp_mask:指定分配内存时的行为
    GFP_KERNEL:
    告知内核,请努力把内存分配成功,如果内存不足,会进行休眠操作,等待空闲内存出现,不能用于中断上下文
    GFP_ATOMIC:
    如果内存不足,不会进行休眠操作,可以用于中断上下文;
    order:
    order = 0,分配1页
    order = 1, 分配2页
    order = 2, 分配4页
    order = 3, 分配8页
    ... ...
    函数返回值:保存分配的内核虚拟内存的首地址

    void free_pages(unsigned long addr, int order);
    功能:释放内存
    addr:首地址
    order:大小
    例如:
    unsigned long addr;
    addr = __get_free_pages(GFP_KERNEL, 4);

    //注意addr数据类型的转换

    free_page(addr, 4);

    1.3.vmalloc/vfree
    void *vmalloc (int size)
    功能:
    1.从动态内存映射区分配内存
    2.大小理论上默认120M
    3.虚拟上连续,物理上不一定连续
    4.如果内存不足,会导致休眠,不能用于中断上下文
    参数:
    size:分配内存的大小
    返回值:保存分配的内核虚拟内存的首地址

    void vfree (void *addr);
    释放内存

    例如:
    void *addr;
    addr = vmalloc (0x200000);
    vfree (addr);

    经验:一般内核分配内存都是在驱动的入口函数,先把内存分配到手!

    1.4.定义全局数组
    static char buf[5*1024*1024];
    说明:
    在BSS段中,BSS段的内容不会影响到可执行文件的大小;
    或者:
    static char buf[5*1024*1024] = {0xaa};
    //如果程序不访问使用
    说明:
    在数据段中,数据段的内容会影响到可执行文件的大小,但是由于程序没有访问这个数组,编译器进行优化,最终数组的大小不会影响到可执行文件的大小;
    或者
    static char buf[5*1024*1024] = {0xaa};
    //如果程序访问使用
    说明:
    程序访问,并且在数据段中,最终可执行文件的大小超过5M,最终会影响到ko文件的加载速度;

    课下:百度搜索:__attribute__ used unused

    1.5.在内核启动参数中,添加vmalloc=250M,表明内核启动时,动态内存映射区的大小有默认的120M修改为250M (从直接内存映射区抢)
    setenv bootargs root=/dev/nfs ... vmalloc=250M
    save
    重启
    查看内核打印信息,看动态内存映射区的大小

    1.6.在内核启动参数中,添加mem=8M(例子,5M 10M都可以),表明告诉内核,物理内存的最后8M要预留,
    内核无需进行管理,将来驱动可以单独使用最后的8M物理内存;
    将来驱动利用大名鼎鼎的ioremap函数将后面8M物理内存进行映射即可访问!

    setenv bootarg root=/dev/nfs ... mem=8M 

    ioremap函数

    明确:在内核空间不允许直接访问设备的物理地址,需要访问对应的虚拟地址;

    void *ioremap(unsigned long phys_addr, int size);
    函数功能:
    1.将物理地址映射到内核空间的虚拟地址上
    2.将物理地址映射到动态内存映射区的虚拟地址上;
    将来访问映射的虚拟地址就是在访问对应的物理地址
    参数:
    phys_addr:设备的起始物理地址
    size:设备的"物理内存"大小
    "物理内存":不单单指内存,还指例如GPIO对应的硬件寄存器对应的存储空间;
    返回值:保存映射的虚拟内存的首地址


    如果不再使用,记得要解除地址映射关系:
    void iounmap(void *addr)
    功能:
    解除物理地址和虚拟地址的映射关系
    参数:
    映射的虚拟内存的首地址

    例如:
    GPC0_3,GPC0_4两个硬件GPIO对应的寄存器分别为:
    GPCCON:配置寄存器
    GPCDATA:数据寄存器
    明确:寄存器对于CPU来说是一种外设,所以CPU要访问,必须要获取寄存器的地址,分别:
    GPCCON:0xE0200060,存储空间为4字节
    GPCDATA:0xE0200064,存储空间为4字节
    并且两个寄存器占用的地址空间是连续的;

    明确:内核不能直接访问以上物理地址,需要做映射:

    unsigned long *gpiocon, *gpiodata;
    gpiocon保存配置寄存器的内核虚拟地址
    gpiodata保存数据寄存器的内核虚拟地址

    映射的方法1:
    gpiocon = ioremap(0xE0200060, 4);
    gpiodata = ioremap(0xE0200064, 4);
    一旦有物理地址对应的内核虚拟地址,就可以访问外设
    *gpiocon ...
    *gpiodata ...

    映射方法2:
    gpiocon = ioremap(0xe0200060, 8);
    gpiodata = gpiocon + 1;
    *gpiocon ...
    *gpiodata ...

    解除映射:
    iounmap(gpiocon);

    #include <linux/io.h>

    案例

    利用ioremap实现LED开关操作,不允许使用GPIO操作库函数;

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/miscdevice.h>
    #include <linux/io.h>
    #include <linux/uaccess.h>
    #include <linux/fs.h>
    
    //定义LED开关命令
    #define LED_ON  0x100001
    #define LED_OFF 0x100002
    
    //定义保存配置寄存器和数据寄存器的内核虚拟地址变量
    static unsigned long *gpiocon, *gpiodata;
    
    static long led_ioctl(struct file *file,
                            unsigned int cmd,
                            unsigned long arg)
    {
        //分配内核缓冲
        int kindex;
        //拷贝用户数据到内核
        copy_from_user(&kindex, (int *)arg, sizeof(kindex));
        //解析命令
        switch(cmd) {
            case LED_ON:
                    if (kindex == 1)
                        *gpiodata |= (1 << 3);
                    else if (kindex == 2)
                        *gpiodata |= (1 << 4);
                break;
            case LED_OFF:
                    if (kindex == 1)
                        *gpiodata &= ~(1 << 3);
                    else if (kindex == 2)
                        *gpiodata &= ~(1 << 4);
                break;
        }
        printk("%s:配置寄存器=%#x, 数据寄存器=%#x\n", 
                            __func__, *gpiocon, *gpiodata);
        return 0;
    }
    
    //定义初始化硬件操作方法.unlocked_ioctl
    static struct file_operations led_fops = {
        .owner = THIS_MODULE,
        .unlocked_ioctl = led_ioctl
    };
    
    //定义初始化混杂设备对象
    static struct miscdevice led_misc = {
        .minor = MISC_DYNAMIC_MINOR,
        .name = "myled",
        .fops = &led_fops
    };
    
    static int led_init(void)
    {
        //注册混杂设备对象
        misc_register(&led_misc);
        
        //将配置寄存器和数据寄存器的物理地址映射到内核虚拟地址上
        gpiocon = ioremap(0xE0200060, 8);
        gpiodata = gpiocon + 1;
    
        //配置GPIO为输出口,输出0
        *gpiocon &= ~((0xf << 12) | (0xf << 16));
        *gpiocon |= ((1 << 12) | (1 << 16));
        *gpiodata &= ~((1 << 3) | (1 << 4));
        return 0;
    }
    static void led_exit(void)
    {
        //输出0,解除地址映射
        *gpiodata &= ~((1 << 3) | (1 << 4));
        iounmap(gpiocon);
        //卸载混杂设备
        misc_deregister(&led_misc);
    }
    module_init(led_init);
    module_exit(led_exit);
    MODULE_LICENSE("GPL");

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    //./led_test on 1
    //./led_test off 1
    //./led_test on 2
    //./led_test off 2
    
    //定义LED开关命令
    #define LED_ON  0x100001
    #define LED_OFF 0x100002
    
    int main(int argc, char *argv[])
    {
        int fd;
        int uindex; //用户缓冲区,保存灯的编号
    
        if (argc != 3) {
            printf("Usage:\n %s <on|off> <1|2>\n", argv[0]); 
            return -1;
        }
        
        fd = open("/dev/myled", O_RDWR);
        if (fd < 0)
            return -1;
    
        //将灯的编号字符串转整形:“123abc” -> 123
        uindex = strtoul(argv[2], NULL, 0);
       
        //向设备发送命令和灯的编号
        if (!strcmp(argv[1], "on"))
            ioctl(fd, LED_ON, &uindex);
        else
            ioctl(fd, LED_OFF, &uindex);
    
        close(fd);
        return 0;
    }

    展开全文
  • linux内存管理(一): arm64内核内存布局

    千次阅读 2020-03-03 23:19:57
    1. 内核内存配置 AArch64 Linux通常使用以下配置: 4KB页面, 使用3级或4级转换表,支持39位(512GB)或48位(256TB)的虚拟地址。 64KB页面,使用2级转换表,支持42位(4TB)虚拟地址。 他们的内存布局是一致的。...

    1. 内核内存配置

    AArch64 Linux通常使用以下配置:

    • 4KB页面, 使用3级或4级转换表,支持39位(512GB)或48位(256TB)的虚拟地址。
    • 64KB页面,使用2级转换表,支持42位(4TB)虚拟地址。

    他们的内存布局是一致的。

    以内核defconfig默认的4KB page + 4 levels配置为例,LINUX在arm架构上把虚拟地址空间划分为2个空间, 虚拟地址和内核地址, 每个空间最大支持256TB.

    		 Start          End         			  Size        Use
     -----------------------------------------------------------------------
     0x0000000000000_0000   0x0000_ffff_ffff_ffff     256TB       user
     0xffff_0000_0000_0000  0xffff_ffff_ffff_ffff     256TB       kernel
    

    2. 内核内存布局的打印

    在arm64 4.16的内核之前,内核基本完成内存初始化工作后会打印出内核的内存布局
    qemu arm64打印如下:
    在这里插入图片描述

    这部分打印在mem_init()函数中实现(arch/arm64/mm/init.c)
    start_kernel()->mm_init()->mem_init()

    #define MLK(b, t) b, t, ((t) - (b)) >> 10
    #define MLM(b, t) b, t, ((t) - (b)) >> 20
    #define MLG(b, t) b, t, ((t) - (b)) >> 30
    #define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K)
    
    	pr_notice("Virtual kernel memory layout:\n");
    #ifdef CONFIG_KASAN
    	pr_notice("    kasan   : 0x%16lx - 0x%16lx   (%6ld GB)\n",
    		MLG(KASAN_SHADOW_START, KASAN_SHADOW_END));
    #endif
    	pr_notice("    modules : 0x%16lx - 0x%16lx   (%6ld MB)\n",
    		MLM(MODULES_VADDR, MODULES_END));
    	pr_notice("    vmalloc : 0x%16lx - 0x%16lx   (%6ld GB)\n",
    		MLG(VMALLOC_START, VMALLOC_END));
    	pr_notice("      .text : 0x%p" " - 0x%p" "   (%6ld KB)\n",
    		MLK_ROUNDUP(_text, _etext));
    	pr_notice("    .rodata : 0x%p" " - 0x%p" "   (%6ld KB)\n",
    		MLK_ROUNDUP(__start_rodata, __init_begin));
    	pr_notice("      .init : 0x%p" " - 0x%p" "   (%6ld KB)\n",
    		MLK_ROUNDUP(__init_begin, __init_end));
    	pr_notice("      .data : 0x%p" " - 0x%p" "   (%6ld KB)\n",
    		MLK_ROUNDUP(_sdata, _edata));
    	pr_notice("       .bss : 0x%p" " - 0x%p" "   (%6ld KB)\n",
    		MLK_ROUNDUP(__bss_start, __bss_stop));
    	pr_notice("    fixed   : 0x%16lx - 0x%16lx   (%6ld KB)\n",
    		MLK(FIXADDR_START, FIXADDR_TOP));
    	pr_notice("    PCI I/O : 0x%16lx - 0x%16lx   (%6ld MB)\n",
    		MLM(PCI_IO_START, PCI_IO_END));
    #ifdef CONFIG_SPARSEMEM_VMEMMAP
    	pr_notice("    vmemmap : 0x%16lx - 0x%16lx   (%6ld GB maximum)\n",
    		MLG(VMEMMAP_START, VMEMMAP_START + VMEMMAP_SIZE));
    	pr_notice("              0x%16lx - 0x%16lx   (%6ld MB actual)\n",
    		MLM((unsigned long)phys_to_page(memblock_start_of_DRAM()),
    		    (unsigned long)virt_to_page(high_memory)));
    #endif
    	pr_notice("    memory  : 0x%16lx - 0x%16lx   (%6ld MB)\n",
    		MLM(__phys_to_virt(memblock_start_of_DRAM()),
    		    (unsigned long)high_memory));
    
    

    kasan: KASAN是一个动态检测内存错误的工具, 原理是利用额外的内存标记可用内存的状态. 这部分额外的内存被称作shadow memory(影子区)。KASAN将1/8的内存用作shadow memory。

    modules: 128MB的内核模块区域,是内核模块使用的虚拟地址空间

    vmalloc: vmalloc函数使用的虚拟地址空间,kernel image也在vmalloc区域,内核镜像的起始地址 = KIMAGE_ADDR + TEXT_OFFSET, TEXT_OFFSET是内存中的内核镜像相对内存起始位置的偏移。
    .text: 代码段。 _text是代码段的起始地址,_etext是结束地址, kernel image放在这段位置。
    .rodata: read-only-data. 常量区,存放程序中定义为const的全局变量。
    .init: 对应大部分模块初始化的数据,初始化结束后就会释放这部分内存。
    .data: 数据段。 包含内核大部分已初始化的全局变量。
    .bss: 静态内存分配段。 包含所有未初始化或初始化为0的静态全局变量。

    fixed: 固定映射区。 在内核的启动过程中,有些模块需要使用虚拟内存并mapping到指定的物理地址上,而且,这些模块也没有办法等待完整的内存管理模块初始化之后再进行地址映射。因此,linux kernel固定分配了一些fixmap的虚拟地址,这些地址有固定的用途,使用该地址的模块在初始化的时候,讲这些固定分配的地址mapping到指定的物理地址上去。(Fix-Mapped Addresses

    PCI I/O: pci设备的I/O地址空间

    vmemmap: 内存的物理地址如果不连续的话,就会存在内存空洞(稀疏内存),vmemmap就用来存放稀疏内存的page结构体的数据的虚拟地址空间。

    memory: 线性映射区,范围是【0xffff_8000_0000_0000, 0xffff_ffff_ffff_ffff】, 一共有128TB, 但这里代码对应的是memblock_start_of_DRAM()和memblock_end_of_DRAM()函数。
    memory根据实际物理内存大小做了限制,所以memroy显示了实际能够访问的内存区。

    MLM(__phys_to_virt(memblock_start_of_DRAM()), (unsigned long)high_memory))
    high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
    

    最终是通过dts或acpi中配置的memory节点确定的。


    后面的内核版本删掉了这段打印,如果需要的话可以手动revert掉该补丁。
    在这里插入图片描述

    3. 内核内存布局图

    根据arm64启动的打印信息, 确定arm64 内核内存布局图:
    在这里插入图片描述

    4. 参考资料:

    Memory Layout on AArch64 Linux
    Fix-Mapped Addresses

    展开全文
  • 内核内存泄露检查

    千次阅读 2014-05-08 09:52:53
    前言:内核内存泄露,对高手来说是小事一桩,轻而易举就能查到的,  但是对于没有接触过这的,要熟悉它,可能需要一段时间,比如我。  写的不好的地方,请多多指正。 内核内存的影响是很大的,特
    作 者: correy
    时 间: 2012-07-29,11:33:30
    链 接: http://bbs.pediy.com/showthread.php?t=154015

    前言:内核内存泄露,对高手来说是小事一桩,轻而易举就能查到的,
          但是对于没有接触过这的,要熟悉它,可能需要一段时间,比如我。
          写的不好的地方,请多多指正。

    内核内存的影响是很大的,特别是在服务器上,具体的看下面的案例。

    检查内核内存池泄露的工具有:
    poolmon.exe微软的命令行工具,在wdk里面。
    Pooltag.exe,osr的图形界面工具。
    Gflags.exe,windbg里面有。另一种办法是修改注册表。
    Pooltag.txt,windbg里面的。//这个很有用。
    Verifier.exe,这个是系统自带的。//这个暂时我没有用到。

    步骤如下:
    首先确保poolmon工具可以使用:winddows 2003及以后的好像不用设置。

    方法一:使用Gflags.exe,具体的步骤如下:
    1.单击开始,单击运行,键入gflags.exe,然后单击确定
    2.选择启用池标记
    3.单击应用,然后单击确定
    4.重新启动计算机。

    方法二:或者使用注册表修改,修改办法如下:
    1.运行注册表编辑器。
    2.在注册表中找到以下项:
    HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager
    3.记下的值的GlobalFlag,或保存Session Manager键。
    4.双击右窗格中的GlobalFlag值。
    5.将值更改为0x00000400的十六进制。
    注意当您添加全局标志值 0x00000400 时,它只显示为正在 0x400 后它将被添加。一定要添加前导零的所有或某些 Poolmon 信息将不会显示在输出屏幕。
    重新启动计算机。

    Poolmon.exe是命令行的,功能强大,不易使用。简要的说明几个使用办法:
    P-排序标记列表中的通过分页,非分页,或混合。
    B-标记按最大字节使用情况。M-标记按最大字节分配。
    T 按标记名称的字母顺序排序-标记。
    E-显示分页,跨底部未分页的总数。循环。
    A-标记按分配大小。
    F-按标记"释放"。
    S-按标记的 allocs 的差异,并释放。
    E-显示分页,跨底部未分页的总数。循环。
    Q-退出。
    L-加亮或者不加亮,显示变化的行。

    一些说明:
    Type。此列显示 Nonp 或 Paged,分别表示非分页或分页内存使用方式。非分页内存使用方式更有可能导致问题。
    Diff。此列显示该组件已执行的尚未得到释放的内存分配次数。
          Diff 列中的值是 Allocs 和 Frees 列中相应的值之差。
          如果一个组件在 Diff 列中的值随着时间而增长,则可能表明此组件存在内存泄漏。
    Bytes。此值指示当前分配的内存量。如果一个组件在 Bytes 列中的值随着时间而增长,则可能表明此组件存在内存泄漏。
    Mapped_Driver。此列仅在使用 g 参数时出现。它显示对标记的易于理解的描述,而且往往指示驱动程序的源文件。

    Pooltag.exe的Mapped_Driver列可以显示驱动所在的目录。但信息很少,没有poolmon显示的信息多。
         操作办法是pooltags->parse all drivers in driver directory
    界面的显示设置我就不说了:

    使用办法:
    例如:poolmon -g "C:\Program Files\Debugging Tools for Windows\triage\pooltag.txt"
    每隔10-30分钟观看,d或者b命令的行列的变化,如果不停的变化(增加),就是泄露。
    按d 显示的是没有释放的,按b显示的是申请的。

    关于内核内存池的tag,
    我以前收集的有3中办法,现在只记得一种了,
    就是使用带有申请标记内存的函数。申请内存的时候一定要加标记。标记在c/c++中要用单引号,不超过4个字节。
    如:ExAllocatePoolWithTag、ExallocatePoolWithTagPriority 和ExAllocatePoolWithQuotaTag,ExInitializeNPagedLookasideList 等。

    如何找到池标记所使用的驱动程序,这时候大多是分析别人的驱动。
    findstr /m /l “xxxx” c:\*.sys
    有的时候会一个都搜索不出,这时我也不知所措,好像也应该没有这种情况。也许是你搜索的已经在,或者是已知的。
    有的时候会搜索出多个,再根据每个驱动的版本和公司等做筛选。直到确定有问题的那一个。

    参考资料:

    如何使用内存池监视器 (Poolmon.exe) 来排查内核模式内存泄漏
    http://support.microsoft.com/kb/177415/zh-cn

    如何找到池标记所使用的第三方驱动程序 
    http://support.microsoft.com/?kbid=298102

    谁在使用池?
    http://msdn.microsoft.com/zh-cn/library/windows/hardware/gg463213.aspx

    PoolMon Run-time Commands
    http://msdn.microsoft.com/en-us/library/ff550476.aspx

    PoolMon Startup Command
    http://msdn.microsoft.com/en-us/library/ff550482.aspx

    PoolMon Examples
    http://www.osronline.com/ddkx/ddtools/poolmon_37n7.htm
    http://msdn.microsoft.com/en-us/library/ff550458.aspx

    360的驱动(qutmdrv.sys)分页内存泄露案例
    http://www.cnblogs.com/ahuo/archive/2010/09/29/1838439.html

    瑞星的驱动(basetdi.sys)的非分页内存泄露案例
    http://space.itpub.net/4670/viewspace-351828

    等等。 

    展开全文
  • 张诗明: Linux内核内存压缩技术

    千次阅读 2017-12-11 00:00:00
    2017年12月9号,来自四十多家公司的60多位一线工程师和国内众多Linux大咖在深圳绽放花园欢聚一堂,就Linux调度器演进,内核内存压缩技术,RISC-V三个主题展开了深入的讨论和思维的碰撞。这是张诗明《郭健: Linux内核...
        

    2017年12月9号,来自四十多家公司的60多位一线工程师和国内众多Linux大咖在深圳绽放花园欢聚一堂,就Linux调度器演进,内核内存压缩技术,RISC-V三个主题展开了深入的讨论和思维的碰撞。这是张诗明《郭健: Linux内核内存压缩技术分享》的演讲slides

    640?wx_fmt=gif&wxfrom=5&wx_lazy=1

    640?wx_fmt=gif&wxfrom=5&wx_lazy=1

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif

    0?wx_fmt=gif


    展开全文
  • x64内核内存空间结构

    千次阅读 2016-07-24 20:32:23
    x64内核内存空间结构 0x00 前言 本文主要是讨论Windows 7 x64下的内核虚拟地址空间的结构,可以利用WiinDBG调试的扩展命令"!CMKD.kvas"来显示x64下的内核虚拟地址空间的整体布局。了解内核的地址布局在某些情况...
  • Linux 内核内存检测工具 - Kmemcheck
  • 浅析linux内核内存管理之最终内核页表   在系统初始化的时候进行了最终内核映射,主要在paging_init函数中: [html] view plaincopy 499void __init paging...
  • 罗玉平: ARMv8 Linux内核内存屏障

    千次阅读 2017-12-06 00:00:00
    来自20个多家公司的50多位一线工程师于12月3号在上海泰兴路99号张园内的一个咖啡厅欢聚一堂,围绕ROS、移动GPU、ARM 内存屏障以及机器学习这四个热门主题展开...这是《罗玉平: ARMv8 Linux内核内存屏障》演讲slides。
  • 浅析linux内核内存管理之临时内核页表   临时页全局目录是在内核编译过程中静态地初始化的,而临时页表是由startup_32()汇编语言函数初始化的。临时页全局目录存放在swapper_pg_dir变量中...
  • 笔记:linux内核内存布局以及/dev/mem

    千次阅读 2019-05-09 16:44:01
    linux内核内存管理(zone_dma zone_normal zone_highmem)(linux memory layout) /dev/mem可没那么简单 学习笔记(以x86为例) linux的虚拟地址空间: 32位的CPU,最大寻址范围为2^32 - 1也就是4G的线性地址空间。...
  • Linux内核内存管理

    2018-04-07 23:39:47
    1、内存模型概览通常CPU可见的地址是有限制的,32位的CPU最多可见4GB的物理空间,64位的CPU可见的空间会更大。...如图1所示,其中0~3G为用户空间,3~4G为内核空间。通过MMU这两部分空间都可以访问到实际的物理内存...
  • linux 内核 内存管理

    千次阅读 2013-05-25 14:58:34
    内存管理应该是linux内核里最复杂的子系统之一。 涉及到的有mmu虚拟内存内存映射,小内存slab 管理,文件系统到内存的映射,进程虚拟内存空间 等待等等。 一图胜千言 看了上面一幅图,在仔细理解下面一...
  • linux内核内存分配

    千次阅读 2013-11-18 20:56:07
    内核中的内存分配通常通过kmalloc/kfree来进行,但是也有其它的方式来获取内存,所有这些方式共同提供了内核中分配、释放内存的接口。 一、kmalloc/kfree 类似于标准C中的malloc/free,kmalloc/kfree是内核中的用于...
  • 浅析linux内核内存管理之PAE

    千次阅读 2012-04-15 20:12:42
    浅析linux内核内存管理之PAE    早期Intel处理器从80386到Pentium使用32位物理地址,理论上,这样可以访问4GB的RAM。然而,大型服务器需要大于4GB的RAM来同时运行数以千计的进程,近几年来这对Intel造成...
  • 内核内存泄露查找方式

    千次阅读 2016-03-11 11:54:53
    内核中发生内存泄露时,一般利用pool tag定位内存泄露的地方。步骤如下: 1. 首先要启用pool tag,对于xp系统,可以利用gflag工具启用pool tag并重启计算机。对于之后的操作系统,pool tag默认启用。 2. 若使用...
  • 前一篇blog linux内核内存分配(一、基本概念) 主要是分析linux内核内存的分配和物理页分配函数接口。但是在实际的操作中,不一定所有内存申请都需要一个物理页,很多只是需要分配几K大小的内存就可以。所以就需要...
  • 调用CreateToolhelp32Snapshot未关闭句柄,导致内核内存泄露
  • linux内核内存管理

    千次阅读 2012-11-06 16:48:56
    内核空间申请指定大小的内存区域,返回内核空间虚拟地址。在函数实现中,如果申请的内存空间较大的话,会从buddy系统申请若干内存页面,如果申请的内存空间大小较小的话,会从slab系统中申请内存空间。有关buddy和...
  • Linux内核内存压缩技术

    千次阅读 2017-12-02 22:59:01
    为什么需要内存压缩说到压缩这个词,我们都可以想到是降低占用空间,使同样的空间可以存放更多的东西,如我们平时常用的压缩文件等。内存压缩同样也是为了节省内存内存无论是多大,总是不够用的(至少目前如此)...
  • 浅析linux内核内存管理之内存池

    千次阅读 2012-05-09 22:19:15
    内核中有些地方的内存分配是不允许失败的。为了确保这种情况下的成功分配,内核开发者建立了一种称为内存池的抽象。内存池其实就是某种形式的后备高速缓存,它试图始终保存空闲的内存,以便在紧急状态下使用。下边是...
  • MDL修改内核内存实现

    千次阅读 2019-02-01 21:30:02
    //创建一个内核模式下的虚拟内存对应ZwQueryDirectoryFile函数 DbgPrint(“addrMm=%x\n”, addrMm); addrMm = MmMapLockedPagesSpecifyCache(mdl, UserMode, MmCached, 0, FALSE, NormalPagePriority);//创建一个...
  • ldd3-内核内存分配

    千次阅读 2007-01-27 16:27:00
    ldd3-内核内存分配先总结内存分配,明天我再来总结Mmap和DMA技术-------------------------------以下忽略了内存池分配技术和per-CPU变量的相关内容。kmalloc函数不对所获取的内存...
  • linux内核内存的详细分配

    万次阅读 2015-08-04 22:23:40
    要解答这个问题,首先就要看看内核非连续内存。 在linux的内存管理中,用户使用0~3GB的地址空间,而内核只是用了3GB~4GB区间的地址空间,共1GB;非连 续空间的物理映射就位于3GB~4GB之间,如下图示 0GB
  • 在arm体系下,内核在较早版本的读写没有...在19版本上理论上可以更改内存的读写属性,但是采取 set_mem_rw = (void *)kallsyms_lookup_name("set_memory_rw"); 进行导出引用,发现根本不管用。我还以为这里内核写的...
  • linux内核内存管理学习

    千次阅读 2015-01-24 19:04:41
    内存是通过指针寻址的,因而CPU的字长决定了CPU所能管理的地址空间的大小,该地址空间就被称为虚拟地址空间,因此32位CPU的虚拟地址空间大小为4G,这和实际的物理内存数量无关。 Linux内核将虚拟地址空间分成了两...
  • linux 内核内存池--mempool

    千次阅读 2016-07-25 11:16:40
    内存池(Memery Pool)技术是在真正使用内存之前,先申请分配一定数量的、大小相等(一般情况下)的... 不仅在用户态应用程序中被广泛使用,同时在Linux内核也被广泛使用,在内核中有不少地方内存分配不允许失败。作为一
  • Linux内核内存分配函数

    千次阅读 2011-06-22 14:25:00
    Linux内核内存的管理不像在内核外这么简单。和用户空间最大的不同是内核的内从空间不像用户空间那么容易得到,并不是总能轻易的得到想要的内存。页:内核最基本的内存管理单元就是页(page),因为MMU管理的内存...
  • 内核内存检测工具memleak的使用方式

    千次阅读 2018-03-18 19:19:30
    Kmemleak 提供了一种可选的内核泄漏检测,其方法类似于跟踪内存收集器使用Kmemleak需要在内核中将CONFIG_DEBUG_KMEMLEAK使能(默认未使能,因此使用该功能会涉及替换内核)。 1. 将内核默认.config文件拷贝到源码...
  •  内核把物理页作为内存管理的基本单位;内存管理单元(MMU)把虚拟地址转换为物理 地址,通常以页为单位进行处理。MMU以页大小为单位来管理系统中的也表。  32位系统:页大小4KB  64位系统:页大小8KB ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 45,176
精华内容 18,070
关键字:

内核内存