2009年3月17日星期二

DM642 RF框架小结

RF5是德州仪器TI公司新近推出的DSP软件开发的起步代码参考框架,它以DSP/BIOS为基础,利用其中的数据处理元素和数据通信元素方便快捷地完成DSP软件的设计与开发RF5是RF的最新版本,其区别于RF1和RF3的显著特点是其支持动态对象创建和支持线程(任务)挂起功能,因此适合系统较复杂的应用场合。

RF5
主要实现三个功能,存储管理,线程模型和通道封装,对于不同的应用,我们只需在这三个元素上做修改,而对于整个应用程序,不用从头设计,这样大大简化了开发者的开发难度,缩短了开发时间。

RF5适用于包含大量的算法,且要求多线程,多通道的应用,如图像处理,多媒体应用等,以Ti提供的实例mpeg2loopback为例,对RF5进行分析。

RF5包含的元素有:

1 线程(Thread):

RF5框架包含四个基本的数据处理元素,处在最顶层的是线程,线程总是顺序的执行所包含的通道,线程在一个比较高级的级别上把数据组织在一起,他们可以与别的线程,设备驱动以及别的类似结构进行通讯,在mpeg2lookback实例中,创建了三个线程分别是tskVideoInput,tskVideoOutput和tskProcess。每个线程都在不断的等待消息,处理数据,并将结果发送给其他的线程,同时有可能还要发送同步消息给其他线程已实现线程间的通讯,这里使用的机制是SCOM模块。

每个线程都是进行数据处理的一个单元,有的是处理简单的,有的处理是相对复杂的过程,简单的线程可以不包括任何的通道,而进行复杂数据处理的线程有可能包含多个的通道。

2 通道(Channel):

RF5提供了一种通道结构是为了更方便的封装算法,这可以理解通道为并行里的串行,因为线程的执行就是由通道的串行执行来完成的,一个通道包含一组核(Icell),其主要任务就是依次顺序的执行所包含的核,主要执行的流程为:首先需要初始化通道模块,然后建立通道对象,注册该通道所包含的核对象,接着依次执行每个核,执行完成了后就销毁对象,最后退出。每个通道可以包含多个核,每个核都要进行初始化后在调用CHAN_regCell注册。

通道对象的结构如下:

typedef struct CHAN_Obj {
ICELL_Obj *cellSet; /* set of cells in the channel */
Uns cellCnt; /* number of cells in the cellSet */
CHAN_State state; /* state of the channel */
Bool (*chanControlCB)(CHAN_Handle chanHandle); /* optional control
function */
} CHAN_Obj;
线程一般不定义通道对象,但是在CHAN_open()调用中初始化它们。CHAN_open()的最后一个参数是通道属性(CHAN_Attrs)结构体的地址。如果最后一个参数是NULL,那么CHAN_open()使用默认的参数。如果要想使用不同的参数,就要声明一个CHAN_Attrs的结构体,并需初始化为CHAN_ATTRS宏所定义的初值,然后根据需要可以修改其中相应的域的值,通常,其中的通道状态参数CHAN_State
state域默认为CHAN_ACTIVE,以及通道控制回调函数参数域Bool
(*chanControlCB)(CHAN_Handle
chanHandle)默认为NULL。如果通道控制回调函数不是空,那么在任何的cell调用执行之前都会先调用此回调函数。
一个典型的设置,一个线程为每一个通道建立一个CHAN_Obj对象(或者一组类似的对象),并且为每一个cell建立一个ICELL_Obj对象(或者是与每个通道相对应的一组ICCE_Obj对象).在线程初始化ICELL_Obj之后就会调用下面的函数:
备注其中的cell 指向cell 对象的指针, inputIcc/outputIcc是相应的cell的 ICC
对象,这个调用计算单元需要的空间,并分配给定的ICC对象给单元cell。
   CHAN_regCell( cell, inputIcc, 1, outputIcc, 1 );
   当所有的cells都已经创建并初始化之后,线程调用CHAN_open()函数来为每一个指定的通道(chanNum)传递cell对象(cellList)。这个函数创建所有的XDAIS算法,并且如果单元细胞定义了cellOpen函数,则会调用每一个单元细胞的cellOpen函数,.
   CHAN_open( chanList[ chanNum ], cellList, numCells, NULL/* default
attributes */ );
最后,在运行时,线程为每一个通道(chanNum)调用CHAN_execute函数开始执行:
   CHAN_execute( chanList[ chanNum ], NULL /* arg to cells */ );

3 核(Icell):

核实际上就是ICELL接口对象,基于RF5的应用常常包含大量的算法和通道,为了便于算法集中到应用中,RF5提出了核的概念,一个核就是包含一种XDAIS算法的容器,一个RF5通道对象可以包含多个核,也即是包含多个算法,通道通过核来调用算法,实际上,真正的数据处理是在XDAIS算法,核只是提供一个调用算法的接口,这大大简化了工作量,便于移植。

该接口包含一个重要的结构:ICELL_Fxns,该结构包含一组函数指针。通道通过调用这些函数来调用算法,其中包含一个关键的函数cellExecute,这个函数的功能是调用XDAIS算法来执行,上面的通道执行函数CHAN_execute就包含了每个cellExecute的调用。

4 ICC模块

ICC模块是用来管理在核之间以及核与其他线程之间的数据通讯,我们知道线程间的数据传输是通过SCOM模块来实现的,每个ICC模块管理一个或者多个ICC对象,每个核都有一组输入和输出ICC对象。这些对象是通过CHAN_regCell()来注册到相应的通道里。

5 同步通讯机制(SCOM)

ThrProcess中包含两个SCOM对象,RF5使用SCOM对象来实现线程的通讯。SCOM消息时用户自定义的一个机构,一个线程通过调用SCOM_putMsg()函数将SCOM消息放置一个SCOM队列中,发送给其他的线程,或者通过调用SCOM_getMsg()函数从队列中获取消息,一般情况下,发送消息指明接收线程所要读取的数据缓冲区的地址(以指针形式),接收消息指明发送线程所要写入的数据缓冲区的地址,在mape2loopback实例中,thrProcess要从thraVideoInput接收消息,并发送消息给thrVideoOutput输出图像。RF5使用SCOM来实现线程间的通讯:thrProcess拥有一些缓冲区,需要thrVideoInput写或thrVideoOutput读,所以thrProcess通过SCOM告诉thrVideoIput和thrVideoOutput线程数据缓冲区的地址,同时还要保证两个线程不会同时访问同一个缓冲区。thrProcess创建了两种消息以分别和两个线程进行通讯,scomMsgRx和scomMsgTx,scomMsgRx指定了被thrVideoInput写的缓冲区地址,scomMsgTx指定了被thrVideoOutput读的缓冲区地址。

在实际的操作中,可是将SCOM看作是种同步标记,她用来区分模块内存是否正在被其他线程所使用,这样就可以放置内存访问的冲突。整个系统中包含很多存储区,这些内存区很有可能在某一时刻正在被某一线程访问,为了保证在任意时刻只有一个线程访问某一块内存,当前正在访问这一内存块的线程通过发送SCOM消息给与这一内存块有关联的线程,告诉他,"我正在访问呢,你等会再来吧"。当他访问完后,放弃了这一内存块的占有权,再通过SCOM消息告诉相关联的线程,"我用完了,你可以用了。"于是相关联的线程就可以访问了。

6 ALGRF模块—算法的实例化Algorithm Instantiation

ALGRF
Module用DSP/BIOSMEM内存管理器来创建和删除XDAIS算法的模块。参考框架服务简化XDAIS部件的使用。所有符合XDAIS标准的算法都必须使用一个标准的接口——IALG接口。ALGRF使用算法的IALG来实现对XDAIS算法的实例化。任何符合XDAIS标准的算法都可以被ALGRF所使用。

用户代码不必直接的调用ALGRF函数,这个工作由CHAN和其他的库函数来完成。例外的是cell
wrappers中的ALGRF_activate/deactivate序列化:如果cell中的XDAIS算法执行IALG_active/deactivate函数,细胞需要调用两个ALGRF函数来完成。

三个模块来简化IALG接口创建算法对象,RF5使用ALGRF模块来创建,配置,删除XDAIS算法实例。ALG模块使用CCStudio作为通用目的使用,并且不用DSP/BIOS
MEM模块分配内存.ALGMIN是三个中的最小应用。

一般情况下,三个模块是相互包含的,但是只有一个能在应用程序中使用。ALGRF适于RF5的需要和别的RF级别,而不适合紧凑和底端的如RF1级别的系统。

ALGRF与ALG相比,有以下的优势:

1 更小的代码脚本(代码量):

作为一个通用的模块,ALG支持malloc/free 运行时库和DSP/BIOS
MEM_alloc/MEM_free动态内存分配方式,ALGRF只支持DSP/BIOS分配,这为设计者省了代码空间,另外ALGRF保证没有无用代码的存在.只有被调用的函数才被连接到执行程序中。

2 暂存区支持:

  下面的API在ALGRF中介绍的实例:
ALGRF_Handle ALGRF_createScratchSupport(IALG_Fxns *fxns, IALG_Handle
parent,
IALG_Params *params, Void *scratchBuf, Uns scratchSize)
除了当IALG_SCRATCH内存区域(内部数据缓冲区)被请求,该函数能根据算法请求分配内存。作为替代,scratchBuf和scratchSize这两个参数表明这一缓冲区已经在应用中存在,而且可以被当前的算法重新使用.这就可以受约束的共享资源有限的内存区。

3 从DSP/BIOS堆标签中做提取:

  ALGRF使用DSP/BIOS 的MEM模块动态分配内存。一个堆标记或内存段名可以传给
MEM_alloc()来表明分配到哪一个堆.如下:
     /* Configure the ALGRF module to use:
     * 1st argument - memory for internal heap
     * 2nd argument - memory for external heap
     */
  ALGRF_setup( INTERNALHEAP, EXTERNALHEAP );
  这让我们可以指定算法的数据分配位置。例如,如果使用EXTERNALHEAP作为两个参数,那么算法的数据就被定位在外部存储器。

一台主机接多套键盘鼠标显示器,实现多人共用一台电脑


是不是场面很震撼,大学时就梦想着能一个宿舍的共用一台电脑了(那时候穷啊,刚开始宿舍就一台电脑啊!)。看看人家是怎么做到的:

Build a Six-Headed, Six-User Linux System
By Bob Smith

Introduction
A Multi-Seat Linux Box
: This tutorial shows how to build a multi-head,
multi-user Linux box using a recent distribution of Linux and standard USB
keyboards and mice. Xorg calls this arrangement a "multi-seat" system.

Advantages of a Multi-Seat System: The advantages of multi-seat systems in
schools, Internet cafe's, and libraries include more than just saving
money. They include much lower noise pollution, much less power
consumption, and lowered space requirements. For many applications power
and noise budgets are as important as initial cost.

Requirements: To build a multi-seat system you need a video adapter,
keyboard, and mouse for each seat. For six seats, you'll also need a
motherboard with an AGP slot and five available PCI slots. In our test
system we used USB keyboards and mice exclusively, but you can use a PS/2
keyboard and mouse for one seat if you wish.

Xorg 6.9 or later is required, but this already ships with many of the
major distributions. Our test system uses the free version of Mandriva
2006 and we did not rebuild the kernel or install any additional packages.


Overview
We divide the implementation of a multi-seat system into five main steps:
Select and Install the Hardware
Install Linux
Record Hardware Configuration
Modify xorg.conf
Modify gdm.conf
After installing the hardware and installing Linux, we read the hardware
configuration from the lspci command from from the /proc/bus/input/devices
file. Most of the effort in setting up a multi-seat system is in
transcribing the hardware information into the xorg.conf file.


Step 1: Select and Install the Hardware
Selecting the Hardware: There are few set rules dictating what hardware to
use in your multi-seat system. Of necessity, some of the keyboards and
mice need to use USB, but there is no minimum CPU or memory requirements.
We suggest building and testing a multi-seat system using a computer that
you already have, and use the test results to help scale your hardware
requirements. You may be surprised how modest the CPU and memory
requirements are for a multi-seat system that is used only for web
browsing.

If possible, try to use accelerated video cards, but for increased
reliability, avoid video cards with on-board fans. Use recent video cards;
older video cards often have a problem sharing the PCI bus. We've had good
luck with nVidia cards but you can try recent cards from other
manufacturers too.

Hardware for our test system: For our system we chose to use video cards
based on the nVidia MX4000 chipset. They are accelerated, have no fans,
and it was nice having one driver for all six video cards. The downside of
nVidia is that the driver is closed source and you need to download and
install it. If you use an nVidia card, be sure to check their web site for
the recommended BIOS settings for your cards.

We used an ECS 755-A2 motherboard with an AMD64-3200 processor and 1 GB of
RAM. Our power supply is a CoolMax 140mm Power Supply and the CPU heat
sink is a Thermaltake "Sonic Tower". During our testing we added a low
noise fan to cool the video cards. Airflow is in at the bottom, past the
video cards, up past the CPU cooler and out through the power supply. This
airflow seemed to work pretty well. At quiescence, the CPU temperature was
31C, rising to only 38C after fifteen minutes of kernel compile. The
current from the mains at quiescence was 0.25 amps, and during a kernel
compile it was 0.35 amps.

You will probably need some USB hubs to connect all of the keyboards and
mice. One problem to think about before permanently installing the
hardware is cable management. Seven power cords, six monitor cables, three
USB hubs, six keyboard cables, and six mice cables: that is a lot of
cabling!


Step 2: Install Linux
Multi-seat capability is provided by Xorg 6.9/7.0 which already ships with
most of the major distributions. When you install Linux, you might want to
install all of the window managers including fluxbox and twm. If you are
going to use the nVidia drivers, be sure to install the kernel source too.

Do the installation with all of the hardware connected and powered up.
Mandriva did a great job detecting and configuring all six of our video
heads. Select a default run level of 3 so that X does not start
automatically after boot. You can check the installation by logging in and
running startx. If all has gone well you should be able to move your mouse
across all six monitors.

Mandriva makes up to ten entries in the /dev/input directory. We needed
twelve since we had six keyboards and mice. We increased the limit to
sixteen by changing the line in /etc/udev/ruled.d/50-mdk.rules from:
KERNEL=="event[0-9]*", NAME="input/%k", MODE="0600"
to:
KERNEL=="event[0-9a-f]*", NAME="input/%k", MODE="0600"


Step 3: Record Hardware Configuration
All hardware in our computer has a name that distinguishes it from similar
hardware in the computer. In this step we record the names for each of our
video heads, keyboards, and mice. Let's start with the video cards.

Video cards are identified by their address on the PCI bus. We can list
the hardware on the PCI buses using the lspci command. On our test system,
the lspci command gives the following result:
lspci | grep VGA
00:09.0 VGA compatible controller: nVidia Corporation NV18 [GeForce4 MX
4000 AGP 8x] (rev c1)
00:0a.0 VGA compatible controller: nVidia Corporation NV18 [GeForce4 MX
4000 AGP 8x] (rev c1)
00:0b.0 VGA compatible controller: nVidia Corporation NV18 [GeForce4 MX
4000 AGP 8x] (rev c1)
00:0c.0 VGA compatible controller: nVidia Corporation NV18 [GeForce4 MX
4000 AGP 8x] (rev c1)
00:0d.0 VGA compatible controller: nVidia Corporation NV18 [GeForce4 MX
4000 AGP 8x] (rev c1)
01:00.0 VGA compatible controller: nVidia Corporation NV18 [GeForce4 MX
4000 AGP 8x] (rev c1)
The bus address is the first field in the lines above. The number before
the colon identifies which PCI bus (computers often have more than one),
and the second number gives the card address on the bus. You will need to
know these addresses to build the xorg.conf configuration file.

The mice are easy to locate. Each mouse has an entry in the /dev/input
directory. An ls can identify the mice.
ls /dev/input/mouse*
/dev/input/mouse0 /dev/input/mouse2 /dev/input/mouse4
/dev/input/mouse1 /dev/input/mouse3 /dev/input/mouse5
The keyboards are identified as a /dev/input/eventN file. Do a more of
/proc/bus/input/devices. Each keyboard will have an entry that specifies
the event file. The following two entries are for the first two keyboards
in our system.
more /proc/bus/input/devices

I: Bus=0003 Vendor=046e Product=530a Version=0001
N: Name="BTC Multimedia USB Keyboard"
P: Phys=usb-0000:00:03.3-4.2.1/input0
H: Handlers=kbd event6
B: EV=120003
B: KEY=1000000000007 ff87207ac14057ff febeffdfffefffff fffffffffffffffe
B: LED=1f

I: Bus=0003 Vendor=046e Product=530a Version=0001
N: Name="BTC Multimedia USB Keyboard"
P: Phys=usb-0000:00:03.3-4.4.1/input0
H: Handlers=kbd event7
B: EV=120003
B: KEY=1000000000007 ff87207ac14057ff febeffdfffefffff fffffffffffffffe
B: LED=1f

A table is a nice way to view all of the above information.
Seat Video Card Keyboard
(/dev/input/) Mouse
(/dev/input/)
0 00:09:0 event6 mouse0
1 00:10:0 event7 mouse1
2 00:11:0 event8 mouse2
3 00:12:0 event9 mouse3
4 00:13:0 event10 mouse4
5 01:00:0 event11 mouse5

Note the slight change in how the video cards are addressed. Also, you'll
find the numbering of the keyboards and mice easier if you plug each mouse
into the same hub as its corresponding keyboard. Don't worry too much
about matching the video head to the keyboard. After setting everything up
you can move the monitors or the keyboards around as needed.


Step 4: Build xorg.conf
The xorg.conf file has sections to describe keyboards, mice, video cards,
monitors, screens, and seats. Most of the work in setting up a multi-seat
system is correctly copying the information in the above table into the
appropriate section of the xorg.conf file. Shown below is our
configuration for seat 5. You should be able to use this configuration as
a prototype for your additional seats. Note the places where the keyboard,
mouse, and video card information is located. Since we were borrowing
monitors for our test, we forced all of the monitors to be flat panel
displays with a 1024 by 768 resolution.
# Seat 5
Section "InputDevice"
Identifier "Keyboard5"
Driver "evdev"
Option "Device" "/dev/input/event11"
Option "XkbModel" "pc105"
Option "XkbLayout" "us"
Option "XkbOptions" "compose:rwin"
EndSection

Section "InputDevice"
Identifier "Mouse5"
Driver "mouse"
Option "Protocol" "ExplorerPS/2"
Option "Device" "/dev/input/mouse5"
Option "ZAxisMapping" "6 7"
EndSection

Section "Device"
Identifier "device5"
Driver "nvidia"
VendorName "NVIDIA Corp."
BoardName "NVIDIA GeForce4 (generic)"
BusID "PCI:0:13:0"
EndSection

Section "Monitor"
Identifier "monitor5"
ModelName "Flat Panel 1024x768"
HorizSync 31.5 - 48.5
VertRefresh 40.0 - 70.0
ModeLine "768x576" 50.0 768 832 846 1000 576 590 595 630
ModeLine "768x576" 63.1 768 800 960 1024 576 578 590 616
EndSection

Section "Screen"
Identifier "screen5"
Device "device5"
Monitor "monitor5"
DefaultDepth 24
SubSection "Display"
Virtual 1024 768
Depth 24
EndSubSection
EndSection

Section "ServerLayout"
Identifier "seat5"
Screen 0 "Screen5" 0 0
InputDevice "Mouse5" "CorePointer"
InputDevice "Keyboard5" "CoreKeyboard"
EndSection

There is a simple trick to help verify that all the numbers in the
xorg.conf file are right -- pass the file through sort and uniq.
cat /etc/X11/xorg.conf | sort | uniq
The output of the above command string will make obvious any errors in
numbering the various keyboards and such.

Testing Your Xorg.conf File: It is a good idea to test your configuration
and to sort out the keyboards and mice by bringing up the heads one at a
time. Login remotely so that you are not using any of the video heads.
Enter the following commands for each of the six heads (0 to 5). (The
commands below are for head 5.)
X -novtswitch -sharevts -nolisten tcp -layout seat5 :5 &
xterm -display :5 &
If the above command fails, examine the error messages and check the
xorg.conf file. If the command succeeds, use the xterm to help identify
which keyboard and mouse go to which head. The keyboards, mice, and video
cards are enumerated in the same order on every boot, so you will only
have to move things around during the initial set up.

The above commands might be sufficient if you don't need user logins. For
example, a six headed kiosk might need only X and a web browser on each
head.


Step 5: Modify gdm.conf
If you want user logins you will need to modify the configuration for your
preferred display manager. The directions given here are for gdm but the
changes are very similar for kdm, or for the X display manager, xdm.

Modify the [servers] section near the bottom of the /etc/X11/gdm/gdm.conf
file to tell gdm which X servers to start. The lines should be:
0=Standard0
1=Standard1
2=Standard2
3=Standard3
4=Standard4
5=Standard5
You need to tell gdm how to start the X server on each head. The lines to
do this are:
[server-Standard5]
name=Standard server
command=/usr/X11R6/bin/X -nolisten tcp -novtswitch -sharevts -layout seat5
flexible=true
You'll need a section like the above for each head. The server name,
"Standard5" in the above example, must match the name given in the
[servers] section. Customize the X command line options to meet the
requirements of your particular system.

Once everything is configured, you should be able to start graphical
logins by switching to runlevel 5.
telinit 5
If everything works, make the default runlevel 5 by editing /etc/inittab
or by setting it using drakconf.


Test Results, Costs, and Problems
Performance Results: Between resets, we found performance to be excellent
for six users doing typical PC tasks, including web browsing, email, word
processing, and games. The accelerated graphics cards seemed to do most of
the work so that even arcade style games and web-based video did not put
much of a load on the CPU. If "3200" is an accurate assessment of the
performance of the AMD64-3200, then a CPU with a performance of "1600"
would have been more than sufficient.

Cost: Not including the monitor, each seat in our system cost about $67.
This includes $40 for the MX4000 based video card, $20 for a USB keyboard,
$5 for a USB mouse, and $2 for half of a USB hub. Our test system uses
expensive keyboards that have a built-in USB hub which we intended for per
user flash disks or audio players.

The shared part of our system cost about $520. This includes $180 for the
CPU, $50 for the motherboard, $90 for RAM, and $50 for the CPU heat sink.
The case, power supply, and disk drive had a combined cost of about $150.

We give these prices just for comparison. You may find lower prices that
these and we'd certainly recommend that you replace our $230 CPU and
motherboard with an Athlon 2800+ set that costs about $80. We have not
included the cost of the monitors since these prices are in free fall and
your particular needs and tastes may dictate what you spend.

Problems: Did you catch the phrase "between resets" above? While the
system worked very well, it was extremely unstable. In particular, we got
a kernel oops fairly often when we logged out. A syslog trace of one such
oops is available here(http://www.linuxtoys.org/multiseat/hydra_hang.txt). We've tried several things to fix this problem
including:
turning APIC off and on
reducing the number of heads
trying the 'nv' and 'vesa' drivers
using NoInt10
upgrading to the official X11R6.9 release
upgrading to the 2.6.15 kernel
using xdm and fvwm instead of gdm and Gnome
The problem persists. Please let bsmith at linuxtoys dot org know if you
have any ideas that might help fix this problem.

A much less severe problem is that some programs assume that there is a
single user on the PC. Screen savers can take a lot of CPU power and both
KDE and Gnome complain if they don't have audio output. Any shared
resource, such as audio or a CD burner, can be a problem.

Longer term, we will need to address security issues surrounding
multi-seat computers. Whether from students or cafe patrons, these systems
are going to come under deliberate, malicious attack. Can we trust KDE and
Gnome to withstand such attacks?


Summary

A multi-head, multi-user Linux system is now possible using commodity PC
hardware and standard Linux distributions. Multi-seat Linux PCs seem
inevitable given the potential savings in cost, noise, and power.


Further Reading

http://www.linuxtoys.org/multiseat/multiseat.html


Chris Tyler's page: Chris Tyler provided support at almost every step of
the way in this project. His web site has a HOWTO that also describes how
to set up a multi-seat system. Chris is something of an expert in X and
I'm looking forward to his next book which will contain some of the
material presented here. Chris' web site is at:
http://blog.chris.tylers.info/

Xorg man pages: Xorg provides a full set of manual pages that describe the
xorg.conf file and all of the commands used in getting X-Windows to run.
The manual page for xorg.conf is at:
http://wiki.x.org/X11R6.9.0/doc/html/xorg.conf.5.html

The manual pages for the X commands are at:
http://wiki.x.org/X11R6.9.0/doc/html/manindex1.html

tmpfs介绍

介绍 tmpfs
如果我必须一下子说清楚 tmpfs,我会说 tmpfs
就象虚拟磁盘(ramdisk),但不一样。象虚拟磁盘一样,tmpfs 可以使用您的
RAM,但它也可以使用您的交换分区来存储。而且传统的虚拟磁盘是个块设备,并需要一个
mkfs 之类的命令才能真正地使用它,tmpfs
是一个文件系统,而不是块设备;您只是安装它,它就可以使用了。总而言之,这让
tmpfs 成为我有机会遇到的最好的基于 RAM 的文件系统。
tmpfs 和 VM
让我们来看看 tmpfs 更有趣的一些特性吧。正如我前面提到的一样,tmpfs
既可以使用 RAM, 也可以使用交换分区。刚开始这看起来可能有点武断,但请记住
tmpfs 也是我们知道的"虚拟内存文件系统"。而且,您可能也知道,Linux
内核的虚拟内存资源同时来源于您的 RAM 和交换分区。内核中的 VM
子系统将这些资源分配到系统中的其它部分,并负责在后台管理这些资源,通常是透明地将
RAM 页移动到交换分区或从交换分区到 RAM 页。
tmpfs 文件系统需要 VM 子系统的页面来存储文件。tmpfs
自己并不知道这些页面是在交换分区还是在 RAM 中;做这种决定是 VM
子系统的工作。tmpfs 文件系统所知道的就是它正在使用某种形式的虚拟内存。
不是块设备
这里是 tmpfs 文件系统另一个有趣的特性。不同于大多数"标准的"文件系统,如
ext3、ext2、XFS、JFS、ReiserFS 和其它一些系统,tmpfs
并不是存在于一个底层块设备上面。因为 tmpfs 是直接建立在 VM
之上的,您用一个简单的 mount 命令就可以创建 tmpfs 文件系统了。# mount
tmpfs /mnt/tmpfs -t tmpfs
执行这个命令之后,一个新的 tmpfs 文件系统就安装在
/mnt/tmpfs,随时可以使用。注意,不需运行 mkfs.tmpfs
;事实上,那是不可能的,因为没有这样的命令存在。在 mount
命令执行之后,文件系统立即就被安装并且可以使用了,类型是 tmpfs 。这和
Linux 虚拟磁盘如何使用大相径庭;标准的 Linux 虚拟磁盘是
块设备,所以在使用它们之前必须用您选择的文件系统将其格式化。相反,tmpfs
是一个文件系统。所以,您可以简单地安装它就可以使用了。

Tmpfs 的优势
动态文件系统的大小
您可能想知道我们前面在 /mnt/tmpfs 安装的 tmpfs
文件系统有多大。这个问题的答案有点意外,特别是在和基于磁盘的文件系统比较的时候。/mnt/tmpfs
最初会只有很小的空间,但随着文件的复制和创建,tmpfs
文件系统驱动程序会分配更多的
VM,并按照需求动态地增加文件系统的空间。而且,当 /mnt/tmpfs
中的文件被删除时,tmpfs 文件系统驱动程序会动态地减小文件系统并释放 VM
资源,这样做可以将 VM 返回到循环当中以供系统中其它部分按需要使用。因为 VM
是宝贵的资源,所以您一定不希望任何东西浪费超出它实际所需的 VM,tmpfs
的好处之一就在于这些都是自动处理的。 请参阅 参考资料。
速度
tmpfs 的另一个主要的好处是它闪电般的速度。因为典型的 tmpfs
文件系统会完全驻留在 RAM
中,读写几乎可以是瞬间的。即使用了一些交换分区,性能仍然是卓越的,当更多空闲的
VM 资源可以使用时,这部分 tmpfs 文件系统会被移动到 RAM 中去。让 VM
子系统自动地移动部分 tmpfs 文件系统到交换分区实际上对性能上是
好的,因为这样做可以让 VM 子系统为需要 RAM
的进程释放空间。这一点连同它动态调整大小的能力,比选择使用传统的 RAM
磁盘可以让操作系统有好得多的整体性能和灵活性。
没有持久性
这看起来可能不象是个积极因素,tmpfs
数据在重新启动之后不会保留,因为虚拟内存本质上就是易失的。我想您可能猜到了
tmpfs 被称为"tmpfs"的一个原因,不是吗?然而,这实际上可以是一件好事。它让
tmpfs 成为一个保存您不需保留的数据(如临时文件,可以在 /tmp 中找到,还有
/var 文件系统树的某些部分)的卓越的文件系统。

使用 tmpfs
为了使用 tmpfs,您所需要的就是启用了"Virtual memory file system
support(以前是 shm fs)"选项的 2.4
系列内核;这个选项在内核配置选项的"File systems"部分。一旦您有了一个启用了
tmpfs 的内核,您就可以开始安装 tmpfs 文件系统了。其实,在您所有的 2.4
内核中都打开 tmpfs 选项是个好主意,不管您是否计划使用
tmpfs。这是因为您需要内核 tmpfs 支持来使用 POSIX 共享的内存。然而, System
V共享的内存不需要内核中有 tmpfs 就 可以工作。注意,您 不需要为了让 POSIX
共享的内存工作而安装 tmpfs 文件系统;您只需要在内核中支持 tmpfs
就可以了。POSIX
共享的内存现在使用得不太多,但这种情况可能会随着时间而改变。
避免低 VM 情况
tmpfs 根据需要动态增大或减小的事实让人疑惑:如果您的 tmpfs
文件系统增大到它耗尽了 所有虚拟内存的程度,而您没有剩余的 RAM
或交换分区,这时会发生什么?一般来说,这种情况是有点讨厌。如果是 2.4.4
内核,内核会立即锁定。如果是 2.4.6 内核,VM
子系统已经以很多种方式得到了修正,虽然耗尽 VM
并不是一个美好的经历,事情也不会完全地失败。如果 2.4.6
内核到了无法分配更多 VM 的程度,您显然不愿意不能向 tmpfs
文件系统写任何新数据。另外,可能会发生其他一些事情。首先,系统的其他一些进程会无法分配更多的内存;通常,这意味着系统多半会变得
极度缓慢而且几乎没有响应。这样,超级用户要采取必要的步骤来缓解这种低 VM
的情况就会很困难,或异常地耗时。
另外,内核有一个内建的最终防线系统,用来在没有可用内存的时候释放内存,它会找到占用
VM 资源的进程并终止该进程。不幸的是,这种"终止进程"的解决方案在 tmpfs
的使用增加引起 VM 耗尽的情况下通常会导致不良后果。以下是原因。tmpfs
本身不能(也不应该)被终止,因为它是内核的一部分而非一个用户进程,而且也没有容易的方法可以让内核找出是那个进程占满了
tmpfs 文件系统。所以,内核会错误地攻击它能找到的最大的占用 VM
的进程,通常会是 X 服务器(X server),如果您碰巧在使用它。所以,您的 X
服务器会被终止,而引起低 VM 情况的根本原因(tmpfs)却没有被解决。Ick.
低 VM:解决方案
幸运的是,tmpfs
允许您在安装或重新安装文件系统的时候指定文件系统容量的最大值上限。实际上,从
2.4.6 内核到 2.11g 内核,这些参数只能在
安装时设置,而不是重新安装时,但我们可以期望在不久的将来可以在重新安装时设置这些参数。tmpfs
容量最大值的最佳设置依赖于资源和您特定的 Linux
主机的使用模式;这个想法是要防止一个完全使用资源的 tmpfs
文件系统耗尽所有虚拟内存结果导致我们前面谈到的糟糕的低 VM 情况。寻找好的
tmpfs 上限值的一个好方法是使用 top
来监控您系统的交换分区在高峰使用阶段的使用情况。然后,确保指定的 tmpfs
上限稍小于所有这些高峰使用时间内空闲交换分区和空闲 RAM 的总和。
创建有最大容量的 tmpfs 文件系统很容易。要创建一个新的最大 32 MB 的 tmpfs
文件系统,请键入:# mount tmpfs /dev/shm -t tmpfs -o size=32m
这次,我们没有把 tmpfs 文件系统安装在 /mnt/tmpfs,而是创建在
/dev/shm,这正好是 tmpfs 文件系统的"正式"安装点。如果您正好在使用
devfs,您会发现这个目录已经为您创建好了。
还有,如果我们想将文件系统的容量限制在 512 KB 或 1 GB
以内,我们可以分别指定 size=512k 和 size=1g
。除了限制容量,我们还可以通过指定 nr_inodes=x
参数限制索引节点(文件系统对象)。在使用 nr_inodes 时, x
可以是一个简单的整数,后面还可以跟一个 k 、 m 或 g
指定千、百万或十亿(!)个索引节点。
而且,如果您想把上面的 mount tmpfs 命令的等价功能添加到
/etc/fstab,应该是这样: tmpfs /dev/shm tmpfs size=32m 0 0
在现存的安装点上安装
在以前使用 2.2 的时候,试图在
已经安装了东西的安装点再次安装任何东西都会引发错误。然而,重写后的内核安装代码使多次使用安装点不再成为问题。这里是一个示例的情况:假设我们有一个现存的文件系统安装在
/tmp。然而,我们决定要开始使用 tmpfs 进行 /tmp
的存储。过去,您唯一的选择就是卸载 /tmp 并在其位置重新安装您新的 tmpfs/tmp
文件系统,如下所示: # umount /tmp# mount tmpfs /tmp -t tmpfs -o size=64m
可是,这种解决方案也许对您不管用。可能有很多正在运行的进程在 /tmp
中有打开的文件;如果是这样,在试图卸载 /tmp
时,您就会遇到如下的错误:umount: /tmp: device is busy
然而,使用最近的 2.4 内核,您可以安装您新的 /tmp
文件系统,而不会遇到"device is busy"错误:# mount tmpfs /tmp -t tmpfs -o
size=64m
用一条命令,您新的 tmpfs /tmp 文件系统就被安装在
/tmp,并安装在已经安装的不能再被直接访问的分区
之上。然而,虽然您不能访问原来的
/tmp,任何在原文件系统上还有打开文件的进程都可以继续访问它们。而且,如果您
unmount 基于 tmpfs 的 /tmp,原来安装的 /tmp
文件系统会重新出现。实际上,您在相同的安装点上可以安装任意数目的文件系统,安装点就象一个堆栈;卸载当前的文件系统,上一个最近安装的文件系统就会重新出现。
绑定安装

使用绑定安装,我们可以将所有甚至
部分已经安装的文件系统安装到另一个位置,而在两个安装点可以同时访问该文件系统。例如,您可以使用绑定安装来安装您现存的根文件系统到
/home/drobbins/nifty,如下所示: # mount --bind / /home/drobbins/nifty
现在,如果您观察 /home/drobbins/nifty
的内部,您就会看到您的根文件系统(/home/drobbins/nifty/etc、/home/drobbins/nifty/opt
等)。而且,如果您在根文件系统修改文件,您在 /home/drobbins/nifty
中也可以看到所作的改动。这是因为它们是同一个文件系统;内核只是简单地为我们将该文件系统映射到两个不同的安装点。注意,当您在另一处安装文件系统时,任何安装在绑定安装文件系统
内部的安装点的文件系统都不会随之移动。换句话说,如果您在单独的文件系统上有
/usr,我们前面执行的绑定安装就会让 /home/drobbins/nifty/usr
为空。您会需要附加的绑定安装命令来使您能够浏览位于
/home/drobbins/nifty/usr 的 /usr 的内容: # mount --bind /usr
/home/drobbins/nifty/usr
绑定安装部分文件系统
绑定安装让更妙的事情成为可能。假设您有一个 tmpfs
文件系统安装在它的传统位置 /dev/shm,您决定要开始在当前位于根文件系统的
/tmp 使用 tmpfs。虽然可以在 /tmp(这是可能的)安装一个新的 tmpfs
文件系统,您也可以决定让新的 /tmp 共享当前安装的 /dev/shm
文件系统。然而,虽然您可以在 /tmp 绑定安装 /dev/shm 就完成了,但您的
/dev/shm 还包含一些您不想在 /tmp 出现的目录。所以,您怎么做呢?这样如何:
# mkdir /dev/shm/tmp# chmod 1777 /dev/shm/tmp# mount --bind /dev/shm/tmp
/tmp
在这个示例中,我们首先创建了一个 /dev/shm/tmp 目录,然后给它 1777 权限,对
/tmp 适当的许可。既然我们的目录已经准备好了,我们可以安装,也只能安装
/dev/shm/tmp 到 /tmp。所以,虽然 /tmp/foo 会映射到
/dev/shm/tmp/foo,但您没有办法从 /tmp 访问 /dev/shm/bar 文件。
正如您所见,绑定安装非常强大,让您可以轻易地修改文件系统设计,丝毫不必忙乱。