Tuesday, August 22, 2006

uClinux学习笔记

uClinux学习笔记 - Javen's Live - by javen

Tuesday, 23. May 2006, 18:59:21

Software

uClinux学习笔记

陈华:
目录 [显示隐藏]
1 目的
2 背景知识
3 share library
4 可执行文件格式
5 内存分配
6 进程
7 共享库
8 查看内存情况
[编辑]
目的

我整理的一部分的uClinux的资料供大家参考、对系统理解的越多越有利于我们的工作、即使只是一般的业务开发最好也了解一下。

uClinux与普通linux的最大区别在于没有VM、衍生出来的不同点都是和这部分相关的、由于是设计给没有MMU的嵌入式CPU设计的、所以VM的实现变成不可能。

最大的危险在于、由于没有VM的内存保护、任何的进程都可以修改其他进程乃至核心的数据。


[编辑]
背景知识


Unix 进程的内存使用可以分为5个部分:text, bss, data, heap, stack text 代码 bss 未初始化数据短 data 初始化数据段 heap 堆空间,libc管理用于动态分配内存(malloc) stack 栈空间,主要用于参数传递

其中stack在地址空间的最高部分,自高而低的增长,heap在其他段的最下方,自低而高的增长。stack的增长是自动的,OS会管理,heap的增长是由libc向OS申请的。

heap 管理的经典算法是power-2, 该算法以2的幂的单位进行内存分配,例如32,64,128,265...,同时配合伙伴算法进行碎片的恢复。这种算法的一个问题是会导致一些内存浪费, 这种浪费被叫做slack memroy。最最恶劣的情况下可能有接近50%的内存没有被使用。

在核心中还引入了一种分配机制 Slab,专门用于分配对象型数据,所谓的对象型数据一般形式为一个struct,其中的很多member再分配后会被进行初始化,而且在释放的时候后常 常有一些member保持不变,为了减少初始化的代价和power-2算法的slack,引入Slab概念,Slab申请整块的页面划分成一个一个指定的 大小,使用用户提供的函数在分配的时候进行初始化和释放,有效的提高了速度,在被Solaris引入后被广泛的使用了。


[编辑]
share library


请 注意unix系统中使用share library,而不是dll. 这不是一个起名字时的不同,而是具有本质区别的。share library包含了在磁盘上和在内存中都被share。而MS的dll实际上一般只能在磁盘上share,内存中的share很困难,因此他只是一个动 态连接而不是共享。
[编辑]
可执行文件格式

standard linux使用的elf格式的文件、这种文件具有PIC(position independent code)特性、表明他是不依赖于内存地址的.

uClinux使用的是FLAT格式、是一种紧凑的格式、仅仅包含code和data、允许重定位.

重定位的基本原理是,不采用绝对调用,所有的不可确定的调用利用中间变量来进行保存,这些中间变量有的在启动的时候有OS来处理,有的被libc的runtime在动态连接的时候进行处理。

flthdr chmod

chmod

Magic: bFLT
Rev: 4
Entry: 0x50
Data Start: 0x1c920
Data End: 0x21200
BSS End: 0x26ba0
Stack Size: 0x4e20
Reloc Start: 0x21200
Reloc Count: 0x6e0
Flags: 0x1 ( Load-to-Ram )

可以清楚的看到data,bss,stack的大小,其中的reloc表示relocation, 就是重定位使用的中间数据,这些中间数据由kernel负责初始化。
[编辑]
内存分配

这里仅仅描述user space的内存管理

内存分配很痛苦、因为没有vm、导致不能动态的分配stack和heap、实际上uClinux是没有传统heap的。stack的大小是可以在编译期间指定的、一旦被加载其大小不可改变。

malloc、 free的实现是基于uClinux kernel维护的一个大的free memory pool。相当于全部的进程在共享同一个heap。优 点是所有被free的内存立刻回到memory pool、可以被其他的进程使用。缺点的碎片可能会使你在分配内存的时候失败。因为没有VM碎片的整理是不可能的。因此、我们在coding的时候要对此 有充分的考虑。uClinux使用mmap来映射实现 malloc、使用mmap是有一定代价的、每次分配大约有56个字节的管理成本。

因为没有VM、uClinux不能试图在内存中移动数据、可能导致明明看起来有足够的内存、但却不能加载程序。
[编辑]
进程

fork 的问题、fork 是没有被实现的、只能使用vfork。fork的实现机制是copy-on-write。因为在uClinux里面没有VM、copy- on-write就不存在了。使用vfork之后主进程就会被suspend起来、让子进程继续执行、直到子进程调用了exit或者exec之后内存才会 被释放。

而且请特别注意、vfork的机制里面子进程和父进程是使用同一段内存的、这意味着子进程对变量的修改对于父进程是可见的。
[编辑]
共享库

linux 共享库的目的在于减少内存和硬盘的空间消耗、核心会保证每个共享库的代码段在内存中只有一份、通过VM将共享库的代码映射到使用他的进程内存空间中去、而 且、核心会根据进程的情况来决定使用他的哪一部分内存地址。这些的动作是由核心完成的、开发人员对此基本上不需要了解。

因为没有VM、最初的uClinux里面是没有共享库的。

一直到uClinux XIP and shared lib patches的出现。

XIP 是execute in position, 当使用XIP的时候OS仅仅为application分配data,bss,stack,而text就是用rom中的。通过这样的方式减少了对内存的消 耗。实际上XIP是设计给nor flash使用的, 因为nor flash被简单的映射到内存空间中来,因此,这个工作相对比较简单。在使用人ramdisk的时候理论上也是可以XIP的,但是由于系统设计的模块化, 这个工作变得很复杂。

目前的XIP支持仅仅限于romfs,因为romfs是唯一可以确保文件连续性的fs,而且他是只读的,进一步简化了工作。

当使用XIP的时候share library自动的被支持了,因为存贮即使执行的位置,他们的地址绝对不会冲突。

不使用XIP的时候,也可以支持share library. uClinux中的share library结构不复杂而且有很多的限制。

其 基本原理如下:使用一个静态数据段,程序和share lib一起使用。每一个share库都被分配一个唯一的数字编号,该编号是有上限的,通过全局静态区可以访问到一个数组,share lib的编号就是数组的下标。通过arm的Static Base Register,每一个函数都可以都可以找到静态区查讯数据。
[编辑]
查看内存情况

mem_map 是linux内部的变量名,用于管理所有的page,每个page的大小为4K,在下面的内容中,每一个字母表示一个page的使用情况

cat /proc/mem_map

0x0c000000: RRRRRRRRssss1111ss1RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
0x0c040000: RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
0x0c080000: RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
0x0c0c0000: RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
0x0c100000: RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
0x0c140000: RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
0x0c180000: RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
0x0c1c0000: RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
0x0c200000: RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
0x0c240000: RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
0x0c280000: RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
0x0c2c0000: RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
0x0c300000: RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
0x0c340000: RRs1[]1ssssss1[]ss[]ss[][][][][]sss1[][][]ssssssssssssssss[]ssss
0x0c380000: sssssssss1[]11sssX[]ssXsXXXs[]XXXsXXXXXXXXXXXXXXXXXXXXXXXX[]ss1s
0x0c3c0000: s1sss--11-ssss-ss-[][]sss-s--1ss[][][]-----sssss----------------
0x0c400000: -------s11---s--------------------------------------------------
0x0c440000: ----------------------------------------------------------------
0x0c480000: ----------------------------------------------------------------
0x0c4c0000: ----------------------------------------------------------------
0x0c500000: ----------------------------------------------------------------
0x0c540000: ----------------------------------------------------------------
0x0c580000: ----------------------------------------------------------------
0x0c5c0000: ----------------------------------------------------------------
0x0c600000: ----------------------------------------------------------------
0x0c640000: ----------------------------------------------------[===========
0x0c680000: ===============================]------------[==================]
0x0c6c0000: ------------[============][===================]---------[=======
0x0c700000: ==]-[==========================][==================][===========
0x0c740000: =======================================================]----[===
0x0c780000: ======]-[==========]------[=][==================================
0x0c7c0000: ===============================================================]

init Mem: 125152 Slack: 80 Shared: 0
inetd Mem: 55840 Slack: 771 Shared: 0
portmap Mem: 115680 Slack: 5144 Shared: 0
telnetd Mem: 72256 Slack: 1747 Shared: 0
sh Mem: 97952 Slack: 566 Shared: 0
sh Mem: 92384 Slack: 549 Shared: 0
cat Mem: 191136 Slack: 1401 Shared: 0
Total Mem: 750400 Slack: 10258 Shared: 0

Active: 5, inactive: 27, free: 698
Free pages: 698 (2792kB), %2 frag, %1 slack
Free blks: 17 min=1 max=614 avg=41
Used blks: 18 min=1 max=965 avg=75

R : 保留页面 B : 块设备 X : 映射内存 s : Slab 1 : 被分配的1个页面 = : 被分配的连续的页面

cat /proc/slabinfo

cache-name | num-active-objs | total-objs | object size | num-active-slabs | total-slabs | num-pages-per-slab

slabinfo - version: 1.1 kmem_cache 57 68 112 2 2 1 tcp_tw_bucket 0 0 96 0 0 1






Tags:

0 Comments:

Post a Comment

<< Home