2010-03-03 12:46:00 satanwxd 阅读数 1980
  • Linux核心技能-用户及权限详解

    Linux起源,Linux架构和Linux形成历史开始逐步讲解,让你彻彻底底了解Linux的诞生,之后介绍了Linux相关文化和核心组成结构,以及Linux常用命令和基本用法,课程由浅入深,讲授方法受到98%学员一致好评!

    12331 人正在学习 去看看 马永亮

  free_bootmem()这个函数是系统启动初期内存释放的核心函数,我们来看看它的代码。

  void __init free_bootmem (unsigned long addr, unsigned long size)//addr是要释放的物理起始地址,size是要释放空间的大小。
 {
    free_bootmem_core(NODE_DATA(0)->bdata, addr, size);//直接从内存node0号开始释放内存空间。
 }//可以看出真正的核心函数是free_bootmem_core()这个函数,这个才是核心部分。我们来看看它的具体内容吧。

  static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr, unsigned long size)
{
    unsigned long i;
    unsigned long start;
    /*
     * round down end of usable mem, partially free pages are
     * considered reserved.
     */
    unsigned long sidx;
    unsigned long eidx = (addr + size - bdata->node_boot_start)/PAGE_SIZE;//计算出要释放空间的结束位置相对于该内存节点的起始位置的偏移页数。
    unsigned long end = (addr + size)/PAGE_SIZE;//释放空间最后位置的绝对页号。

    BUG_ON(!size);//如果释放空内存,系统崩溃。
    BUG_ON(end > bdata->node_low_pfn);//不能释放超过本节点范围内的内存空间,否则系统崩溃。

    if (addr < bdata->last_success)
             bdata->last_success = addr;

    /*
     * Round up the beginning of the address.
     */
    start = (addr + PAGE_SIZE-1) / PAGE_SIZE;//这里计算开始地址的全新页,假设addr是在0~4kb的地址范围的话,其实真正在0号页的位置,但是如果通过上面的运算,求出来的就是1号页的位置。为什么这样做呢?因为如果起始地址不是按页对齐的,如果直接释放,就会把前面不属于这个内存node的空间也释放了。
    sidx = start - (bdata->node_boot_start/PAGE_SIZE);//这个就是计算新页和原来的起始地址所在页的偏移页数。

    for (i = sidx; i < eidx; i++) {//这里是对要释放的页对应的页帧位码表的位清零,在mem_init()执行之前必须要把释放的页对应的位清零,因为执行mem_init()时,会把页帧位码表清除的,同时会把对应位为1的页strcut page的flags=PG_reserved。这时用__free_pages是无法对标志为PG_reserved的页释放的。
                  if (unlikely(!test_and_clear_bit(i, bdata->node_bootmem_map)))//如果发现页帧位码表的那些位已经为0的话,系统就崩溃了。
                  BUG();
    }
}
看到这里,我们已经把启动前的内存释放和分配讲了一遍了。我们现在关注启动之后的内存在Linux是如何管理的,这也是Linux里面应用的重头戏。

2018-04-12 10:44:07 valada 阅读数 191
  • Linux核心技能-用户及权限详解

    Linux起源,Linux架构和Linux形成历史开始逐步讲解,让你彻彻底底了解Linux的诞生,之后介绍了Linux相关文化和核心组成结构,以及Linux常用命令和基本用法,课程由浅入深,讲授方法受到98%学员一致好评!

    12331 人正在学习 去看看 马永亮

内存管理不仅是 Linux 系统中比较难理解的模块,更是网上资料讲解混乱的模块。本场 Chat 旨在让读者了解内存分配的来龙去脉,从硬件原理和内核角度出发,分析如下内容:

  1. CPU 通过 MMU 访问物理地址的原理;
  2. 内存的 ZONE 划分:DMA、NORMAL 和 HIGHMEM;
  3. 内存的 Page 管理以及防止内外碎片的方法;
  4. 内存管理的 Buddy 算法;
  5. 内存管理的 Slab 算法;
  6. 连续内存分配器(CMA)。

阅读全文: http://gitbook.cn/gitchat/activity/5a9fddc6f497b003c2476c6e

您还可以下载 CSDN 旗下精品原创内容社区 GitChat App ,阅读更多 GitChat 专享技术内容哦。

FtooAtPSkEJwnW-9xkCLqSTRpBKX

2013-02-07 12:57:14 tenfyguo 阅读数 3301
  • Linux核心技能-用户及权限详解

    Linux起源,Linux架构和Linux形成历史开始逐步讲解,让你彻彻底底了解Linux的诞生,之后介绍了Linux相关文化和核心组成结构,以及Linux常用命令和基本用法,课程由浅入深,讲授方法受到98%学员一致好评!

    12331 人正在学习 去看看 马永亮
一,不是 malloc 后就马上占用实际内存,而是第一次使用时(如对内存赋值,memset等操作)发现虚存对应的物理页面未分配,产生缺页中断,才真正分配物理页面,
同时更新进程页面的映射关系。但由于每个物理内存页面大小是 4k ,不管 memset其中的1k还是5k 、7k ,实际占用物理内存总是 4k 的倍数。所以 RSS 的增量总是 4k 的倍数。

二,可以通过如下命令查看一个进程占有的虚拟内存和物理内存大小:
    ps aux | grep pid | grep -v grep
    其中关键的两信息(第五、六列)为:
    1. VSZ , virtual memory size ,表示进程总共使用的虚拟地址空间大小,包括进程地址空间的代码段、数据段、堆、文件映射区域、栈、内核空间等所有虚拟地址使用的总和,单位是 K
    2. RSS , resident set size ,表示进程实际使用的物理内存空间, RSS 总小于 VSZ 。

三,关于内存释放
malloc 使用 mmap 分配的内存 ( 大于 128k) , free 会调用 munmap 系统调用马上还给 OS ,实现真正释放。
堆内的内存,只有释放堆顶的空间,同时堆顶总连续空闲空间大于 128k 才使用 sbrk(-SIZE) 回收内存,真正归还 OS 。
堆内的空闲空间,是不会归还给 OS 的。
随着系统频繁地 malloc 和 free ,尤其对于小块内存,堆内将产生越来越多不可用的碎片,导致“内存泄露”。而这种“泄露”现象使用 valgrind 是无法检测出来的。
因此,当我们写程序时,不能完全依赖 glibc 的 malloc 和 free 的实现。更好方式是建立属于进程的内存池,即一次分配 (malloc) 大块内存,小内存从内存池中获得,
当进程结束或该块内存不可用时,一次释放 (free) ,可大大减少碎片的产生。

四,如何查看缺页中断
可通过以下命令查看缺页中断信息
ps -o majflt,minflt -C <program_name>
ps -o majflt,minflt -p <pid>
其中, majflt 代表 major fault ,指大错误, minflt 代表 minor fault ,指小错误。这两个数值表示一个进程自启动以来所发生的缺页中断的次数。
其中 majflt 与 minflt 的不同是, majflt 表示需要读写磁盘,可能是内存对应页面在磁盘中需要 load 到物理内存中,也可能是此时物理内存不足,需要淘汰部分物理页面至磁盘中。

2009-03-31 17:58:36 iteye_13453 阅读数 75
  • Linux核心技能-用户及权限详解

    Linux起源,Linux架构和Linux形成历史开始逐步讲解,让你彻彻底底了解Linux的诞生,之后介绍了Linux相关文化和核心组成结构,以及Linux常用命令和基本用法,课程由浅入深,讲授方法受到98%学员一致好评!

    12331 人正在学习 去看看 马永亮
[url=http://www.ibm.com/developerworks/cn/linux/management/tune/index.html]Linux性能调协[/url]之
3.5使用内存文件系统

在Linux中可以将一部分内存mount为分区来使用,通常称之为RamDisk。
RamDisk有三种实现方式:
第一种就是传统意义上的,可以格式化,然后加载。
这在Linux内核2.0/2.2就已经支持,其不足之处是大小固定,之后不能改变。
为了能够使用Ramdisk,我们在编译内核时须将block device中的Ramdisk支持选上,它下面还有两个选项,一个是设定Ramdisk的大小,默认是4096k;另一个是initrd的支持。
如果对Ramdisk的支持已经编译进内核,我们就可以使用它了:
查看一下可用的RamDisk,使用ls /dev/ram*
首先创建一个目录,比如test,运行mkdir /mnt/test;
然后对/dev/ram0 创建文件系统,运行mke2fs /dev/ram0;
最后挂载 /dev/ram0,运行mount /dev/ram /mnt/test,就可以象对普通硬盘一样对它进行操作了。

更详细的内容可以参考: http://www.linuxfocus.org/ChineseGB/November1999/article124.html http://www.vanemery.com/Linux/Ramdisk/ramdisk.html

另两种则是内核2.4才支持的,通过Ramfs或者Tmpfs来实现:
它们不需经过格式化,用起来灵活,其大小随所需要的空间而增加或减少。

Ramfs顾名思义是内存文件系统,它它处于虚拟文件系统(VFS)层,而不像ramdisk那样基于虚拟在内存中的其他文件系统(ex2fs)。

因而,它无需格式化,可以创建多个,只要内存足够,在创建时可以指定其最大能使用的内存大小。
如果你的Linux已经将Ramfs编译进内核,你就可以很容易地使用Ramfs了。创建一个目录,加载Ramfs到该目录即可:
# mkdir /testRam
# mount -t ramfs none /testRAM
缺省情况下,Ramfs被限制最多可使用内存大小的一半。可以通过maxsize(以kbyte为单位)选项来改变。
# mount -t ramfs none /testRAM -o maxsize=2000 (创建了一个限定最大使用内存为2M的ramdisk)


Tmpfs是一个虚拟内存文件系统,它不同于传统的用块设备形式来实现的Ramdisk,也不同于针对物理内存的Ramfs。
Tmpfs可以使用物理内存,也可以使用交换分区。在Linux内核中,虚拟内存资源由物理内存(RAM)和交换分区组成,这些资源是由内核中的虚拟内存子系统来负责分配和管理。
Tmpfs向虚拟内存子系统请求页来存储文件,它同Linux的其它请求页的部分一样,不知道分配给自己的页是在内存中还是在交换分区中。同Ramfs一样,其大小也不是固定的,而是随着所需要的空间而动态的增减。
使用tmpfs,首先你编译内核时得选择"虚拟内存文件系统支持(Virtual memory filesystem support)" 。
然后就可以加载tmpfs文件系统了:
# mkdir -p /mnt/tmpfs
# mount tmpfs /mnt/tmpfs -t tmpfs
同样可以在加载时指定tmpfs文件系统大小的最大限制:
# mount tmpfs /mnt/tmpfs -t tmpfs -o size=32m

使用df -aT命令可以看到有个/dev/shm目录,该目录的文件系统是tmpfs的,因此这个目录下的文件访问是非常快的,但是其大小可能不同机器都不一样,而且每次重启后文件也就丢失了。

更详细的可参考《[url=http://linux.chinaitlab.com/unix/10809.html]FreeBSD下的内存文件系统[/url]》一文

“对于高负载的服务器,使用内存文件系统实际上得不偿失,在系统内存很快用光的情况下,操作系统将进行磁盘交换,导致系统性能严重下降,这比起直接使用磁盘文件系统更为糟糕。事实上,在高负载的服务器环境下,允许系统使用更多的内存来缓冲磁盘数据,更有效的发挥系统的磁盘缓冲能力,在实际使用中更为有效。 ”
2019-08-04 22:36:53 ysu_wangli 阅读数 45
  • Linux核心技能-用户及权限详解

    Linux起源,Linux架构和Linux形成历史开始逐步讲解,让你彻彻底底了解Linux的诞生,之后介绍了Linux相关文化和核心组成结构,以及Linux常用命令和基本用法,课程由浅入深,讲授方法受到98%学员一致好评!

    12331 人正在学习 去看看 马永亮

一、介绍

  1. 内核态函数定义
    与C语言编程时常用的malloc()、free()函数类似,LINUX内核态分别用kmalloc()、kfree()实现与核心内存接口的功能要求。
  2. 用户态函数定义
    与C语言编程时常用的malloc()、free()函数类似,LINUX用户态分别用vmalloc()、vfree()实现功能要求。

二、Kmalloc内存分配函数

void * kmalloc(size_t size ,int flags)

  1. kmalloc可分配的空闲内存来自free_area[]数组;
  2. 当空闲块数低于min_free_page时,只得换出其他页面;
  3. 换页过程中,该调用kmalloc函数的进程暂时挂起,CPU调度其他就绪进程;
  4. 如果下一个进程,也调用kmalloc函数,这要求该函数必须是可重入函数;

三、Kfree内存释放函数

void Kfree(const void * objp)

  1. 必须是通过kmalloc分配的内存;
  2. objp是地址;
  3. 如果当前待释放的对象是在slab完全块,则将该slab链接移植非完全块;如果是非完全块,则判断是否为空闲块,然后判断移植空闲链表;

四、Vmalloc内存分配函数

1.Kmalloc()由存储空间在进程的虚拟空间是连续的,但是对应的屋里内存仍需要经缺页中断后,由缺页服务程序分配。
2.分配的物理页帧也不是连续的,这个特征与访问用户态内存相似,所以不妨把Vmalloc和Vfree称为用户内存的申请和释放界面。

没有更多推荐了,返回首页