Install Chinese fonts support for Unbuntu
- [Ubuntu] - Linux for human beings
- 软件仓库分类:universe
- 安装包文件名:xfonts-wqy
- 安装方法:sudo apt-get install xfonts-wqy
- 对应WQY版本:0.6.0
- 维护人:Carlos Liu (carlosliu # users_sourceforge_net)
FvwmButtons, also known as GoodStuff, is sometimes overlooked by new
fvwm users, despite being the most powerful software for creating
desktop panels available today.
I've written this guide to introduce FvwmButtons to new users, and
take anyone interested step by step through creating a simple panel.
Hopefully this will help get you started a little quicker than the man
page alone :).
This is the panel I am going to create.
http://dev.gentoo.org/~taviso/goodstuff1.png
It's very simple, has a set of nine buttons that can be bound to
applications or window controls. It also has an xclock along the top.
Of course, FvwmButtons has many, many features I havn't mentioned
here, but this should be enough to get started :)
Step 1: Planning
Fvwm uses a flat text based configuration, which is not an intuitive
method for designing user interfaces. The solution is to use a
graphics package to create a template to work from. You can use any
package you like, The GIMP, xpaint, dia, or even xfig.
Here is a screenshot of me planning this panel in dia..
http://dev.gentoo.org/~taviso/goodstuff2.png
As you can see I have an outline and the approximate layout of the
buttons all plotted in dia. Don't worry about this template being
perfect, we are just going to use it to estimate the dimensions in the
next step.
Step 2: Dimensions
Now that you have a template to work from, you can calculate what the
minimum grid size you will need in order to contain your buttons.
This is a lot simpler than it sounds, we just need to know how many
rows and columns we should split our panel into. Each button can take
up any whole number of grid squares, so we just have to make sure we
have enough.
http://dev.gentoo.org/~taviso/goodstuff3.png
As you can see, we need a minimum grid of 7 rows and 3 columns so that
each button occupies a whole number of grid squares. The top button
requires one row and 3 columns, the other buttons need 2 rows and 1
columns.
Step 3: Create Buttons
Now that we have the dimensions needed, we can make an absolute
minimum FvwmButtons configuration to test the dimensions.
You can tweak the button geometries and grid size until everything looks right.
代码:
DestroyModuleConfig LaunchTime: *
*LaunchTime: Rows 7
*LaunchTime: Columns 3
*LaunchTime: (3x1)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
As you can see, each configuration line for our panel starts with an
asterisk, then the panel alias. Lines that dont use brackets are
settings, lines that do are button definitons. The buttons defined
here only have one setting, how many rows and columns they need.
You can enter this in your fvwm2rc and restart, or paste it into an
FvwmConsole. I've used DestroyModuleConfig so that if you paste the
configuration into FvwmConsole twice, fvwm knows that you are not
trying to continue the same configuration.
Now lets try starting the panel, enter the following into your FvwmConsole
代码:
Module FvwmButtons -g 178x207 LaunchTime
The -g specifies the Geometry, it tells FvwmButtons how big you want
the panel to be (and also where you want it to appear).
Hopefully, you should see a window like this
http://dev.gentoo.org/~taviso/goodstuff4.png
Not very exciting yet, but don't worry, move on to the next step where
we will configure the buttons and add the bindings.
Step 4: Fill in the blanks
Swallowing is what FvwmButtons calls Reparenting, it basically means
any application window can be used as a button on your panel. So lets
use this concept to swallow an xclock into our new panel.
First lets find a command line for xclock that looks suitable for our panel.
代码:
xclock -bg '#31658c' -fg white -digital -face 'Aquafont:size=11'
-strftime '%a, %d %b %Y %H:%M'
This is what I have used. Now lets tell our panel how to start the clock.
代码:
*LaunchTime: (3x1, Swallow "xclock" `Exec xclock -bg '#31658c' -fg
white -digital -face 'Aquafont:size=11' -strftime '%a, %d %b %Y
%H:%M'`)
The first setting is the Rows and Columns we want, then the Swallow
command. the next argument is the name of the window FvwmButtons
should look out for, followed by the Fvwm command needed to start the
window.
Here is our new Panel:
代码:
DestroyModuleConfig LaunchTime: *
*LaunchTime: Rows 7
*LaunchTime: Columns 3
*LaunchTime: (3x1, Swallow "xclock" `Exec xclock -bg '#31658c' -fg
white -digital -face 'Aquafont:size=11' -strftime '%a, %d %b %Y
%H:%M'`)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
Enter the configuration into your FvwmConsole, and start the panel to
make sure everything has worked, hopefully you will see a window like
this:
http://dev.gentoo.org/~taviso/goodstuff5.png
Now for the next button, Let's make it a launcher for The GIMP.
代码:
*LaunchTime: (1x2, Title "gimp", Icon graphics_paint_edit.png)
As you can see, we have the dimensions, a Title and an Icon. All we
need now is to define an Action. Actions are responses to Clicks, so
lets say we want the first mouse button to start the gimp.
代码:
Action(Mouse 1) `Exec gimp`
Lets enter this into the button definition.
代码:
*LaunchTime: (1x2, Title "gimp", Icon graphics_paint_edit.png,
Action(Mouse 1) `Exec gimp`)
The configuration should now look like this:
代码:
DestroyModuleConfig LaunchTime: *
*LaunchTime: Rows 7
*LaunchTime: Columns 3
*LaunchTime: (3x1, Swallow "xclock" `Exec xclock -bg '#31658c' -fg
white -digital -face 'Aquafont:size=11' -strftime '%a, %d %b %Y
%H:%M'`)
*LaunchTime: (1x2, Title "gimp", Icon graphics_paint_edit.png,
Action(Mouse 1) `Exec gimp`)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
*LaunchTime: (1x2)
Test out the panel, if everything looks okay fill in the rest of the buttons.
代码:
DestroyModuleConfig LaunchTime: *
*LaunchTime: Rows 7
*LaunchTime: Columns 3
*LaunchTime: (3x1, Center, Swallow "xclock" `Exec xclock -bg '#31658c'
-fg white -digital -face 'Aquafont:size=11' -strftime '%a, %d %b %Y
%H:%M'`)
*LaunchTime: (1x2, Title "gimp", Icon graphics_paint_edit.png,
Action(Mouse 1) `Exec gimp`)
*LaunchTime: (1x2, Title "xmag", Icon telescope.png, Action(Mouse 1)
`Exec xmag`)
*LaunchTime: (1x2, Title "xcalc", Icon calculator.png, Action(Mouse 1)
`Exec xcalc`)
*LaunchTime: (1x2, Title "mozilla", Icon browser_ship-wheel.png,
Action(Mouse 1) `Exec mozilla`)
*LaunchTime: (1x2, Title "run", Icon gears.png, Action(Mouse 1) `Exec gmrun`)
*LaunchTime: (1x2, Title "gvim", Icon gvim.png, Action(Mouse 1) `Exec gvim`)
*LaunchTime: (1x2, Title "move", Icon hardware_mouse.png, Action(Mouse
1) `Pick Move`)
*LaunchTime: (1x2, Title "close", Icon bomb.png, Action(Mouse 1) `Pick Close`)
*LaunchTime: (1x2, Title "shade", Icon window.png, Action(Mouse 1)
`Pick WindowShade True`)
Start the panel and you should see something like:
http://dev.gentoo.org/~taviso/goodstuff6.png
Step 5: Finalise Panel
Test all your buttons, make sure everything is working, Hopefully it
is and you can setup Colorsets, Fonts, Frames, Padding and any other
setting you want!
代码:
Colorset 30 fg black, bg #c6c3c6, RootTransparent buffer, Tint #efebef 65
DestroyModuleConfig LaunchTime: *
*LaunchTime: Rows 7
*LaunchTime: Columns 3
*LaunchTime: Font "xft:Bitstream Vera Sans Mono:style=Roman:size=8"
*LaunchTime: Colorset 30
*LaunchTime: Frame 1
*LaunchTime: (3x1, Center, Swallow "xclock" `Exec xclock -bg '#31658c'
-fg white -digital -face 'Aquafont:size=11' -strftime '%a, %d %b %Y
%H:%M'`)
*LaunchTime: (1x2, Title "gimp", Icon graphics_paint_edit.png,
Action(Mouse 1) `Exec gimp`)
*LaunchTime: (1x2, Title "xmag", Icon telescope.png, Action(Mouse 1)
`Exec xmag`)
*LaunchTime: (1x2, Title "xcalc", Icon calculator.png, Action(Mouse 1)
`Exec xcalc`)
*LaunchTime: (1x2, Title "mozilla", Icon browser_ship-wheel.png,
Action(Mouse 1) `Exec mozilla`)
*LaunchTime: (1x2, Title "run", Icon gears.png, Action(Mouse 1) `Exec gmrun`)
*LaunchTime: (1x2, Title "gvim", Icon gvim.png, Action(Mouse 1) `Exec
"gvim" gvim`)
*LaunchTime: (1x2, Title "move", Icon hardware_mouse.png, Action(Mouse
1) `Pick Move`)
*LaunchTime: (1x2, Title "close", Icon bomb.png, Action(Mouse 1) `Pick Close`)
*LaunchTime: (1x2, Title "shade", Icon window.png, Action(Mouse 1)
`Pick WindowShade True`)
Try out the new Panel!
代码:
Module FvwmButtons -g 178x207 LaunchTime
Hopefully you should see something similar to this:
http://dev.gentoo.org/~taviso/goodstuff7.png
Now all you have to do is set any Style options you want, and decide
how to start your panel. Did you notice the extra argument to Exec on
the gvim button? Try pressing it, notice the button will stay down
until a window called gvim appears! You can do this for all the
buttons, if you like it.
Maybe you would like LaunchTime to always be visible?
代码:
Style LaunchTime StaysOnTop
And lets start it everytime we login
代码:
AddToFunc StartFunction
+ I Module FvwmButtons -g 178x207 LaunchTime
And finally, lets add it to a menu:
代码:
AddToMenu MyRootMenu
+ "Start LaunchTime" Module FvwmButtons -g 178x207 LaunchTime
edit: 21/05/2004 changed wording of planning section, using dia instead.
内核洋文用 kernel,我刚才翻了一下词典,kernel 中文意思是内核、核心、中心、精髓的意思;也是果仁、果核的意思。从字面理解,kernel 是一事物的中心,植物的果实最重要的也是果仁和果核;:) 由此我们可以推断内核是操作系统的中心。
我们知道Linus Torvalds 开发了Linux ,其实他开发的就是内核,按内核官方主页的理解,这个内核就是Linux ;其它的扩展和应用都是围绕内核而展开的。所有Linux应用程序都会和内核发生直接或者间接的接触;比如硬件需要内核支持,网络的通信也需要内核支持; 文件系统更需要内核支持... ...
直言我的能力的不行,如果您想了解和学习解操作系统,我写的教程只是初级应用,理论性的东西不是一言两语能说的清楚的,更不是应用者能说的清楚的。
二、为什么需要编译内核和管理内核
硬件是需要内核支持才行,有些硬件的支持没有被编入内核,这也需要我们重编内核;内核的包含的不仅仅是设备的驱动,还有其它的内容,比如网络协议的支持, 防火墙的支持... ... 比如iptables的实现,有些功能是需要内核支持的,如果内核与iptables相关的内容没有被编入,iptables 相关的功能就无法实现;
三、内核编译方法
请参考:《编译内核操作流程 ──为新手指南》
四、管理内核模块的相关命令
1、lsmod 列加以挂载的内核模块;
lsmod 是列出目前系统中已加载的模块的名称及大小等;另外我们还可以查看 /proc/modules ,我们一样可以知道系统已经加载的模块;
[root@localhost beinan]# lsmod
2、modinfo 查看模块信息;
modinfo 可以查看模块的信息,通过查看模块信息来判定这个模块的用途;
[root@localhost beinan]# moinfo 模块名
举例:
[root@localhost beinan]# modinfo ne2k-pci
filename: /lib/modules/2.6.11-1.1369_FC4/kernel/drivers/net/ne2k-pci.ko
author: Donald Becker / Paul Gortmaker
description: PCI NE2000 clone driver
license: GPL
parmtype: debug:int
parmtype: options:array of int
parmtype: full_duplex:array of int
parm: debug:debug level (1-2)
parm: options:Bit 5: full duplex
parm: full_duplex:full duplex setting(s) (1)
vermagic: 2.6.11-1.1369_FC4 686 REGPARM 4KSTACKS gcc-4.0
depends: 8390
alias: pci:v000010ECd00008029sv*sd*bc*sc*i*
alias: pci:v00001050d00000940sv*sd*bc*sc*i*
alias: pci:v000011F6d00001401sv*sd*bc*sc*i*
alias: pci:v00008E2Ed00003000sv*sd*bc*sc*i*
alias: pci:v00004A14d00005000sv*sd*bc*sc*i*
alias: pci:v00001106d00000926sv*sd*bc*sc*i*
alias: pci:v000010BDd00000E34sv*sd*bc*sc*i*
alias: pci:v00001050d00005A5Asv*sd*bc*sc*i*
alias: pci:v000012C3d00000058sv*sd*bc*sc*i*
alias: pci:v000012C3d00005598sv*sd*bc*sc*i*
alias: pci:v00008C4Ad00001980sv*sd*bc*sc*i*
srcversion: 6ACE95F441CD26DF9DC31C2
上面的例子是我们查看 ne2k-pci 这个模块的信息,通过查看,我们知道ne2k-pci 模块是8029网卡(PCI NE2000 clone driver)的驱动;模块是位于 /lib/modules/2.6.11-1.1369_FC4/kernel/drivers/net/ 中ne2k-pci.ko
我们现在常用的网卡也有8139的,8139网卡所用的驱动是 8139too ;查查看?
[root@localhost beinan]# modinfo 8139too
我们再查查vfat 和ntfs 的模块信息;
[root@localhost beinan]# modinfo vfat
[root@localhost beinan]# modinfo ntfs
自己尝试一下;
注意: 模块名是不能带有后缀的,我们通过modprobe -l 所看到的模块,都是带有.ko 或.o后缀;
3、modprobe 挂载新模块以及新模块相依赖的模块
modprobe 我们常用的功能就是挂载模块,在挂载某个内核模块的同时,这个模块所依赖的模块也被同时挂载;当然modprobe 也有列出内核所有模块,还有移除模块的功能;下在我们举个例子说一说咱们常用的功能和参数;
modprobe [-v] [-V] [-C config-file] [-n] [-i] [-q] [-o ] [parameters...]
modprobe -r [-n] [-i] [-v] ...
modprobe -l -t [ -a ...]
上面是modprobe 的用法,具体更为详细的帮助,我们可以查看 man modprobe ;
[root@localhost beinan]# modprobe -c
modprobe -c 可以查看modules 的配置文件,比如模块的别名是什么等;
[root@localhost beinan]# modprobe -l
modprobe -l 是列出内核中所有的模块,包括已挂载和未挂载的;通过modprobe -l ,我们能查看到我们所需要的模块,然后根据我们的需要来挂载;其实modprobe -l 读取的模块列表就位于 /lib/modules/'uname -r' 目录中;其中uname -r 是内核的版本;
[root@localhost beinan]# uname -r
2.6.11-1.1369_FC4
[root@localhost beinan]# ls /lib/modules/2.6.11-1.1369_FC4/
通过上面的命令,自己试试看?
[root@localhost beinan]# modprobe 模块名 注:挂载一个模块;
举例:
[root@localhost beinan]# modprobe ne2k-pci 注:挂载 ne2k-pci 模块;
[root@localhost beinan]# modprobe vfat 注:挂载vfat 模块
[root@localhost beinan]# modprobe ntfs 注:挂载ntfs 模块
[root@localhost beinan]# lsmod 注:列出已挂载模块, 我们会看到ne2k-pci ,vfat ,ntfs的模块 ;
注意: 模块名是不能带有后缀的,我们通过modprobe -l 所看到的模块,都是带有.ko 或.o后缀;
[root@localhost beinan]# modprobe -r 模块名 注:移除已加载的模块,和rmmod 功能相同;
注意: 模块名是不能带有后缀的,我们通过modprobe -l 所看到的模块,都是带有.ko 或.o后缀;
[root@localhost beinan]# modprobe -r 模块名
举例:
[root@localhost beinan]# modprobe -r ne2k-pci
就说这么多吧,更为详细的还是用 man modprobe 来查看和尝试;
4、rmmod 移除已挂载模块;
命令格式:
rmmod 模块名
注意: 模块名是不能带有后缀的,我们通过modprobe -l 所看到的模块,都是带有.ko 或.o后缀;
举例:
[root@localhost beinan]# rmmod vfat 注:移除已挂载的模块vfat
5、depmod 创建模块依赖关系的列表
这个模块管理工具是创建模块依赖关系的列表,有几个参数我们注意一下就行了,目前的的Linux 发行版所用的内核是2.6x版本,是自动解决依赖关系,所以这个命令知道就行了;模块之前也有依赖关系,比如我们想驱动USB 移动硬盘,目前有两种驱动,一种是udev ,在内核中有,但目前不太稳定;另一种办法是用usb-storage驱动,而usb-storage 依赖的模块是scsi 模块,所以我们要用usb-storage 的模块,也得把scsi 编译安装;
再举个例子:sata的硬盘,在Linux中的设备表示的是/dev/sd* ,比如 /dev/sda,/dev/sdb 等... 系统要驱动 sata硬盘,则需要把sata在内核中选中,或编译成模块,或内置于内核之中,在此同时,还需要在内核中选中ide ,scsi 的支持等;
depmod 工具的洋文原意:depmod ― program to generate modules.dep and map files.(我译的:为modules.dep 文件或映射文件创建依赖关系)
[root@localhost beinan]# depmod -a 注:为所有列在/etc/modprobe.conf 或/etc/modules.conf 中的所有模块创建依赖关系,并且写入到modules.dep文件;
[root@localhost beinan]# depmod -e 注:列出已挂载但不可用的模块;
[root@localhost beinan]# depmod -n 注:列出所有模块的依赖关系,但仅仅是输出出来 (Write the dependency file on stdout only)
注:modules.dep 位于 /lib/modules/内核版本 目录
比如 Fedora Core 4.0 中,系统默认的内核:
[root@localhost beinan]# ls /lib/modules/2.6.11-1.1369_FC4/modules.dep
/lib/modules/2.6.11-1.1369_FC4/modules.dep
6、insmod 挂载模块;
insmod 这个工具,和modprobe 有点类似,但功能上没有modprobe 强,modprobe 在挂载模块是不用指定模块文件的路径,也不用带文件的后缀.o 或.ko ;而insmod 需要的是模块的所在目录的绝对路径,并且一定要带有模块文件名后缀的(modulefile.o 或modulesfile.ko );
对于这个工具,我们只是介绍一下, 并不推荐使用。因为模块有依赖关系,对于新手来说,可能不知道这个模块依赖和哪个模块依赖;
举例:
[root@localhost beinan]# insmod /lib/modules/2.6.11-1.1369_FC4/kernel/drivers/net/tg3.ko
我们要到 /lib/modules/内核版本 uname -r 的命令输出/kernel/drivers 中找相对应的模块才行,要有绝对路径,而且必须要用到文件名的全称,不能把文件名的后缀省略;
五、与内核模块加载相关的配置文件;
1、模块的配置文件 modules.conf 或 modprobe.conf
内核模块的开机自动挂载模块一般是位于一个配置文件,一般的Linux发行版本都有 /etc/modules.conf 或 /etc/modprobe.conf 。比如Fedora Core 4.0 内核模块开机自动加载文件是 /etc/modprobe.conf ;在这个文件中,一般是写入模块的加载命令或模块的别名的定义等;比如我们在modules.conf 中可能会发行类似的一行 ;
alias eth0 8139too
而8029的网卡应该是
alias eth0 ne2k-pci
这样系统启动的时候,首先会modprobe 8139too ,然后再为8139too 指定别名为 eth0,然后我们在登录的时候,用 ifconfig 就会查看到网卡的IP 等情况,当然您得为网卡设置IP 才行;
一般的情况下,modproe.conf 或modules.conf的内容 是我们用相应的硬件配置工具而生成的;如果您的硬件驱动是没有被内核支持,您自己到硬件的厂商下载而来的驱动。一般的情况下都有安装和帮助文件。他们的驱 动在配置时,他会写入硬件的支持到modules.conf 或modprobe.conf 文件中。
再比如我们的声卡在modules.conf 或modprobe.conf 中也有相应的内容,这是由alsaconf 配置工具生成的,明白了吧;同理网卡在modprobe.conf 或modules.conf中的内容也是由网卡的配置工具而来的。
有些硬件是以内核模块的方式驱动的,模块一旦加载上就能用,也没有什么配置工具,比如vfat 和ntfs 的支持;如果是硬件驱动不以模块的方式支持,而是直接编入内核,也不会用在modprobe.conf 或 modules.conf 中加入什么内容;
如果您有些模块不能开机加载,您想让一些模块加机自动加载,就可以把modprobe 模块 直接写入配置文件;
2、内核模块其它配置文件
内核模块的其它配置文件还是需要了解的,比如 /lib/modules/内核版本目录下的几个文件;了解一下就行;比如:
[root@localhost beinan]# uname -r
2.6.11-1.1369_FC4
[root@localhost beinan]# ls /lib/modules/2.6.11-1.1369_FC4/
build misc modules.ccwmap modules.ieee1394map modules.isapnpmap modules.symbols source
kernel modules.alias modules.dep modules.inputmap modules.pcimap modules.usbmap
六、硬件驱动在系统中的目录;
硬件驱动在内核中以模块支持的目录;
硬件驱动是必须由内核支持的,无论是我们自己安装驱动,还是内核自带的驱动都是如此。硬件驱动如果是以内核模块支持的,驱动目录位于: /lib/modules/内核版本/kernel/目录 或 /lib/modules/内核版本/kernel/drivers 目录中;
[root@localhost beinan]# uname -r
2.6.11-1.1369_FC4
[root@localhost beinan]# ls /lib/modules/2.6.11-1.1369_FC4/kernel
arch crypto drivers fs lib net sound
注:只有驱动在内核中以模块的方法支持,驱动才位于 /lib/modules/相应的目录;如果是直接置入内核的,不会出现在/lib/modules驱动相关的目录;
七、自己编译驱动的办法;
如果是硬件厂商或者开源社区提供的驱动(没有集成在内核源码中的),编译驱动过程一般是./configure ;make;make install ,有时程序不提供./configure ,我们可以make或make install ,或者执行make;make install ;如果不能make install ,则需要我们自己复制.o或者.ko文件到 /lib/modules/内核版本/kernel/目录 或 /lib/modules/内核版本/kernel/drivers 目录中相应的驱动目录;
这个还是自己尝试吧,说也说不清楚,遇到问题后就知道怎么弄了;具体的还是驱动的REAME和INSTALL为准;
现在大多驱动都是在编译安装时,都自动复制.o或.ko 文件到内核模块目录,大多不用我们自己动手复制过去。如果您尝试编译安装声卡驱动 alsa-drivers 就会明白我所说的意思;
如果是我们通过重编内核来解决驱动问题,可以查看/usr/src/目录中的内核源码目录中的 Documentation 的REAME ;所有的帮助文件都在那里;
后记:
内核编译对新手来说是有点困难,我写过类似的文档也有好多篇,但是不是新手弟兄从中能学到点什么,我不太知道;毕竟我写的文档在内核文件告诉一些基本的流程和注意的事项;内核的配置只有多实践才能学会,在配置内核时,要多看看帮助;
内核模块管理方面我在本文中已经写了一些,大体上就这些,如果想要知道更为详细的,只能是自己看man 和--help了,我写文档也无非是查看这些东西,然后实践再写给大家;我能写出来,我想您的能力并不一定比我差,应该超出我才对;
原文:[http://www.xxlinux.com/linux/article/development/kernel/20051228/775_2.html ]
Linux内核主要由五个子系统组成:进程调度,内存管理,虚拟文件系统,网络接口,进程间通信。
1. 进程调度(SCHED):控制进程对CPU的访问。当需要选择下一个进程运行时,由调度程序选择最值得运行的进程。可运行进程实际上是仅等待CPU资源的 进程,如果某个进程在等待其它资源,则该进程是不可运行进程。Linux使用了比较简单的基于优先级的进程调度算法选择新的进程。
2. 内存管理(MM)允许多个进程安全的共享主内存区域。Linux的内存管理支持虚拟内存,即在计算机中运行的程序,其代码,数据,堆栈的总量可以超过实际 内存的大小,操作系统只是把当前使用的程序块保留在内存中,其余的程序块则保留在磁盘中。必要时,操作系统负责在磁盘和内存间交换程序块。内存管理从逻辑 上分为硬件无关部分和硬件有关部分。硬件无关部分提供了进程的映射和逻辑内存的对换;硬件相关的部分为内存管理硬件提供了虚拟接口。
3. 虚拟文件系统(VirtualFileSystem,VFS)隐藏了各种硬件的具体细节,为所有的设备提供了统一的接口,VFS提供了多达数十种不同的文 件系统。虚拟文件系统可以分为逻辑文件系统和设备驱动程序。逻辑文件系统指Linux所支持的文件系统,如ext2,fat等,设备驱动程序指为每一种硬 件控制器所编写的设备驱动程序模块。
4.网络接口(NET)提供了对各种网络标准的存取和各种网络硬件的支持。网络接口可分为网络协议和网络驱动程序。网络协议部分负责实现每一种可能的网络传输协议。网络设备驱动程序负责与硬件设备通讯,每一种可能的硬件设备都有相应的设备驱动程序。
5.进程间通讯(IPC) 支持进程间各种通信机制。
处于中心位置的进程调度,所有其它的子系统都依赖它,因为每个子系统都需要挂起或恢复进程。一般情况下,当一个进程等待硬件操作完成时,它被挂起;当操作 真正完成时,进程被恢复执行。例如,当一个进程通过网络发送一条消息时,网络接口需要挂起发送进程,直到硬件成功地完成消息的发送,当消息被成功的发送出 去以后,网络接口给进程返回一个代码,表示操作的成功或失败。其他子系统以相似的理由依赖于进程调度。
各个子系统之间的依赖关系如下:
进程调度与内存管理之间的关系:这两个子系统互相依赖。在多道程序环境下,程序要运行必须为之创建进程,而创建进程的第一件事情,就是将程序和数据装入内存。
进程间通信与内存管理的关系:进程间通信子系统要依赖内存管理支持共享内存通信机制,这种机制允许两个进程除了拥有自己的私有空间,还可以存取共同的内存区域。
虚拟文件系统与网络接口之间的关系:虚拟文件系统利用网络接口支持网络文件系统(NFS),也利用内存管理支持RAMDISK设备。
内存管理与虚拟文件系统之间的关系:内存管理利用虚拟文件系统支持交换,交换进程(swapd)定期由调度程序调度,这也是内存管理依赖于进程调度的唯一原因。当一个进程存取的内存映射被换出时,内存管理向文件系统发出请求,同时,挂起当前正在运行的进程。
除了这些依赖关系外,内核中的所有子系统还要依赖于一些共同的资源。这些资源包括所有子系统都用到的过程。例如:分配和释放内存空间的过程,打印警告或错误信息的过程,还有系统的调试例程等等。
系统数据结构
在linux的内核的实现中,有一些数据结构使用频度较高,他们是:
task_struct.
Linux 内核利用一个数据结构(task_struct)代表一个进程,代表进程的数据结构指针形成了一个task数组(Linux中,任务和进程是相同的术 语),这种指针数组有时也称为指针向量。这个数组的大小由NR_TASKS(默认为512),表明Linux系统中最多能同时运行的进程数目。当建立新进 程的时候,Linux为新进程分配一个task_struct结构,然后将指针保存在task数组中。调度程序一直维护着一个current指针,他指向 当前正在运行的进程。
Mm_struct
每个进程的虚拟内存由一个mm_struct结构来代表,该结构实际上包含了当前执行映像的有关信息,并且包含了一组指向vm_area_struct结构的指针,vm_area_struct结构描述了虚拟内存的一个区域。
Inode
虚拟文件系统(VFS)中的文件、目录等均由对应的索引节点(inode)代表。每个VFS索引节点中的内容由文件系统专属的例程提供。VFS索引节点只 存在于内核内存中,实际保存于VFS的索引节点高速缓存中。如果两个进程用相同的进程打开,则可以共享inade的数据结构,这种共享是通过两个进程中数 据块指向相同的inode完成。
Linux的具体结构
所谓具体结构是指系统实现的结构。
Linux的具体结构类似于抽象结构,这种对应性是因为抽象结构来源于具体结构,我们的划分没有严格依照源代码的目录结构,且和子系统的分组也不完全匹配,但是,它很接近源代码的目录结构。
尽管前面的讨论的抽象结构显示了各个子系统之间只有很少的依赖关系,但是具体结构的5个子系统之间有高度的依赖关系。我们可以看出,具体结构中的很多依赖关系并没有在抽象结构中出现。
Linux内核源代码
目前,较新而又稳定的内核版本是2.0.x和2.2.x,因为版本不同稍有差别,因此如果你想让一个新的驱动程序既支持2.0.x,又支持2.2.x,就 需要根据内核版本进行条件编译,要作到这一点,就要支持宏LINUX_VERSION_CODE,假如内核的版本用a.b.c来表示,这个宏的值就是 216a+28b+c。要用到指定内核版本的值,我们可以用KERNEL_VERSION宏,我们也可以自己去定义它。
对内核的修改用补丁文件的方式发布的。Patch实用程序用来用来对内核源文件进行一系列的修改。例如:你有2.2.9的源代码,但想移到2.2.10。就可以获得2.2.10的补丁文件,应用patch来修改2.2.9源文件。例如:
$ cd /usr/src/linux
$ patch �Cpl < patch-2.2.10
Linux 内核源代码的结构
Linux内核源代码位于/usr/src/linux目录下。
/include子目录包含了建立内核代码时所需的大部分包含文件,这个模块利用其他模块重建内核。
/init 子目录包含了内核的初始化代码,这是内核工作的开始的起点。
/arch子目录包含了所有硬件结构特定的内核代码。如:i386,alpha
/drivers子目录包含了内核中所有的设备驱动程序,如块设备和SCSI设备。
/fs子目录包含了所有的文件系统的代码。如:ext2,vfat等。
/net子目录包含了内核的连网代码。
/mm子目录包含了所有内存管理代码。
/ipc子目录包含了进程间通信代码。
/kernel子目录包含了主内核代码。
从何处开始阅读源代码?
摘要:
几乎所有工业领域的设备都是通过网络控制的。 用户界面作为一个简单的终端程序运行在与主控程序不同的硬件上, 通过网络接收和发送数据, 并且对时间不是很敏感(比方说:初始化参数和显示测量结果)。 在下面的示意图中使用绿色的箭头显示:![[gui frontend]](http://www.linuxfocus.org/common/images2/article350/frontend_en.png)
#######################################
# .fvwm2rc
# changed by shanlimin 2005-10-20
#######################################
## ==================================================================
## 图示路径设定
ImagePath +:/usr/share/icons/Bluecurve
ImagePath +:/usr/share/icons/Bluecurve/16x16/apps
ImagePath +:/usr/share/icons/Bluecurve/32x32/apps
ImagePath +:/usr/share/icons/kdeclassic
ImagePath +:/usr/share/icons/kdeclassic/16x16/apps
ImagePath +:/usr/share/icons/kdeclassic/48x48/apps
ImagePath +:/usr/share/icons/kids
ImagePath +:/usr/share/icons
ImagePath +:/usr/local/share/ icons/
ImagePath +:/usr/local/share/icons/16x16
ImagePath +:/usr/share/pixmaps
ImagePath +:/usr/share/icons/hicolor/48x48/apps
ImagePath +:/usr/local/share/fvwm/icons
ImagePath +:$HOME/.fvwm/xp/xpm/
ImagePath +:$HOME/.fvwm/xp/window /
ImagePath +:$HOME/.fvwm/xp/myicons/
## ==================================================================
##环境变量
SetEnv fvwm_wallpaper_dir $[HOME]/background
SetEnv fvwm_wallpaper $[fvwm_wallpaper_dir]/bg0.jpg
SetEnv fvwm_icon_size 128
## ==================================================================
## 桌面设定
#EdgeResistance 250 10
EdgeScroll 100 100
ClickTime 300
DeskTopSize 2x1
## ==================================================================
## 初始化设定
DestroyFunc InitFunction
AddToFunc InitFunction
+ I Exec exec xscreensaver -no-splash
+ I exec fcitx &
#+ I Exec exec gkrellm
+ I Exec exec konsole --nomenubar --noscrollbar --tn xterm
#+ I Wait "konsole"
+ I All ("konsole") State 0
## ^^^^^^^ 载入中文输入法,启动屏幕保护程序,该函数只在第一次运行fvwm时调用,
## fvwm重启时不在调用,fvwm重启时调用的是ReStartFunction。
## 而启动和重启时都调用StartFunction
## ==================================================================
## 基本鼠标设定
## I = Immediate 即刻生效
## M = On Mouse Motion 鼠标动时
## C = On Click 按一下
## D = On Double Click 按两下
## H = On Button Held Down 按下不放
##关闭窗口---------------------------
DestroyFunc DestroyOnHold
AddToFunc DestroyOnHold I Raise
+ C Schedule 100 Close
#+ H Destroy
+ H Beep
+ I Next Raise
+ I $0 FlipFocus
AddToFunc Move-or-Raise-or-Shade
+ H Move
+ M Move
#+ C Raise
#用C感觉有延迟,用I就很好了
+ I Raise
+ D WindowShade
AddToFunc Maximize-Func
+ M Maximize 80 0
+ C Maximize 100 96
+ D Maximize 100 100
AddToFunc Move-or-Raise-or-Iconify
+ I Raise
+ M Move
+ D Iconify
AddToFunc Resize-or-Raise-or-Shade
+ H Resize
+ M Resize
#+ C Raise
+ I Raise
+ D WindowShade
AddToFunc Resize-or-Raise2
+ M Raise
+ M Resize
+ C RaiseLower
AddToFunc Iconify-and-Raise
+ I Iconify
+ I Raise
#------增加移动图标功能----------
DestroyFunc Move-or-DeIconify
AddToFunc Move-or-DeIconify I Raise
+ "M" Move
+ "D" Iconify
##
AddToFunc FuncFvwmSetTitleBindings
+ I Mouse 1 $0 A Move-or-Raise-or-Shade
AddToFunc FuncFvwmUnsetTitleBindings
+ I Mouse 1 $0 A -FuncFvwmSetTitleBindings TSF
Mouse 1 SF A Resize-or-Raise-or-Shade
## ^^^^^^^ 以上设定可使窗口缩起来。 参看了 fvwm-themes 包里面的设定方
## 法。
## 颜色设定
Colorset 0 Transparent, bg blue, fg white
## ^^^^^^^ 如果要用透明背色,就用上面的设定。
Style * MiniIcon xapp_mini.png
Style * Icon xapp_36x36.png, Color #2B5E78/#E7E7EF
## ^^^^^^^ 非使用窗口的图示及色彩。
Style * HilightFore black, HilightBack #E7E7EF
## ^^^^^^^ 使用窗口的色彩。
好久没有更新Blog了,最近沉迷于Linux,Blog荒于打理,实在不该,由今天开始,我们将开始"挣脱Windows的枷锁"系列文章的书写,主要的目的是帮助大家在Linux下搭建一个完整的,替代windows并好于windows的linux桌面环境。
很多人不使用linux桌面,其中一个很大的原因就是离不开Windows下的软件,其实linux的开源社区里有得的好用的工具,关键是看您会不会用而已,所以就有了我们的这个"挣脱Windows的枷锁"这一系列文章的开始。
网络上,linux的资料非常的丰富,我们这系列的文章基本上在网络上都可以找到类似的文章,我们基本做的就是将这些散落网络各处的文章收集整理的工作而已,应了一句活,世界上不缺少美,只是缺少发现美的眼睛而已,linux的桌面应用也是如此。
一直都想看《霍元甲》,但直到前几天才下载了部,所以,今天,我们现来从Linux下的电影播放来开始我们"挣脱"之旅。
相信对于Windows下的电影播放软件,用得最多、最方便的就是暴风影音(包括其他基于MPC的实现)了,那么在Linux下是否也有类似的软件的,答案就是 MPlayer。
MPlayer是Linux下最优秀的多媒体播放器之一,播放速度是最快的,支持的文件格式也是最多的。 一下是官方的介绍:
MPlayer是Linux 上的电影播放器(也能跑在许多其它Unices上,甚至非x86CPU上,参见移植部分)。它能使用众多的本地的,XAnim,RealPlayer,和 Win32 DLL编解码器,播放大多数MPEG,VOB,AVI,OGG,VIVO,ASF/WMV,QT/MOV,FLI,RM,NuppelVideo, yuv4mpeg,FILM,RoQ文件。你还能观看VideoCD,SVCD,DVD,3ivx,RealMedia,和DivX格式的电影(你根本不 需要avifile库)。mplayer的另一个大的特色是广泛的输出设备支持。它可以在X11,Xv,DGA, OpenGL,SVGAlib,fbdev,AAlib,DirectFB下工作,而且你也能使用GGI和SDL(由此可以使用他们支持的各种驱动模式) 和一些低级的硬件相关的驱动模式(比如Matrox,3Dfx和Radeon,Mach64,Permedia3)!他们大多数支持软件或者硬件缩放,因 此你能在全屏下观赏电影。MPlayer还支持通过硬件MPEG解码卡显示,诸如DVB 和DXR3与Hollywood+。可以使用European/ISO 8859-1,2(匈牙利语,英语,捷克语等等),西里尔语,韩语的字体的清晰放大并且反锯齿的字幕(支持10种格式),和on screen display(OSD)你又觉得如何?
这个播放器能够稳如泰山的播放被破坏的MPEG文件(对一些VCD有用),而它能播放著名的windows media player 都打不开的的坏的AVI文件。甚至,没有索引部分的AVI文件可播放,你能暂时由重建他们的索引-idx选择,或者用MEncoder永久重建,使你能够 在影片中搜索!如你所见,稳定和质量是最重要的事情,而且他的速度是也惊人的。
是否已经动心了,废话少说,我们现在开始安装,和linux下的其他软件一样,MPlayer有两种安装方式,一种是直接的二进制rpm包的安装方式,另外的就是通过源码自己编译了。
二进制rpm包的安装方式很简单,直接到这里下载Suse Mplayer RPM安装包: MPlayer-1.0pre7try3-1.i586.rpm,使用rpm -ivf MPlayer-1.0pre7try3-1.i586.rpm安装就可以了。
我们今天的重点是源代码编译安装的方式,二进制RPM安装的方式比较方便,但是因为是通用的安装,所以并没有特殊的优化,而源代码编译安装的方式可以根据我们自己的PC配置进行相应的优化,对于电影播放器来说,特定的优化来实现性能的提高是非常有益的。
首先到这里下载MPlayer的源代码:
$wget http://www4.mplayerhq.hu/MPlayer/releases/MPlayer-1.0pre7try2.tar.bz2
$bzip2 -d MPlayer-1.0pre7try2.tar.bz2
$tar xvf MPlayer-1.0pre7try2.tar
$cd MPlayer-1.0pre7try2
##添加中文支持##
MPlayer-1.0pre7try2$echo "gb18030"> help/help_mp-zh_CN.h.charset
因为MPlayer的源代码要求的Gcc环境还是gcc-2.95.3,不支持现在高版本的Gcc-4.X,所以我们需要对源代码打个Gcc-4x的补丁: mplayer-1.0_pre7-gcc4.patch,将该文件保存在MPlayer-1.0pre7try2目录下,然后使用一下命令打补丁:
MPlayer-1.0pre7try2$patch -p1 < mplayer-1.0_pre7-gcc4.patch
另外,为了免除字体安装的麻烦,我们再打一个Gtk2的补丁,让mplayer使用Gtk2,这样就支持utf-8的编码了。到这里下载补丁: mplayer-1.0_pre7-gtk2.patch,同样保存到MPlayer-1.0pre7try2目录下,执行一下命令:
MPlayer-1.0pre7try2$patch -p1 < mplayer-1.0_pre7-gtk2.patch
最后我们在编译前,我们需要现下载MPlayer解码器,到这里下载: all-20050412.tar.bz2
MPlayer-1.0pre7try2$wget http://www4.mplayerhq.hu/MPlayer/releases/codecs/all-20050412.tar.bz2
MPlayer-1.0pre7try2$ bzip2 -d all-20050412.tar.bz2
MPlayer-1.0pre7try2$tar xvf all-20050412.tar
创建一个目录用来存放,我们的编码器,目录位置及名称任意。
MPlayer-1.0pre7try2$mv all-20050412 /usr/lib/codecs
OK,准备工作做完,可以开始编译了。
配置,带GUI界面的MPlayer,解码器存放位置/usr/lib/codecs,支持zh_CN和en语言,utf-8编码,mplayer将安装在/opt/feiy/player/MPlayer1.0下:
MPlayer-1.0pre7try2$./configure --enable-gui with-codecsdir=/usr/lib/codecs \MPlayer-1.0pre7try2$make MPlayer-1.0pre7try2$make install
--with-win32libdir=/usr/lib/codecs with-reallibdir=/usr/lib/codecs \
--with-xanimlibdir=/usr/lib/codecs disable-inet6 --language=zh_CN,en \
--prefix=/opt/feiy/player/MPlayer1.0 charset=utf8
因为我们是从源代码安装的,源码中并没有带MPlayer皮肤,所以我们还需要安装一下MPlayer的皮肤,到这里下载MPlayer皮肤,官方提供好多款皮肤下载,我们这里下载默认的皮肤 Blue Skin
$wget http://www1.mplayerhq.hu/MPlayer/Skin/Blue-1.5.tar.bz2
$bzip -d Blue-1.5.tar.bz2
$tar xvf Blue-1.5.tar
$mv Blue $MPlayer1.0_install_path/share/mplayer/Skin/default/skin
然后将其移动到,MPlayer安装目录下的share/mplayer/Skin/default/skin 以上就安装好了MPlayer,在/opt/feiy/player/MPlayer1.0/bin目录下,就可以看到我们的mplayer,其中 mplayer是命令行方式的MPlayer播放器,gmplayer是GUI方式的MPlayer播放器,而mencoder是解码器。
MPlayer用法:
用法: mplayer [options] [url|path/]filename
基本选项: (包括所有选项的详细列表参见manpage!)
-vo 选择视频输出模式和设备(用'-vo help'查看列表)
-ao 选择音频输出模式和设备(用'-ao help'查看列表)
vcd:// 从设备而不是普通文件上播放VCD(video cd)track
dvd:// 从设备而不是普通文件上播放DVD title/track
-alang/-slang 选择DVD音轨/字幕的语言(使用两位的国家代码)
-ss 寻找指定的(多少秒或hh:mm:ss)位置
-nosound 不播放声音
-fs -vm -zoom 全屏播放选项(fullscr,vidmode chg,softw.scale)
-x -y 设置播放的分辨率(用于改变vidmode或软件缩放)
-sub 指定使用的字幕文件(参见-subfps, -subdelay)
-playlist 指定使用播放列表文件
-vid x -aid y 选择用于播放的视频(x)和音频(y)流
-fps x -srate y 改变视频(x fps)和音频(y Hz)率
-pp 使用后期处理滤镜(详细内容参见manpage/docs)
-framedrop 使用 frame-dropping (用于慢机器)
基本控制键: (完整的列表参见manpage, 同时也要检查一下 input.conf)
<- or -> 向后/向前搜索10秒
up or down 向后/向前搜索1分钟
pgup or pgdown 向后/向前搜索10分钟
< or > 跳到播放列表中的前一首/下一首
p or SPACE 暂停播放(按任意键继续)
q or ESC 停止播放并推出
+ or - 调整音频延迟+/-0.1秒
o 循环OSD模式: none/seekbar/seekbar+timer
* or / 增加或减少pcm音量
z or x 调整字幕延迟+/-0.1秒
r or t 上/下调整字幕位置, 参见-vf expand!
例如以下命令播放~movies/hyj.rmvb文件:
/opt/feiy/player/MPlayer1.0/bin$mplayer ~movies/hyj.rmvb
当然也可以在KDE中,使用打开方式->其他,选择mplayer打开的方式打开。
apt-get install mplayer后,播放一些带中文字幕的电影老显示不了中文字,会出现诸如:"___Ants,_____"的玩意,看了不少文档,终于搞定,下面总结一番
A~命令行方式播放:
这是我的~/.mplayer/config
[code]
# Write your default config options here!
font=/usr/share/fonts/truetype/hiweed/simsun.ttf
subcp=cp936
subfont-autoscale=2
subfont-text-scale=5
vo=xv
[/code]
然后,命令行输入mplayer aaa.avi,(前提是同目录下有同名字幕文件)。就OK了。
======================================
B~至于窗口模式,我采用以下方法也解决:
1.rm -rf /usr/share/mplayer/font/*
2.rm -rf ~/.mplayer/font/*
上面两步让gmplayer找不到那些英文字体,呵呵,就让它乖乖地用我们指定的字体:
3.ln -s /YOUR/PATH/TO/CHINESEFONT.ttf subfont.ttf
4.修改~/.mplayer/gui.conf如下项目:
[code]
sub_auto_load = "yes"
sub_unicode = "yes"
sub_pos = "100"
sub_overlap = "no"
sub_cp = "cp936"
font_factor = "0.750000"
font_name = "/home/badants/.mplayer/subfont.ttf"
font_encoding = "unicode"
[/code]
然后,打开gmplayer,试试看,能不能成功。
~~BadAnts~~
未经验证,备查linux 在启动过程的最后阶段(具体启动步骤略),init 会根据 /etc/inittab文件的最后一行x:5:respawn:/etc/X11/prefdm -nodaemon运行/etc/X11/prefdm脚本,(Red hat 7.2缺省时是这样的)。prefdm脚本的主要任务是完成X window的启动,可以有几种启动X window的方法,都包含在prefdm脚本中,几种主要方法有:
prefdm脚本框架大致如下:
|
在/etc/X11/prefdm脚本中,是否实现自动登录有一个条件测试开关,事实上,可以在这里注释掉测试开关,直接执行启动X window的操作。
自动登录实质上就是绕过身份验证,直接启动X window。X window的启动可以由xinit来完成。
startx脚本的最基本框架是:
由此可看出,startx在不需要传递任何参数的情况下,可以完成启动X的任务,因此,可以如下修改/etc/X11/prefdm脚本来实现自动登录:
|
当然,应确保/etc/inittab中的启动级别为5。
重 新启动系统,会发现系统不验证用户身份,直接进入X window,此时的用户身份为root。但是,如果原来root有自己的桌面、默认shell时,上述方法启动X不一定保证还能拥有原来的设置。为了在 启动X后,在避免验证身份的同时,又不改变用户原来的设置,那么在运行startx之前,还有工作要做。
三、自动登录后,保持用户原来的配置(桌面、shell以及其它的一些环境变量)。
观察原来/etc/X11/prefdm脚本的自动登录部分:
|
不难看出,脚本中保留了自动登录的接口:一个可执行文件/usr/sbin/autologin以及一个配置文件/etc/sysconfig/autologin。
1、/etc/sysconfig/autologin配置文件的实现:
|
2、/usr/sbin/autologin可执行文件的实现:
|
如 果不需要自动登录的配置文件/etc/sysconfig/autologin,所有的操作都在/usr/sbin/autologin以默认的方式实现 (比如,默认登录身份为root,默认执行操作为/usr/X11R6/bin/startx等),那么,/etc/X11/prefdm脚本的自动登录 部分可简化如下:
|
即在脚本中去掉条件测试开关,直接执行/usr/sbin/autologin,这时,只需要拷贝autologin可执行文件到/usr/sbin/autologin,不再需要拷贝autologin配置文件到/etc/sysconfig/autologin。
郑彦兴,男,现攻读国防科大计算机学院网络方向博士学位。您可以通过电子邮件 mlinux@163.com和他联系。 | ||
赵蔚, 自由职业者, Author company
2002 年 9 月 18 日
本文将带领大家构建一个迷你型的 Linux 系统。它占用的硬盘空间远小于 16M 字节,但是却包括了 XFree86 的 X Window 窗口系统。
本 文要构建的这个迷你型的 Linux 系统只能在一台特定的单机上运行,如果读者朋友们有兴趣的话,在这个系统的基础上加以改进,是可以构建出通用的、可以在大多数常规 PC 机上即插即用的系统来的。但是这已经不在本文的话题之内了,读者朋友们如果有兴趣,可以通过我的电子邮件和我讨论其中的细节问题。
我 们的目标 Linux 系统运行在一台普通的 Intel 386 PC 机上,可以有硬盘,也可以不要硬盘,而用 Flash Disk 来代替。如果是用 Flash 盘的话,需要能够支持从 Flash 盘启动,而且 Flash 盘的大小要在 16M 字节或者以上。我们希望用户一开机启动,就直接进入 X Window 图形界面,运行事先指定好的程序。不需要用户输入用户名和密码进行登录。
我们设定的这个目标有点像一个 X Terminal 终端工作站。稍加改进,还可以做成干脆无盘的形式,也就是说,连 16M 的 Flash 盘也不要了。不过,这也超出了本文的话题了。读者朋友们如果有兴趣,可以来信和我进行讨论。
因 为我们要考虑从 Flash 盘进行启动,所以我们选择用 LILO 作为我们的 Boot Loader,而不选用 GRUB。这是考虑到 GRUB 有较强的对硬盘和文件系统的识别能力,而 Flash 盘到底不是标准的硬盘,并且我们选用的文件系统 GRUB 又不一定认识,搞不好的话 GRUB 反 会弄巧成拙。而 LILO 就简单的多了,它在硬盘开始的 MBR 写入一个小程序,这个小程序不经过文件系统,直接从硬盘扇区号,读出 Kernel Image 装入内存。这样,保险系数就大大增加。并且也给了我们自由选用文件系统的余地。那么,我们要如何安装 LILO 呢?
首 先,我们要找一块普通的 800M 左右的 IDE 硬盘,连在目标机器的 IDE 线上。这样在我们的目标机器上,IDE1 上挂的是 Flash 盘,IDE2 上挂的是一块工作硬盘。我们用标准的步骤在 IDE2 的标准硬盘上装上一个 Debian GNU/Linux 系统。当然,如果读者朋友们手头没有 Debian,也可以装 Red Hat 系统。装好工作系统之后,要首先做一些裁减工作,把不必要的 Service 和 X Window 等等东西都删掉。这样做的目的是增进系统启动速度,因为我们在后面的工作中,肯定要不停的重新启动机器,所以启动速度对我们的工作效率是很关键的。
装 好工作系统之后,在 Falsh 盘上做一个 Ext2 文件系统,这个用 mke2fs 这个命令就可以完成。由于 Flash 盘是接在 IDE1 上的,所以在 Linux 里面,它的身份是 /dev/hda。本文作者在操作的时候,把整个 Flash 盘划分了一个整个的分区,所以,调用 mke2fs 的时候,处理的是 /dev/hda1。读者朋友们应该可以直接在 /dev/hda 上做一个 Ext2 文件系统,而不用事先分区。
在 Flash 盘上做好了文件系统之后,就可以把一个编译好的内核映像文件 vmlinuz 拷贝到 Flash 盘上了。注意,必须要先把这个 vmlinuz 映像文件拷贝到 Flash 盘上,然后才能在 Flash 盘上安装 LILO。不然的话,LILO 到时候可是会 LILILILI 打结巴的,因为它会找不到 Kernel Image 在 Flash 盘上的位置的,那样的话 Flash 盘也就启动不起来了。还有,如果读者朋友们在 Flash 盘上用的是一个压缩的文件系统的话,到时候 LILO 也会出问题,它虽然能正确的找到 Kernel Image 在硬盘上的起始位置,但是它却没有办法处理被文件系统重新压缩过的这个 Kernel Image,不知道该如何把它展开到内存中去。
把 Kernel Image 拷贝过去以后,我们就可以动手编辑一份 lilo.conf 文件,这份文件可以就放在工作系统上就行了。但是注意在 lilo.conf 中索引的文件名的路径可要写对。这些路径名都是在工作系统上看上去的路径名。比如,如果 Flash 盘 Mount 在 /mnt 目录下面,那么,在 lilo.conf 中,vmlinuz 的路径名就是 /mnt/vmlinuz。注意这一点千万不要搞错。不然的话,如果一不小心把工作系统的 LILO 给破坏掉了,那就麻烦了。编辑好了 lilo.conf,然后再运行 lilo 命令,注意,要告诉它用这个新的 lilo.conf 文件,而不要用 /etc/lilo.conf。
安 装好 LILO 之后,我们可以立即重新启动,测试一下。首先在 BIOS 里面,设置成从 IDE1 开始启动,如果我们看到 LILO 的提示符,按回车后还能看到 Kernel 输出的消息,这就算是 LILO 的安装成功了。记得这个操作的方法,以后每次我们更新 Flash 盘上的 Kernel Image,都记得要更新 LILO。也就是说,要重新运行一遍 lilo 命令。
![]()
回页首
试 验成功 LILO 的安装以后,我们开始考虑编译一个新的内核。当然,要编译新的内核,我们首先要进入我们的工作系统。这里有两个办法进入工作系统,一是在 BIOS 里面设置从 IDE2 启动,当然,这就要求当初安装工作系统的时候,要把 LILO 安装在 /dev/hdb 上;另一个办法是还是从 IDE1 启动,不改变 BIOS 的设置,但是在看到 LILO 的提示符的时候,要键入 linux root=/dev/hdb1,最前面的 linux 是在 lilo.conf 里面定义的一个 entry,我们只采用这个 entry 所指定的 Kernel Image,但是用 /dev/hdb1 作为 root 文件系统。两个办法可能有的时候一个比另一个好,更方便一些。这就要看具体的情况了。不过,它们的设置并不是互相冲突的。
在 编译内核的时候,由于我们的内核是只有一台机器使用的,所以我们应该对它的情况了如指掌;另外一方面,为了减低不必要的复杂性,我们决定不用 kernel module 的支持,而把所有需要的东西直接编译到内核的里面。这样编译出来的内核,在一台普通的 586 主板上,把所有必要的功能都加进去,一般也不到 800K 字节。所以,这个办法是可行的。而且减低了 init scripts 的复杂程度。从运行方面来考虑,由于需要的 kernel 代码反正是要装载到内存中的,所以并不会引起内存的浪费。
在 我们的目标平台上,我们希望使用 USB 存储设备。还有一点要注意的,就是对 Frame buffer 的支持。这主要是为了支持 XFree86。一般说来,如果我们的显卡是 XFree86 直接支持的,那当然最好,也就不需要 frame buffer 的内核支持。但是如果 XFree86 不支持我们的显卡,我们可以考虑用 VESA 模式。但是 XFree86 的 VESA 卡支持运行起来不太漂亮,还有安全方面的问题,有时在启动和退出 X Window 的时候会出现花屏。所以我们可以采用 kernel 的 vesa 模式的 frame buffer,然后用 xfree86 的 linux frame buffer 的驱动程序。这样一般就看不到花屏的现象了,而且安全方面也没有任何问题。
devfs 也是我们感兴趣的话题。如果 kernel 不使用 devfs,那么系统上的 root 文件系统就要有 /dev 目录下面的所有内容。这些内容可以用 /dev/MAKEDEV 脚本来建立,也可以用 mknod 手工一个一个来建。这个方法有其自身的好处。但是它的缺点是麻烦,而且和 kernel 的状态又并不一致。相反的,如果使用了 devfs,我们就再也不用担心 /dev 目录下面的任何事情了。/dev 目录下面的项目会有 kernel 的代码自己负责。实际使用起来的效果,对内存的消耗并不明显。所以我们选择 devfs。
![]()
回页首
有 了 LILO 和 kernel image 之后,接下来,我们要安排 root 文件系统。由于 flash 盘的空间只有 16M 字节,可以说,这是对我们最大的挑战。这里首先要向大家介绍小型嵌入式 Linux 系统安排 root 文件系统时的一个常用的利器:BusyBox。
Busybox 是 Debian GNU/Linux 的大名鼎鼎的 Bruce Perens 首先开发,使用在 Debian 的安装程序中。后来又有许多 Debian developers 贡献力量,这其中尤推 busybox 目前的维护者 Erik Andersen,他患有癌症,可是却是一名优秀的自由软件开发者。
Busybox 编译出一个单个的独立执行程序,就叫做 busybox。但是它可以根据配置,执行 ash shell 的功能,以及几十个各种小应用程序的功能。这其中包括有一个迷你的 vi 编辑器,系统不可或缺的 /sbin/init 程序,以及其他诸如 sed, ifconfig, halt, reboot, mkdir, mount, ln, ls, echo, cat ... 等等这些都是一个正常的系统上必不可少的,但是如果我们把这些程序的原件拿过来的话,它们的体积加在一起,让人吃不消。可是 busybox 有全部的这么多功能,大小也不过 100K 左右。而且,用户还可以根据自己的需要,决定到底要在 busybox 中编译进哪几个应用程序的功能。这样的话,busybox 的体积就可以进一步缩小了。
使用 busybox 也很简单。只要建一个符号链接,比方 ln -s /bin/busybox /bin/ls,那么,执行 /bin/ls 的时候,busybox 就会执行 ls 的功能,也会按照 ls 的方式处理命令行参数。又比如 ln -s /bin/busybox /sbin/init,这样我们就有了系统运行不可或缺的 /sbin/init 程序了。当然,这里的前提是,你在 busybox 中编译进去了这两个程序的功能。
这里面要提出注意的一点是,busybox 的 init 程序所认识的 /etc/inittab 的格式非常简单,而且和常规的 inittab 文件的格式不一样。所以读者朋友们在为这个 busybox 的 init 写 inittab 的时候,要注意一下不同的语法。至于细节,就不在我们这里多说了,请大家参考 Busybox 的用户手册。
![]()
回页首
busybox 安装好以后,我们就可以考虑重新启动,一直到进入 shell 提示符了。这之前,我们要准备一下 /etc 目录下的几个重要的文件,而且要把 busybox 用到的 library 也拷贝过来。
用 ldd 命令,后面跟要分析的二进制程序的路径名,就可以知道一个二进制程序,或者是一个 library 文件之间的互相依赖关系,比如 busybox 就依赖于 libc.so 和 ld-linux.so ,我们有了这些知识,就可把动手把所有需要的 library 拷贝到 flash 盘上。由于我们的 flash 盘说大不大,说小倒也不小,有 16M 字节之多。我们直接就用 Glibc 的文件也没有太多问题。如果读者朋友们有特殊的需要,觉得 Glibc 太庞大了的话,可以考虑用 uClibc,这是一个非常小巧的 libc 库,功能当然没有 Glibc 全,但是足够一个嵌入式系统使用了。本文就不再介绍 uClibc 了。
库程序拷 贝过来以后,我们就可以考虑系统启动的步骤了。启动的时候,先是 lilo,接下来就是 kernel,kernel 初始化之后,就调用 /sbin/init,然后由 init 解释 /etc/inittab 运行各种各样的东西。inittab 会指导 init 去调用一个最重要的系统初始化程序 /etc/init.d/rcS,我们将要在 rcS 中完成各个文件系统的 mount,此外,还有在 rcS 中调用 dhcp 程序,把网络架起来。rcS 执行完了以后,init 就会在一个 console 上,按照 inittab 的指示开一个 shell,或者是开 getty + login,这样用户就会看到提示输入用户名的提示符。我们这里为了简单起见,先直接进入 shell,然后等到调试成功以后,再改成直接进入 X Window。
关于 inittab 的语法,我们上面已经提到过了,希望读者朋友们去查权威的 busybox 的用户手册。这里,我们先要讲一下文件系统的构成情况。
![]()
回页首
大 家已经看到,我们的 root 文件系统为了避免麻烦,用的是标准的 ext2 文件系统。由于我们的硬盘空间很小,只有不到 16M,而且我们还要在上面放上 X Window,所以,如果我们全部用 ext2 的话,Flash 盘的有限空间会很快耗尽。我们唯一的选择是采用一个适当的压缩文件系统。考虑到 /usr 目录下面的内容在系统运行的时候,是不需要被改写的。我们决定选择只读的压缩文件系统 cramfs 来容纳 /usr 目录下面的全部内容。
cramfs 是 Linus Torvalds 本人开发的一个适用于嵌入式系统的小文件系统。由于它是只读的,所以,虽然它采取了 zlib 做压缩,但是它还是可以做到高效的随机读取。既然 cramfs 不会影响系统读取文件的速度,又是一个高度压缩的文件系统,对于我们,它就是一个相当不错的选择了。
我们首先把 /usr 目录下的全部内容制成一个 cramfs 的 image 文件。这可以用 mkcramfs 命令完成。得到了这个 usr.img 文件之后,我们还要考虑怎样才能在系统运行的时候,把这个 image 文件 mount 上来,成为一个可用的文件系统。由于这个 image 文件不是一个通常意义上的 block 设备,我们必须采用 loopback 设备来完成这一任务。具体说来,就是在前面提到的 /etc/init.d/rcS 脚本的前面部分,加上一行 mount 命令:
mount -o loop -t cramfs /usr.img /usr
这样,就可以经由 loopback 设备,把 usr.img 这个 cramfs 的 image 文件 mount 到 /usr 目录上去了。哦,对了,由于要用到 loopback 设备,读者朋友们在编译内核的时候,别忘了加入内核对这个设备的支持。对于系统今后的运行来说,这个 mount 的效果是透明的。cramfs 的压缩效率一般都能达到将近 50%,而我们的系统上绝大部分的内容是位于 /usr 目录下面,这样一来,原本可能要用到 18M 的 Flash 盘,现在可能只需要 11M 就可以了。一个 14M 的 /usr 目录,给压缩成了仅仅 7M。
上面考虑了压 缩问题,下面还要考虑到,Flash 盘毕竟不像普通硬盘,多次的擦写毕竟不太好,所以我们考虑,在需要多次擦写的地方,使用内存来做。这个任务,我们考虑用 tmpfs 来完成。至于 tmpfs 和经典的 ramdisk 的比较,我们这里就不多说了。一般说来,tmpfs 更加灵活一些,tmpfs 的大小不像 ramdisk,可以顺着用户的需要增长或者缩小。我们选择把 /tmp、/var 等几个目录做成 tmpfs。这只需要我们在 /etc/fstab 里面加上两行类似下面的文字就可以了:
none /var tmpfs default 0 0
然后别忘了在 /etc/init.d/rcS 里面靠近开头的地方,加上 mount -a。这样,就可以把 /etc/fstab 里面指定的所有的文件系统都 mount 上来了。
![]()
回页首
进 行到这里,读者朋友们可能会以为,X Window 的安装可能会很复杂。其实不然,由于我们上面的架子搭好了,X Window 的安装非常简单,只需要把几个关键的程序拷贝过来就可以了。一般说来,只需要 /usr/X11R6 目录下面的 bin 和 lib 两个目录。然后,根据用户各自的需要,还可以做大幅的裁减。比如,如果你的局域网上有一个开放的 xfs 字体服务器的话,你可以把所有本地的字体都删掉,而使用远端的字体服务器。如果只需要运行有限的程序,别忘了把没有用的 library 都删掉。此外,还可以把多余的 X Window 的 driver 都删掉,只保留本机的显示卡所需要的 driver 就可以了。
当然,这一关免不了要做多次测试。
![]()
回页首
如果你的工作系统式在另外一台机器上,通过局域网和本机互联的话,ssh 是一个不错的工具。此外,ssh 中带的 scp 用起来和普通的 cp 拷贝程序差不多,非常方便。用 ssh 和 scp 来共享文件,远程试验,你就可以不需要在办公室里跑来跑去的了。
如果你需要一个 MS Windows 上运行的 X Server 和 xfs 字体服务器,可以考虑包括在 Red Hat 的 Cygwin 工具箱中的 XFree86 系统。
![]()
回页首
- BusyBox 的站点: http://www.busybox.net
- Linux From Scratch,自己动手,从头开始做一个 Linux 系统: http://www.linuxfromscratch.org
- uClibc 的站点: http://www.uclibc.org
- Cygwin 的站点: http://www.cygwin.com
![]()
回页首
赵蔚,自由职业者。我的网络日记位于 http://www.advogato.org/person/zhaoway/。上面列有我在网络上发表的其它的文章。欢迎读者朋友们来信和我讨论问题。