2009年3月17日星期二

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


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

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 文件。
正如您所见,绑定安装非常强大,让您可以轻易地修改文件系统设计,丝毫不必忙乱。

2009年3月16日星期一

路由器和UDP广播

不同网段之间的通讯(TCP/UDP)可以通过端口映射来实现。端口映射就是将主机的IP地址的一个端口映射到局域网中一台机器,当用户访问这个IP的这个端口时,服务器自动将请求映射到对应局域网分机(就这么简单)。

广播地址主要有以下四种:
1、受限的广播:受限的广播地址是255.255.255.255,该地址用于主机配置过程中IP数据报的地址,此时,主机可能还不知道它所在网络的网络掩码,甚至连它的IP地址也不知道。在任何情况下,路由器都不转发目的地址为受限广播地址的数据报,这样的数据报只出现在本地网络中。
2、指向网络的广播:指向网络的广播地址是主机号全为1的地址,A类网络广播地址为netid.255.255.255,其中netid为A类网络的网络号。
3、指向子网的广播:指向子网的广播地址是主机号全为1的地址,作为子网直接广播的IP地址需要知道子网的掩码。如果B类网络128.1的子网掩码是255.255.255.0,则地址128.1.2.255就是对应子网的广播地址。
4、指向所有子网的广播:指向所有子网的广播也需要知道目的网络的子网掩码。这些广播地址的子网号和主机号全为1。如果目的子网掩码是255.255.255.0,那么IP地址128.1.255.255就是一个指向所有子网的广播地址。

路由器默认是不转发UDP广播包的,这样可以净化内网环境。但是某些特殊场合,需要使用udp广播,最常见的是DHCP服务,因为给每个网段都架设DHCP服务器,效率太低。怎么办呢?
cisco有ip广播转发的解决方案:DHCP中继代理和UDP广播转发。
在路由器或者三层交换机接口模式下用个ip helper-address的命令,这个使用DHCP中继代理特性将路由器配置成可以转发DHCP广播
对于udp广播转发,在前面的基础上加个 ip forward protocol udp udp_ports。
对于要禁止转发的udp广播,只需在前面加个no 后面加上端口号
默认情况下 使用ip helper-address,可以转发DHCP、TFTP、DNS、时间、NetBIOS、名称服务器和BOOTP等UDP数据包。

帮助地址(Helper Address)将会阐述网络和路由器如何使用帮助地址来将广播分组转发给另一个网段的服务器和路由器,以及使用帮助地址的目的和情景。

1使用帮助地址
在一个复杂的分级网络中,往往不是所有的客户端都与这些服务器(ftp、dhcp、dns)处于同一个子网中。远程客户端将通过广播方式寻找服务器,但在缺省的情况下,路由器是不会将客户端广播转发到它们的子网之外的。但比如一种情况,因为有些客户端在没有DHCP这类服务的情况下将不能工作,所以管理员不得不面对两种选择:
在所有子网上都放置DHCP和DNS服务器
采用Cisco IOS 的帮助地址特性
在多台电脑上运行例如DHCP和DNS这类服务会产生很多额外的开销和管理问题,所以第一张选择并不是最佳的。在可能的情况下,管理员可以用命令"ip
helper-address"来中继这些主要的用户数据报文协议(UDP)服务请求。
通过使用命令"ip
helper-address",路由器可以被配置为接受对UDP服务的请求广播,然后将该广播以单播传送方式转发给某个具体的IP地址或者路由器可以用定向广播方式向某个网络或者子网转发这些请求。

2配置帮助地址
要配置帮助地址,先要识别将接受UDP服务广播的路由器端口。然后在端口配置模式下,使用命令"ip
helper-address"来定义UDP服务广播应该被转发出去的地址。缺省地,命令"ip
helper-address"将转发表1中所示的8种UDP服务

表1 缺省转发的UDP服务

服务                          端口
Time                          37
TACAS                      49
DNS                          53
BOOTP/DHCP服务器 67
BOOTP/DHCP客户机 68
TFTP                         69
NetBIOS名字服务      137
NetBIOS数据报服务   138

但若公司需要转发的服务请求不再这个表中怎么办?Cisco
IOS提供了全局配置命令"ip forward-protocol"来是管理员能转发除这8种缺省协议之外的任何UDP端口。例如,为了转发UDP端口517,可以使用全局配置命令"ip forward-protocol 517"。"ip forward-protocol"命令不仅可以用来添加UDP端口,还可以用于从缺省的8种协议种减去任何不想要的端口。例如,如果要转发DHCP、TFTP和DNS,但出于某种原因,不转发时间、TACACS和NetBIOS,则可以按照例1来配置路由器。

例1 配置定制的UDP转发端口
RTA (config-if) #ip helper-address 192.168.1.254
RTA (config-if) #exit
RTA (config) #ip forward-protocol udp 517
RTA (config) # no ip forward-protocol udp 37
RTA (config) # no ip forward-protocol udp 49
RTA (config) # no ip forward-protocol udp 137
RTA (config) # no ip forward-protocol udp 138

3帮助地址配置举例
考虑图2中复杂的帮助地址的配置例子。首先,我们想让主机A自动从位于地址172.24.1.9处的DHCP服务器上获得它的IP配置。因为路由器RTA不转发主机A的DHCPDISCOVER广播,所以必须配置路由器RTA以帮助主机A转发广播。之后,配置将要接收主机A的广播的路由器RTA的接口E0,以便它可以将DHCP广播以单点传送的方式中继给DHCP服务器,使用的配置命令如下:
RTA (config) # interface e0
RTA (config-if) # ip helper-address 172.24.1.9

通过这个简单的配置,使用8个缺省UDP端口中任意一个主机A的广播都将被中继到DHCP服务器。例如,如果主机A发送广播型TFTP分组,则该分组将由路由器RTA转发到位于地址172.24.1.9的DHCP服务器。然而,若主机A也需要位于地址172.24.1.5的NetBIOS服务器的服务,这样会出现什么样的情况呢?根据上面的配置,主机A的NetBIOS广播分组也将会被路由器RTA转发到172.24.1.9的DHCP服务器上。显然,这样就无法获得正确的服务。事实上,在这种情况下,只需配置一个可以向网段上所有服务器都中继广播分组的帮助地址即可,配置命令如下:

RTA (config) # interface e0
RTA (config-if) # ip helper-address 172.24.1.255

给服务器网段(172.24.1.255)配置一个定向广播比输入每台有可能应答主机A的UDP广播的服务器的IP地址更有效。
最后,在主机A所在的网段上还有一些设备需要广播到不再服务器机群种的TACACS服务器上。此时,可以通过添加命令"ip helper-address 172.16.1.2"来配置RTA的E0以让它工作。
可以用命令"show ip interface"验证帮助地址的配置是否正确,如例2所示

例2 验证IP帮助地址的配置
RTA# show ip interface e0
Ethernet0 is up, line protocol is up
Interface address is 10.1.1.1/24
Broadcast address is 255.255.255.255
Address determined by setup command
MTU is 1500 bytes
Helper addresses are
172.24.4.255
172.16.1.2
Directed broadcast forwarding is disabled
<Output omitted>

在 例3中,路由器RTA连接服务器机群的E3接口并没有配置帮助地址。然而,输入显示该接口的定向广播转发功能被关闭了。这意味着路由器将不能把逻辑广播172.24.1.255转发为一个物理广播(有FF-FF-FF-FF-FF-FF的第二层地址)

例3 验证定向广播的转发
RTA# show ip interface e3
Ethernet3 is up, line protocol is up
Interface address is 172.24.1.1/24
Broadcast address is 255.255.255.255
Address determined by setup command
MTU is 1500 bytes
Helper addresses is not set
Directed broadcast forwarding is disabled
<Output omitted>

要让服务器机群中的所有节点都收到第二层广播,必须配置接口E3让它转发定向广播,配置如下:
RTA (config) # interface e3
RTA (config-if) # ip directed-broadcast

如此,你就可以实现UDP广播转发了,但是一般的路由器大都没有这项功能,支持如此操作。对于一般的路由器,如果你非要用全网广播,那么一个简单的方法是把路由器降级当作交换机来使用,实现方法也非常简单:WAN闲置,将所有的线都接在LAN口上。

2009年3月15日星期日

GE被她的执着所打动!

想不想进GE?想,也不想。有些事想也没用。进GE难不难?难,也不难。有些事想不难
也就不难。本期求职故事NO.7人物女生Yvone,最终能进入GE,使用的招数只是简单的两
个字:执着。

  NO.007 姓名:Yvone
专业:上海交通大学电子信息与电器工程学院自动化专业与国
际经济贸易双学士

  2004年6月,还是大三学生的我开始在网上寻找实习机会。我学的是自动化专业,不
过,为了让自己能够成为所谓的复合型人才,我同时还读了国际经济与贸易作为我的第二
专业。与我的性格有关,我并不想在将来走上纯粹研发的职业道路,所以在选择实习机会
的时候,我一般瞄准大公司的市场、质量管理等综合性比较强的部门。毕竟,实习是为将
来的求职作准备。在BBS上我发现了一条信息,GE的质量管理部门正在招实习生,于是立
即投出了简历。两个星期过去了,迟迟没有回复,就在我以为没希望了的时候,我接到了
面试通知。

  群面后,我给自己投了一票

  第一面是群面,10几个来自不同学校的学生围坐在一张椭圆型桌子边上。面试官发给
我们一些材料,大都是关于生活、学习内容的。请大家短时间浏览之后,发表各自的看
法。

  很快,大家就争先恐后地发言。我是第一次面对这样的面试,也没太多的准备。所以
那天发挥得并不理想。而且一向以来,我也不是个喜欢和善于打断别人说话的人,甚至,
我认为随便打断别人的话是不礼貌的。

  按规定,每个人只有三四分种的说话时间,可也有人"霸占着别人的时间",5分钟
后还没有让别人说话的意思。我觉得这样的做法不可取,因为事先我对GE的文化是作过了
解的,团队合作精神,是GE非常推崇的精神之一。所以,讨论中能否发扬团队合作,能否
考虑其他成员的利益非常重要。

  回想起来,我抓住了这样几个要点。第一,必须尊重其他人的发言。我总是耐心听完
别人的发言后才说:我很同意你的观点,但我还想补充一点……第二,在团队中适时显示
自己的领导才能。也许因为曾担任过团支书记、党支书记等职,所以我总是能在大家较激
动容易"豁边"时,说上一两句,以推动整个讨论的继续开展。

  进入下一轮面试的方式有点出乎我的意料。面试官让我们当场互相投票,得票较多的
五六个人立即进入下一轮面试。我进入了下一轮面试,因为除了其他人投我的票之外,我
给自己也投了一票。我觉得这时候千万不能谦虚,否则这个机会就丢在自己手里了。

  接下来的面试是与HR"一对一"的英语交流。15分钟左右的时间。当HR问我"请说说
你对刚才的表现是否满意"时,我实话实说了:"我对自己的表现并不十分满意,我也不
知道我为什么能进入这轮面试。"接下去的问题简单一些:"请说说你在大学里最成功的
一件事。"这种问题我事先准备得很充分,所以回答时的感觉也比刚才群面时好多了。

  我为什么能顺利通过两轮面试?我以为,一,我适时显示出了我的领导能力。这当然
也不是一时之功,这与我大学里一直担任学生干部有关;二,我很好地表现出了我的团队
合作精神。我的谦虚、礼貌的说话方式,我话不多却能对整个讨论有所推动,这都能给面
试官留下很好的印象;三,因为是学生,我没有选择职业装,而是选了一件色彩和谐、款
式端庄的连衣裙。我发现当时也有人穿着很随便的套头T恤就来了。而最后进入第二、三
轮面试的3个女生,全都是与我相似的打扮。

  被淘汰,心才开始有点痛

  一个星期之后的星期一,GE通知我去参加第三轮面试,那次面试很不顺利。面试官是
质量管理部门的头,总共10分钟时间,彼此之间的冷场多于说话。而那天早上我似乎有点
糊里糊涂没睡醒,回答问题时也全没有激情。果然,一星期后我接到了通知:另一个人更
适合你。

  这时我被失败的感觉弄得心很痛,大哭了一场后,才发现我还是非常希望进入GE实
习。于是我给HR打电话,至少我要知道理由。HR很客气说:可能部门更希望要一个男生
吧。如果有其他机会,我们再通知你吧。

  原以为HR只是种安慰,谁知第二天,还真来电话。说研发中心有一个助理工程师的机
会。从失望的谷底又回到了希望的顶端,两天的大起大落还真让人有点受不了。幸运的
是,由我的直接上司主持的第四轮面试进行得很顺利。

  事实上,所有的面试还是需要准备的。譬如,很多面试官都会针对你的简历提一些问
题。

  所以,有必要事先用中英文对每一段简历准备些解释。这种准备就好像是为面试官准
备了一缸水,需要时舀上一杯。再譬如,事先对职位的要求、对企业文化都要有所了解。
并尽量找出企业文化与你个人素质的契合点。在事先对GE文化深入研究一番后,我注意到
GE尤其关注员工的领导能力、团队合作能力等等,而这些于我还是存在很多契合点,在举
例说明我的能力时就比较有的放矢。

  面试即将结束时,我的直接上司问:"你对GE的文化了解多少?"我说了理解。上司
接着说:"相信3个月后,你对GE的了解会有所不同。"这时我知道,实习有着落了。

  和很多人聊起来都有一个共同的感觉,在大公司面试,尤其是直接上司面试你的时
候,彼此之间聊得投缘与否直接决定了你是否有机会。所以,尽量找出与面试官的共同兴
趣,也是提高求职成功率的方法之一。

  实习时,我找到了心仪的职位

  3个月实习合同期满后,我又续签了8个月实习合同。通过这段时间的实习,我开始对
将来的职业目标越来越清晰:我要进入GE.通过内部招聘系统,我发现GE正在招IMLP(信
息管理领导培训生)。我决定投简历,同时,也将自己的想法直接告诉了当时部门的头
儿。幸运的是头儿对我的想法很支持,并热情地帮我写了一封推荐信。

  投出简历一个月后,我接到了面试通知。因为有了第一次经验,我很容易就通过了群
面,进入第二轮"二对一"的面试。其中的一位面试官来自印度,是我们的首席信息官。
他说的英语非常难懂。我很着急,但我很明白,无论如何不能要求他把问题重复一遍,这
会是很无礼的。于是为了搞清问题,我巧妙地将他的问题重复一遍,并礼貌地说:"我的
重复是不是准确?"就这样不断地提问不断地重复提问,我们彼此却聊得很高兴。40分钟
的规定时间,我们却聊了一个多小时。

  其中印象比较深刻的问题是:你是不是有过失败的经验?为什么失败?从失败中你又
学到了什么?你是不是愿意继续与那些曾合作失败的人一起工作?

  对最后一个问题我这样回答:"我愿意与他们继续合作,因为有过失败的经验与教
训,再次合作,成功的可能性更大。"

  最后,为了考察我如何解决工作中出现的矛盾,面试官还给出了一个几乎是刁难的情
景:假如我们俩同时让你完成一个任务,我们都不希望被你安排在第二位完成,你会如何
处理?

  我作了很多安排,他们都一一否决了,最后,我从理论上对两个任务排了一个优先
级。总算面试官不再"刁难"我。其实,面试官最后也不想要什么正确答案,只是想看看
我在面对不断的"挑衅"与"刁难"时会是一种怎么样的神情与态度。对我始终表现出的
泰然自若的神情他们似乎挺满意。他们说:"今天谈得很愉快,回去等HR的通知吧。"

  我执着地"骚扰"HR

  原以为笃笃定定的事情,可最后却等来了一个拒绝电话:另外一个人比我更适合。后
来我才知道我输给了一位清华大学的女生,她更活泼,比我更优秀。虽然没有像上次差一
点失去实习机会那样大哭一场,可这让我更加心痛。毕竟,我已经离GE这么近。认输吗?
不!我给HR发E-mail,一封接一封,不断地实施"骚扰"。终于HR又给了我一次机会。可
是,我又被拒了,这回输给了一位从美国回来的硕士。虽然我输得心服口服,但我实在不
甘心就此失败。于是继续"骚扰"HR,再次写信将我渴望进入GE的心情表达了一遍。

  幸亏我坚持了,而HR后来也说:是你的执着打动了我。其实,GE何尝不需要一个执着
于自己理想的员工呢?事实上,GE有很多公司,每个公司都有相同的机会。那个被我"打
动"了的HR其实就是将我推荐给了不同的公司。在这样一次次尝试中,我终于找到了属于
我的位置。当我第3次被推荐后,当我为了这次机会又经历了3次面试后,我终于得到了这
个机会。

  也常有人问我,你何以能够进入GE?我想,有一些特别的东西是我拥有的。我一直是
个学生干部,平常的学生生活锻炼了我的领导能力;面试时我尽量紧紧跟着面试官的思想
走,寻找彼此相同的兴趣;为人踏实,交给我的每一件事一定是百分之百地努力做好;而
之前好不容易得来的实习经验对我更是直接的帮助。我的部门在录取我之前还专门去我实
习的部门了解了我的表现。

  而我之所以进入GE,也是因为我相信我拥有的这些特别的东西也是GE所需要的。

如何创建属于自己的GNU/Linux发行版?

简介

本文介绍了如何在Ubuntu
Hardy的基础上,创建属于自己的GNU/Linux发行版。本文的作者也是gNewSense的创造者。他们在构建gNewSense的过程中,导出了一个通用的Builder工具,用户可以利用它定制属于自己的GNU/Linux发行版。

作为创建gNewSense的一部分,我们导出了Builder工具,允许在Ubuntu
Hardy的基础上创建新的GNU/Linux发行版。通过一个简单的配置文件,你就能够选择发行版的名称,版本号,标语以及你想要安装或者移除默认的软件包。图像将会自动生成。虽然这些脚本主要的目的是为了创建gNewSense,但是它还是一个不错值得利用的工具。需要注意的是你可以不遵循下面的步骤使用gNewSense,因为你可以从网站的镜像下载到相关的镜像文件。

你需要至少60GB的硬盘空间,最好有一个非常快的网络连接(因为你将要下载40GB的数据)。同时你的镜像点(也可以在同一个系统中)也需要40GB左右的空间。如果你会利用硬链接,就能够避免一些重复的下载。这一些操作都将在Ubuntu
Hardy(或者更高版本的)系统执行。所有的命令都必须运行在Root权限下。

如果你有什么问题,可以发到我们的IRC中。Builder这个工具还只是测试版软件,我已经很久没有从源码重新编译过该工具,因为有些代码已经修改过了。

第一步:GPG Key

软件库中很多最近版本的apt,需要经过GPG签名的版本文件,这样可以保证发行版的集成度,所以我们的第一步就是创建一个GPG
Key。

gpg --gen-key

这个命令就可以让你做到这些。确保Key只有一个空白的密码。把这个Key的指纹信息记录下来,因为之后你将在配置文件中用到它。

第二步: Deb镜像(可选的)

为了避免重复下载文件,我建议创建一个Ubuntu
main和universe软件库的镜像点。这样的话大概需要40GB的空间。

debmirror --verbose --progress --method=http --host=ie.archive.ubuntu.com
--arch=i386 --source \
--dist=hardy,hardy-security,hardy-updates,hardy-backports
--section=main,main/debian-installer,universe \
--ignore-release-gpg --root=ubuntu /the/target/directory

你也可以建一个Apache服务器,这样你就能通过HTTP看到这个镜像点。这个步骤是可选的,但是我强烈推荐大家制作一个本地的Ubuntu镜像点。

第三步: 软件包

你需要安装一些软件包,使得Builder运行顺畅。

apt-get install reprepro debmirror build-essential apache2 subversion
cdebootstrap debootstrap imagemagick
apt-get install squashfs-tools netpbm syslinux bittornado fakeroot
devscripts equivs sharutils mkisofs
svn co http://svn.gnewsense.svnhopper.net/gnewsense/builder/trunk builder
cd builder

如果这里面还缺少某些软件包,请告知我。

第四步: 配置

用文本编辑器,打开配置文件。你主要关心的设置有MIRROR,RELEASE,DISTRONAME,DOMAIN,BASEDIR,和REPOAPT。
如果还有其它的定制要求可以修改配置文件的其它设置部分。

MIRROR
指的是你在第二步中创建的镜像点,或者Ubuntu镜像点,它应该包含安全的软件包。

MIRRORDIST 指的是镜像点的发行版本,通常是"Ubuntu"

DISTRONAME 指的是你的发行版名称,只能包含字母和数字。

BASE_RELEASE 指的是你的版本号。版本号应该是小写的,因为它将在路径出现。

TAGLINE 出现在开机启动和登录的屏幕中。

SIGNINGKEY 指的是第一步中你设置的GPG Key,不能包含任何空格。

BASEDIR 指的是放置软件库、livecd、临时文件的目录名称,REPODST
指的是当前文件系统下建立的镜像点位置($BASEDIR/发行版名称的小写形式)。

REPOAPT
指的是编译脚本放置的路径,用来下载软件包。我们假定在archive.DOMAIN和security.DOMAIN以及subdomains处都是类Ubuntu的安装方式。

RSYNC_DEST 指的是可以通过push-repo
或者push-cd来同步的软件库和livecd的位置。

LOGO_LETTER 指的是标志中的字母。

META_*_{ADD,REMOVE}
在你的默认的软件包建立之后,用来管理哪些软件包你想增加或者想把它从Ubuntu默认的软件包移除。

*_VERSION
指的是给软件包版本添加的号码。每次你要重编译一个软件包的时候,你需要增加这些。多半都是从1开始计。

第五步: 构造软件库

./gen-repo && ./do-update

这一步需要一些时间。当这个命令运行的时候,软件库有可能会不一致。这就是为何在第七步中你只需要将改动放到镜像点中。每次有新的版本(例如安全库更新了)重新执行
do-update命令就可以了(如果需要的话,也只可以执行debmirror)。

如果你在64位的内核上运行32位的用户程序,安装linux32软件包,然后执行命令

./gen-repo && linux32 ./do-update

第六步: 创建LiveCD

./gen-livecd

创建好的镜像文件将放在 $LIVECDDIR/$DISTRONAME_L-livecd-$LIVECD_VERSION.iso

./gen-cdsource
./stage-cd

这两个命令将创建一个源码包,并把这个ISO放置在 $REPODST/cdimage

第七步:把你的软件库放到镜像点并公开

现在可以在你的镜像点公开你的软件库(dists和pool)地址和LiveCD,将你的新发行版向世界公开。

./push-repo
./push-cd

© Brian Brazil 2006
Minor edits by Karl Goetz

对于UDP协议组播的一些认识

  利用UDP组播能在intarnet,internet上也数据报的形式进行数据的组播(在internet上进行组播,要求路由器支持IGMP(internet网关管理协议,这个协议是在IP出现以后,为了支持组播而出现的)).相对于极度消耗网络带宽的广播来说(广播只能在intranet内广播),UDP组播有了很大的优化,只有终端加入到了一个广播组,UDP组播的数据才能被他接受到.
  UDP组播是采用的无连接,数据报的连接方式,所以是不可靠的.也就是数据能不能到达接受端和数据到达的顺序都是不能保证的.但是由于UDP不用保证数据的可靠性,所有数据的传送速度是很快的.
1. 组播的"根"
  组播从概念上来讲分为两部分:控制部分和数据部分。控制部分决定着组播的对象的组织方式。而数据部分决定了数据的传输方式。
  控制层有"有根","无根"两种情况。对于有根的控制层,存在着一个root和若干个leaf.
root负责管理这个组播组,只有他能邀请一个leaf加入一个组播组(ATM就是有根控制的一个典型的例子)。对于无根的控制层,没有root,只有若干的leaf.
每一个leaf都能自己加入一个组播组(IP就是无根控制的典型例子)
  数据层也有"有根","无根"两种情况。对于有根数据层,从root发出的数据能到达每一个leaf,而从leaf发出的数据只能到达root.对于无根数据层,每一个leaf发出的数据能到达组播组中的每一个leaf(甚至包括他自己)。每一个leaf也能接受组播组里的任何数据包。
二.IP组播地址
IP组播通信需要一个特殊的组播地址.IP组播地址是一组D类IP地址,范围从224.0.0.0

239.255.255.255。其中还有很多地址是为特殊的目的保留的。224.0.0.0到224.0.0.255的地址最好不要用,因为他们大多是为了特殊的目的保持的(比如IGMP协议)
三.IGMP协议
  IGMP(internet网关管理协议)是IP组播的基础.在IP协议出现以后,为了加入对组播的支持,IGMP产生了。IGMP所做的实际上就是告诉路由器,在这个路由器所在的子网内有人对发送到某一个组播组的数据感兴趣,这样当这个组播组的数据到达后面,路由器就不会抛弃它,而是把他转送给所有感兴趣的客户。假如不同子网内的A,B要进行组播通信,那么,位与A,B之间的所有路由器必须都要支持IGMP协议,否则A,B之间不能进行通信。
  当一个应用加入一个组播组后,就会向这个子网的所有路由器发送一个IGMP加入命令,告诉他子网内有人对发送到某一个组播组的数据感兴趣.路由器也会定时向子网内的所有终端发送一条查询消息,用于询问是否还有人对某个组播组的数据感兴趣。如果有的话,终端就会回应一条IGMP消息,路由器则继续转发这个组播组的数据。如果没有人回应这条消息,那么路由器就认为已经没有终端对这个组播组的数据感兴趣,就不会在转发关于这个组播组的数据了。在IGMP第二版中,一个终端推出组播组以后,会向路由器发送一个推出消息,路由器也会通过这个消息来判断是否还要继续转发关于这个组播组的数据了(IGMP第一版中没有这个功能)[这些事情都是底层的系统做的,你只要坐享其成就好了]
四. winsock 1组播
  winsock 1的组播主要有以下几个步骤:
1. 建立支持数据报的scoket
2. 把socket和本地的一个端口绑定(以后会通过这个端口进行数据的收发)
3. 通过setsockopt IP_ADD_MEMBERSHIP加入一个组播组
4. 然后就能通过sendto / recvfrom进行数据的收法
5. 通过 setsockopt IP_DROP_MEMBERSHIP离开一个组播组
6. 关闭socket
  如果你仅仅是想向一个组播组发送数据,而不要接受数据,那么可不用加入组播组,而直接通过sendto向组播组发送数据
五.winsock 2组播
  winsock
2组播主要是通过WSAJoinLeaf来实现的(WSAJoinLeaf的行为,返回值根据socket的模式,组播的实现构架有很大的关系)
  winsock 2组播的主要有以下几个步骤
1. 建立支持数据报的socket(用WSASocket建立socket,同2. 时设置组播的一些属性)
3. 把socket和本地的一个端口绑定(以后会通过这个端口进行数据的收发)
4. 通过WSAJoinLeaf加入一个组播组
5. 通过sendto / recvfrom进行数据的收发
6. 直接关闭socket,
7. 退出组播组

广播和多播

引言

在第1章中我们提到有三种IP地址:单播地址、广播地址和多播地址。本章将更详细地介绍广播和多播。
广播和多播仅应用于UDP,它们对需将报文同时传往多个接收者的应用来说十分重要。TCP是一个面向连接的协议,它意味着分别运行于两主机(由IP地址确定)内的两进程(由端口号确定)间存在一条连接。
考虑包含多个主机的共享信道网络如以太网。每个以太网帧包含源主机和目的主机的以太网地址(48 bit)。通常每个以太网帧仅发往单个目的主机,目的地址指明单个接收接口,因而称为单播(unicast)。在这种方式下,任意两个主机的通信不会干扰网内其他主机(可能引起争夺共享信道的情况除外)。
然而,有时一个主机要向网上的所有其他主机发送帧,这就是广播。通过ARP和RARP可以看到这一过程。多播(multicast) 处于单播和广播之间:帧仅传送给属于多播组的多个主机。

为了弄清广播和多播,需要了解主机对由信道传送过来帧的过滤过程。图12-1说明了这一过程。

首先,网卡查看由信道传送过来的帧,确定是否接收该帧,若接收后就将它传往设备驱动程序。通常网卡仅接收那些目的地址为网卡物理地址或广播地址的帧。另外,多数接口均被设置为混合模式,这种模式能接收每个帧的一个复制。作为一个例子,tcpdump使用这种模式。
目前,大多数的网卡经过配置都能接收目的地址为多播地址或某些子网多播地址的帧。对于以太网,当地址中最高字节的最低位设置为1时表示该地址是一个多播地址,用十六进制可表示为01:00:00:00:00:00(以太网广播地址ff:ff:ff:ff:ff:ff可看作是以太网多播地址的特例)。
如果网卡收到一个帧,这个帧将被传送给设备驱动程序(如果帧检验和错,网卡将丢弃该帧)。设备驱动程序将进行另外的帧过滤。首先,帧类型中必须指定要使用的协议(IP、ARP等等)。其次,进行多播过滤来检测该主机是否属于多播地址说明的多播组。
设备驱动程序随后将数据帧传送给下一层,比如,当帧类型指定为IP数据报时,就传往IP层。IP根据IP地址中的源地址和目的地址进行更多的过滤检测。如果正常,就将数据报传送给下一层(如TCP或UDP)。
每次UDP收到由IP传送来的数据报,就根据目的端口号,有时还有源端口号进行数据报过滤。如果当前没有进程使用该目的端口号,就丢弃该数据报并产生一个ICMP不可达报文(TCP根据它的端口号作相似的过滤)。如果UDP数据报存在检验和错,将被丢弃。
使用广播的问题在于它增加了对广播数据不感兴趣主机的处理负荷。拿一个使用UDP广播应用作为例子。如果网内有50个主机,但仅有20个参与该应用,每次这20个主机中的一个发送UDP广播数据时,其余30个主机不得不处理这些广播数据报。一直到UDP层,收到的UDP广播数据报才会被丢弃。这30个主机丢弃UDP广播数据报是因为这些主机没有使用这个目的端口。
多播的出现减少了对应用不感兴趣主机的处理负荷。使用多播,主机可加入一个或多个多播组。这样,网卡将获悉该主机属于哪个多播组,然后仅接收主机所在多播组的那些多播帧。
12.2 广播
在图3-9中,我们知道了四种IP广播地址,下面对它们进行更详细的介绍。
12.2.1 受限的广播
受限的广播地址是255.255.255.255。该地址用于主机配置过程中IP数据报的目的地址,此时,主机可能还不知道它所在网络的网络掩码,甚至连它的IP地址也不知道。
在任何情况下,路由器都不转发目的地址为受限的广播地址的数据报,这样的数据报仅出现在本地网络中。
一个未解的问题是:如果一个主机是多接口的,当一个进程向本网广播地址发送数据报时,为实现广播,是否应该将数据报发送到每个相连的接口上?如果不是这样,想对主机所有接口广播的应用必须确定主机中支持广播的所有接口,然后向每个接口发送一个数据报复制。
大多数BSD系统将255.255.255.255看作是配置后第一个接口的广播地址,并且不提供向所属具备广播能力的接口传送数据报的功能。不过,routed(见10.3节)和rwhod(BSDrwho客户的服务器)是向每个接口发送UDP数据报的两个应用程序。这两个应用程序均用相似的启动过程来确定主机中的所有接口,并了解哪些接口具备广播能力。同时,将对应于那种接口的指向网络的广播地址作为发往该接口的数据报的目的地址。
Host Requirements
RFC没有进一步涉及多接口主机是否应当向其所有的接口发送受限的广播。
12.2.2 指向网络的广播
指向网络的广播地址是主机号为全1的地址。A类网络广播地址为netid.255.255.255其中netid为A类网络的网络号。
一个路由器必须转发指向网络的广播,但它也必须有一个不进行转发的选择。
12.2.3 指向子网的广播
指向子网的广播地址为主机号为全1且有特定子网号的地址。作为子网直接广播地址的IP地址需要了解子网的掩码。例如,如果路由器收到发往128.1.2.255的数据报,当B类网络128.1的子网掩码为255.255.255.0时,该地址就是指向子网的广播地址;但如果该子网的掩码为255.255.254.0,该地址就不是指向子网的广播地址。
12.2.4 指向所有子网的广播
指向所有子网的广播也需要了解目的网络的子网掩码,以便与指向网络的广播地址区分开。指向所有子网的广播地址的子网号及主机号为全1。例如,如果目的子网掩码为255.255.255.0,那么IP地址128.1.255.255是一个指向所有子网的广播地址。然而,如果网络没有划分子网,这就是一个指向网络的广播。
当前的看法[Almquist 1993]是这种广播是陈旧过时的,更好的方式是使用多播而不是对所有子网的广播。
[Almquist 1993] 指出RFC 922要求将一个指向所有子网的广播传送给所有子网,但当前的路由器没有这么做。这很幸运,因为一个因错误配置而没有子网掩码的主机会把它的本地广播传送到所有子网。例如,如果IP地址为128.1.2.3的主机没有设置子网掩码,它的广播地址在正常情况下的默认值是128.1.255.255。但如果子网掩码被设置为255.255.255.0,那么由错误配置的主机发出的广播将指向所有的子网。
1983年问世的4.2BSD是第一个影响广泛的TCP/IP的实现,它使用主机号全0作为广地址。一个最早提到广播IP地址的是IEN 212 [Gurwitz and Hinden 1982],它提出用主机号中的1比特来表示IP广播地址(IENs是互联网试验注释,基本上是RFC的前身)。RFC 894 [Hornig
1984]认为4.2BSD使用不标准的广播地址,但RFC 906 [Finlayson 1984]注意到对广播地址还没有Internet标准。RFC编辑在RFC 906中加了一个脚注承认缺少标准的广播地址,并强烈推荐将主机号全1作为广播地址。尽管1986年的4.3BSD采用主机号全1表示广播地址,但直到90年代早期,操作系统(著名的是SunOS 4.x)还继续使用非标准的广播地址。
12.3 广播的例子
广播是怎样传送的?路由器及主机又如何处理广播?很遗憾,这是难以回答的问题,因为它依赖于广播的类型、应用的类型、TCP/IP实现方法以及有关路由器的配置。
首先,应用程序必须支持广播。如果执行
sun % ping 255.255.255.255
/usr/etc/ping: unknown host 255.255.255.255
打算在本地电缆上进行广播。但它无法进行,原因在于该应用程序(ping)中存在一个程序设计上的问题。大多数应用程序收到点分十进制的IP地址或主机名后,会调用函数inet_addr(3)来把它们转化为32bit的二进制IP地址。假定要转化的是一个主机名,如果转化失败,该库函数将返回-1来表明存在某种差错(例如是字符而不是数字或串中有小数点)。但本网广播地址(255.255.255.255)也被当作存在差错而返回- 1。大多数程序均假定接收到的字符串是主机名,然后查找DNS(第14章),失败后输出差错信息如"未知主机"。
如果我们修复ping程序中这个欠缺,结果也并不总是令人满意的。在6个不同系统的测试中,仅有一个像预期的那样产生了一个本网广播数据报。大多数则在路由表中查找IP地址255.255.255.255,而该地址被用作默认路由器地址,因此向默认路由器单播一个数据报。最终该数据报被丢弃。
指向子网的广播是我们应该使用的。在6.3节中,我们向测试网络(见扉页前图)中IP地址为140.252.13.63的以太网发送数据报,并接收以太网中所有主机的应答。与子网广播地址关联的每个接口是用于命令ifconfig(见3.8节)的值。如果我们ping那个地址,预期的结果是:

IP通过目的地址(140.252.13.63)来确定,这是指向子网的广播地址,然后向链路层的广播地址发送该数据报。
在6.3节提到的这种广播类型的接收对象为局域网中包括发送主机在内的所有主机,因此可以看到除了收到网内其他主机的答复外,还收到来自发送主机(sun)的答复。
在这个例子中,我们也显示了执行ping广播地址前后ARP缓存的内容。这可以显示广播与ARP之间的相互作用。执行ping命令前ARP缓存是空的,而执行后是满的(也就是说,对网内其他每个响应回显请求的主机在ARP缓存中均有一个条目)。我们提到的该以太网数据帧被传送到链路层的广播地址(0 x ffffffff)是如何发生的呢?由sun主机发送的数据帧不需要ARP。
如果使用tcpdump来观察ping的执行过程,可以看到广播数据帧的接收者在发送它的响应之前,首先产生一个对sun主机的ARP请求,因为它的应答是单播的。在4.5节我们介绍了一个ARP请求的接收者(该例中是sun)通常在发送ARP应答外,还将请求主机的IP地址和物理地址加入到ARP缓存中去。这基于这样一个假定:如果请求者向我们发送一个数据报,我们也很可能想向它发回什么。
我们使用的ping程序有些特殊,原因在于它使用的编程接口(在大多数Unix实现中是低级插口(rawsocket))通常允许向一个广播地址发送数据报。如果使用不支持广播的应用如TFTP,情况又如何呢?(TFTP将在第15章详细介绍。)
bsdi % tftp 启动客户程序
tftp> connect 140.252.13.63 说明服务器的IP地址
tftp> get temp.foo 试图从服务器或获取一个文件
tftp: sendto: Permission denied
tftp> q u i t 终止客户程序
在这个例子中,程序立即产生了一个差错,但不向网络发送任何信息。产生这一切的原因在于,插口提供的应用程序接口API只有在进程明确打算进行广播时才允许它向广播地址发送UDP数据报。这主要是为了防止用户错误地采用了广播地址(正如此例)而应用程序却不打算广播。
在广播UDP数据报之前,使用插口中API的应用程序必须设置SO_BROADCAST插口选项。
并非所有系统均强制使用这个限制。某些系统中无需进程进行这个说明就能广播UDP数据报。而某些系统则有更多的限制,需要有超级用户权限的进程才能广播。
下一个问题是是否转发广播数据。有些系统内核和路由器有一选项来控制允许或禁止这一特性(见附录E)。
如果让路由器bsdi能够转发广播数据,然后在主机slip上运行ping程序,就能够观察到由路由器bsdi转发的子网广播数据报。转发广播数据报意味着路由器接收广播数据,确定该目的地址是对哪个接口的广播,然后用链路层广播向对应的网络转发数据报。

我们观察到它的确正常工作了,同时也看到BSD系统中的ping程序检查重复的数据报序列号。如果出现重复序列号的数据报就显示DUP!,这意味着一个数据报已经在某处重复了,然而它正是我们所期望看到的,因为我们正向一个广播地址发送数据。
我们还可以从远离广播所指向的网络上的主机上来进行这个试验。在主机angogh.cx.berkeley.edu(和我们的网络距离14跳)上运行ping程序,如果路由器sun被设置为能够转发所指向的广播,它还能正常工作。在这种情况下,这个IP数据报(传送ICMP回显请求)被路径上的每个路由器像正常的数据报一样转发,它们均不知道传送的实际上是广播数据。接着最后一个路由器netb看到主机号为63,就将其转发给路由器sun。路由器sun觉察到该目的IP地址事实上是一个相连子网接口上的广播地址,就将该数据报以链路层广播传往相应网络。
广播是一种应该谨慎使用的功能。在许多情况下,
IP多播被证明是一个更好的解决办法。
12.4 多播
IP多播提供两类服务:
1)
向多个目的地址传送数据。有许多向多个接收者传送信息的应用:例如交互式会议系统和向多个接收者分发邮件或新闻。如果不采用多播,目前这些应用大多采用TCP来完成(向每个目的地址传送一个单独的数据复制)。然而,即使使用多播,某些应用可能继续采用TCP来保证它的可靠性。
2)
客户对服务器的请求。例如,无盘工作站需要确定启动引导服务器。目前,这项服务是通过广播来提供的(正如第16章的BOOTP),但是使用多播可降低不提供这项服务主机的负担。
12.4.1 多播组地址
图1 2 - 2显示了D类IP地址的格式。

不像图1 - 5所示的其他三类IP地址(A、B和C),分配的28bit均用作多播组号而不再表示其他。
多播组地址包括为111 0的最高4bit和多播组号。它们通常可表示为点分十进制数,范围从224.0.0.0到239.255.255.255。
能够接收发往一个特定多播组地址数据的主机集合称为主机组(host group)。一个主机组可跨越多个网络。主机组中成员可随时加入或离开主机组。主机组中对主机的数量没有限制,同时不属于某一主机组的主机可以向该组发送信息。
一些多播组地址被IANA确定为知名地址。它们也被当作永久主机组,这和TCP及UDP中的熟知端口相似。同样,这些知名多播地址在RFC最新分配数字中列出。注意这些多播地址所代表的组是永久组,而它们的组成员却不是永久的。
例如,224.0.0.1代表"该子网内的所有系统组",224.0.0.2代表"该子网内的所有路由器组"。多播地址224.0.1.1用作网络时间协议NTP,224.0.0.9用作RIP-2 (见10.5节),224.0.1.2用作SGI公司的dogfight应用。
12.4.2 多播组地址到以太网地址的转换
IANA拥有一个以太网地址块,即高位24bit为00:00:5e(十六进制表示),这意味着该地址块所拥有的地址范围从00:00:5e:00:00:00到00:00:5e:ff:ff:ff。IANA将其中的一半分配为多播地址。为了指明一个多播地址,任何一个以太网地址的首字节必须是01,这意味着与IP多播相对应的以太网地址范围从01:00:5e:00:00:00到01:00:5e:7f:ff:ff。
这里对CSMA/CD或令牌网使用的是Internet标准比特顺序,和在内存中出现的比特顺序一样。这也是大多数程序设计员和系统管理员采用的顺序。IEEE文档采用了这种比特传输顺序。Assigned Numbers RFC给出了这些表示的差别。
这种地址分配将使以太网多播地址中的23 bit与IP多播组号对应起来,通过将多播组号中的低位23 bit映射到以太网地址中的低位23 bit实现,这个过程如图12 - 3所示。
由于多播组号中的最高5 bit在映射过程中被忽略,因此每个以太网多播地址对应的多播组是不唯一的。32个不同的多播组号被映射为一个以太网地址。例如,多播地址224.128.64.32(十六进制e0.80.40.20)和224.0.64.32(十六进制e0.00.40.20)都映射为同一以太网地址01:00:5e:00:40:20。
既然地址映射是不唯一的,那么设备驱动程序或IP层(见图12 -1)就必须对数据报进行过滤。因为网卡可能接收到主机不想接收的多播数据帧。另外,如果网卡不提供足够的多播数据帧过滤功能,设备驱动程序就必须接收所有多播数据帧,然后对它们进行过滤。

局域网网卡趋向两种处理类型:一种是网卡根据对多播地址的散列值实行多播过滤,这意味仍会接收到不想接收的多播数据;另一种是网卡只接收一些固定数目的多播地址,这意味着当主机想接收超过网卡预先支持多播地址以外的多播地址时,必须将网卡设置为"多播混杂(multicast
promiscuous)"模式。因此,这两种类型的网卡仍需要设备驱动程序检查收到的帧是否真是主机所需要的。
即使网卡实现了完美的多播过滤(基于48bit的硬件地址),由于从D类IP地址到48 bit的硬件地址的映射不是一对一的,过滤过程仍是必要的。
尽管存在地址映射不完美和需要硬件过滤的不足,多播仍然比广播好。
单个物理网络的多播是简单的。多播进程将目的IP地址指明为多播地址,设备驱动程序将它转换为相应的以太网地址,然后把数据发送出去。这些接收进程必须通知它们的IP层,它们想接收的发往给定多播地址的数据报,并且设备驱动程序必须能够接收这些多播帧。这个过程就是"加入一个多播组"(使用"接收进程"复数形式的原因在于对一确定的多播信息,在同一主机或多个主机上存在多个接收者,这也是为什么要首先使用多播的原因)。当一个主机收到多播数据报时,它必须向属于那个多播组的每个进程均传送一个复制。这和单个进程收到单播UDP数据报的UDP不同。使用多播,一个主机上可能存在多个属于同一多播组的进程。
当把多播扩展到单个物理网络以外需要通过路由器转发多播数据时,复杂性就增加了。需要有一个协议让多播路由器了解确定网络中属于确定多播组的任何一个主机。这个协议就是Internet组管理协议(IGMP),也是下一章介绍的内容。
12.4.3 FDDI和令牌环网络中的多播FDDI网络使用相同的D类IP地址到48 bit FDDI地址的映射过程[Katz 1990]。令牌环网络通常使用不同的地址映射方法,这是因为大多数令牌控制中的限制。

广播是将数据报发送到网络中的所有主机(通常是本地相连的网络),而多播是将数据报发送到网络的一个主机组。这两个概念的基本点在于当收到送往上一个协议栈的数据帧时采用不同类型的过滤。每个协议层均可以因为不同的理由丢弃数据报。
目前有四种类型的广播地址:受限的广播、指向网络的广播、指向子网的广播和指向所有子网的广播。最常用的是指向子网的广播。受限的广播通常只在系统初始启动时才会用到。
试图通过路由器进行广播而发生的问题,常常是因为路由器不了解目的网络的子网掩码。结果与多种因素有关:广播地址类型、配置参数等等。
D类IP地址被称为多播组地址。通过将其低位23bit映射到相应以太网地址中便可实现多播组地址到以太网地址的转换。由于地址映射是不唯一的,因此需要其他的协议实现额外的数据报过滤。