前几天为了测试一个程序,在 SimH 模拟的 DEC VAX-11/780 计算机中安装了 4.3BSD 系统(大概是历史上最伟大的操作系统之一?)。本系统于 1986 年夏天在加州伯克利新鲜出炉,安装磁带绝赞发售中……
# dmesg | head
4.3 BSD UNIX #1: Fri Jun 6 19:55:29 PDT 1986
karels@monet.Berkeley.EDU:/usr/src/sys/GENERIC
real mem = 8388608
系统的安装过程完全是按照一篇教程进行的。当完成教程后,就可以启动 VAX-11/780 并进入 BSD 系统,这里就不重复了。
登录系统
4.3 BSD UNIX (bsd.my.domain) (console)
login: root
Last login: Mon Jan 27 09:19:47 on console
Jan 27 10:20:58 bsd login: ROOT LOGIN console
4.3 BSD UNIX #1: Fri Jun 6 19:55:29 PDT 1986
Would you like to play a game?
Don't login as root, use su
bsd#
一切仿佛就在昨天,Unix 的 getty 这么多年都没有变化过。另外发现原来连 4.3BSD 都会嘲笑 root 敢死队——小心点,如果误操作,你会引起第三次世界核大战的……(”Would you like to play a game” 显然是 BSD 开发者在玩 1983 年好莱坞科幻《Wargames》的梗)。
系统中甚至有有个名为 /usr/games/wargames
的游戏……
# /usr/games/wargames
Would you like to play a game? yes
Funny, the only way to win is not to play at all
不管你回答什么,它都只会打印 “Funny, the only way to win is not to play at all”,纯粹是为了玩梗而存在。如今技术圈的社交媒体的人们经常玩科幻、电影、动画相关的各种梗,看来一直是历史传统了。
寻找源代码
不玩游戏了,回到测试工作。
众所周知,BSD 操作系统不只是一个内核,而是一套完整的操作系统。因此,所有程序的全套源代码都可以在 /usr/src 中找到。为了进行测试,我需要调试并修改某个系统工具的源代码。于是我使用了 find 快速递归列出文件。
# find /usr/src
/usr/src
...
/usr/src/bin/as
...
/usr/src/bin/awk
...
/usr/src/bin/cat.c
/usr/src/bin/cc.c
/usr/src/bin/chgrp.c
/usr/src/bin/chmod.c
/usr/src/bin/cmp.c
/usr/src/bin/cp.c
/usr/src/bin/csh
...
/usr/src/bin/date.c
/usr/src/bin/dd.c
/usr/src/bin/df.c
/usr/src/bin/diff
/usr/src/bin/diff/diff.c
源代码是应有尽有,一目了然。
见鬼的是这个目录居然不存在?!
# ls /usr/src
/usr/src not found
显然 find 对系统中存在的文件似乎有不同的理解。不过没有什么是看文档解决不了的问题,RTFM 一下。
# man find
SYNOPSIS
find pathname-list expression
find pattern
DESCRIPTION
...
The second form rapidly searches a database for all path-
names which match pattern. Usually the database is recom-
puted weekly and contains the pathnames of all files which
are publicly accessible.
原来 BSD 的 find(1)
居然这么强大,还包含了文件索引的功能(GNU/Linux 用户可以理解为 updatedb + locate)。换句话说,现在列出的文件都是安装盘建立时的索引,并不实际存在。
磁带
显然,/usr/src 在这台机器上还没有被安装,需要从磁带安装。要使用磁带,必须先将磁带放入磁带机,并根据磁带机的型号在 /dev 下创建设备文件。在 SimH 模拟器的 .ini 配置文件中,我已经配置好了磁带机设备 ts0,它对应的是 DEC TS-11 型磁带机。从名字就可以看出,这台磁带机最初来自 PDP-11 计算机,后来在 VAX-11 时代沿用。
att ts 43.tap
开机时可以在 dmesg 中看到磁带机。
# dmesg | grep ts0
ts0 at zs0 slave 0
但是却找不到相关的设备文件。
# ls /dev/ts0 /dev/zs0
/dev/ts0 not found
/dev/zs0 not found
原来 ts0 和 zs0 都是内核驱动的硬件设备名,并非真正的设备文件。因此,首先创建设备文件。由于 Unix 支持大量不同的设备,创建设备文件是一项十分繁琐的任务。好在 BSD 的同学们为我们准备了一个名为 ./MAKEDEV 的 shell 脚本。
# head /dev/MAKEDEV
#!/bin/sh -
#
# Copyright (c) 1980 Regents of the University of California.
# All rights reserved. The Berkeley software License Agreement
# specifies the terms and conditions for redistribution.
#
# @(#)MAKEDEV 4.27 (Berkeley) 4/15/86
创建 ts0 磁带机的设备文件时,只需要输入如下命令(不知为何,./MAKEDEV 没有可执行权限,于是使用 sh ./MAKEDEV)
# cd /dev
# sh ./MAKEDEV ts0
但运行后发现 MAKEDEV 创建的好几个设备文件,包括 /dev/mt0, /dev/mt4, /dev/mt8, /dev/mt12, /dev/rmt0, /dev/rmt4, /dev/rmt8, /dev/rmt12, /dev/nmt0, /dev/mnt8, /dev/nrmt0, /dev/nmrt8,不知应使用哪个文件。
实在不会了,只能上网搜索看看。我首先了解到知道的是,BSD 控制磁带机的工具是 mt,所以先看看本机中 mt 的文档(不能看网络上的,版本都不一样。看来在文档难求的年代,man page 能解决不少问题)。
# man mt
...
Mt is used to give commands to a magnetic tape drive. If a
tape name is not specified, the environment variable TAPE is
used; if TAPE does not exist, mt uses the device
/dev/rmt12.
status
Print status information about the tape unit.
原来可以查看磁带机的状态,试一试:
# mt status
ts11 tape drive, residual=0
ds=0
er=152<onl,ies,ped,bot></onl,ies,ped,bot>
确实能识别。
接下来意识到了 Unix 从磁带读取文件的工具是 tar(这显然是废话),也许 tar 的文档里有什么说明,继续 RTFM。
# man tar
t The names of the specified files are listed each
time they occur on the tape. If no file argument is
given, all of the names on the tape are listed.
f Tar uses the next argument as the name of the
archive instead of /dev/rmt?.
原来当 tar 没有指定任何文件时,它会去读取默认的磁带设备文件(不仅如今还有多少人使用过这个功能,反正我没有……)。这就试一试。
# tar t
tar: blocksize = 1
tar: directory checksum error (0 != 217)
tar 提示校验和错误。后来又使用 tar tf /dev/rmtX 把所有的设备文件都试了一遍,没有一个是能正常读取的。
彻底卡在这里了,只能从网络上搜索并重新阅读 SimH 的 4.3BSD 安装教程。原来 tar 不能读取磁带的原因是因为之前没有倒带到开头。
# mt rewind
倒带之后,还需要向后移动三条“空白计数文件”的距离。作为新手,我还并不清楚什么是空白计数文件,也不知道为什么是 3 个。不过先运行一下,日后慢慢了解。
# mt fsf 3
FSF 不是自由软件基金会,而 Forward Space Count Files 的缩写。
再试试 tar,成功!
# tar t
./
./cassette/
./dist/group
./dist/fstab.hp
./dist/motd
./dist/passwd
./dist/rc.local
./conf/touch.c
./h/mount.h
./h/signal.h
./h/quota.h
./netinet/tcp.h
./netinet/udp.h
能看到许多熟悉的文件,但并没有我要找的 /usr 或者 /usr/src。磁带后面还有更多文件,继续倒带。但运行 mt fsf 或者 mt fsf 3 没有效果。后来猜测之前的记录是 mt fsf 3,下一条可能是 mt fsf 6,果然如此。
# tar t
Makefile
...
bin/df.c
bin/hostid.c
bin/mail.c
bin/du.c
bin/strip.c
bin/stty.c
bin/cat.c
bin/ld.c
bin/login.c
bin/time.c
bin/ed.c
bin/nm.c
bin/dd.c
bin/su.c
bin/rm.c
bin/pr.c
bin/cp.c
bin/cmp.c
bin/true.sh
bin/false.sh
bin/ln.c
bin/grep.c
bin/write.c
bin/mv.c
bin/passwd.c
bin/echo.c
bin/hostname.c
bin/ps.c
bin/cc.c
bin/tar.c
bin/kill.c
bin/sync.c
bin/size.c
bin/date.c
bin/tee.c
bin/wall.c
bin/chmod.c
bin/test.c
bin/rmail.c
bin/od.c
bin/chgrp.c
bin/ar.c
bin/expr.y
bin/rcp.c
bin/ls.c
bin/Makefile
bin/mkdir.c
bin/mt.c
bin/nice.c
bin/pagesize.c
bin/pwd.c
bin/rmdir.c
bin/who.c
找到了,这就是 /usr/src。接下来只需要再重新倒带,向前快进并解压磁带上的tar 归档即可。
# mt rewind
# mt fsf 6
# mkdir /usr/src
# cd /usr/src
# tar x
大功告成。
# ls
Makefile etc/ include/ local/ ucb/ usr.bin/
bin/ games/ lib/ old/ undoc/ usr.lib/
关机
输入 halt。
# halt
Jan 27 11:01:03 bsd halt: halted by root
Jan 27 11:01:04 bsd syslogd: going down on signal 15
syncing disks... done
halting (in tight loop); hit
^P
HALT
由于 Unix 的传统 halt 命令是只关机不断电的(您现在可以安全的关闭计算机了?),因此模拟器此时会报 HALT 指令死循环错误。
HALT
Infinite loop, PC: 8002AFCD (BRB 8002AFCD)
输入 quit 退出 DEC VAX-11/780 模拟器。