A primeira versão do UNIX
- por Sergio Prado
O UNIX é um dos sistemas operacionais mais influentes na história da computação. Criado por pesquisadores da AT&T entre o final da década de 60 e o início dos anos 70, foi implementado por diversas empresas e instituições de ensino ao redor do mundo (Solaris, AIX, HP-UX, OS-X, BSD, Minix, etc), servindo de motivação para a criação do que é hoje o sistema operacional de código aberto mais usado no mundo, o Linux!
Durante um tempo, acreditou-se que o código-fonte original da primeira versão do UNIX estivesse perdida para sempre. Mas em 2006, foi encontrado um documento escrito por T.R. Bashkow e entitulado “Study of Unix“, que descrevia a estrutura e os componentes internos do UNIX, incluindo uma listagem do código-fonte original em assembly!
Foi a deixa para ressussitar um dos softwares mais influentes de todos os tempos. Em 2008, uma equipe da The Unix Heritage Society (TUHS) conseguiu completar este trabalho. Foi necessário escanear o documento e passar por uma ferramenta de OCR para converter para o código-fonte original, incluindo aí o trabalho manual de revisar linha a linha do código-fonte escaneado! Durante o processo de recuperação, alguns bugs foram encontrados e corrigidos. No final, usando uma ferramenta de emulação com suporte ao PDP11, conseguiram rodar a primeira versão do UNIX, cujo código-fonte está disponível para todos os interessados e amantes da computação no Github.
Que tal então um pouco de diversão?
COMPILANDO O UNIX v1.0
O primeiro passo é baixar o código-fonte do UNIX:
$ cd ~/ $ git clone https://github.com/c3x04/Unix-1st-Edition-jun72 unix $ cd unix |
Verifique se o código-fonte foi baixado com sucesso:
$ ls boot Credits Dockerfile Makefile notes patches simh.cfg tools build diffs fs misc pages Readme src |
Para os mais curiosos, o diretório pages contém as páginas escaneadas do código-fonte original do UNIX:
$ ls pages/ e00-01 e00-08 e01-05 e02-02 e02-09 e04-02 e05-02 e06-03 e07-04 e08-03 e09-01 e09-08 e11-05 e00-02 e00-09 e01-06 e02-03 e02-10 e04-03 e05-03 e06-04 e07-05 e08-04 e09-02 e10-01 e11-06 e00-03 e00-10 e01-07 e02-04 e03-01 e04-04 e05-04 e06-05 e07-06 e08-05 e09-03 e10-02 e11-07 e00-04 e01-01 e01-08 e02-05 e03-02 e04-05 e05-05 e06-06 e07-07 e08-06 e09-04 e11-01 e12-01 e00-05 e01-02 e01-09 e02-06 e03-03 e04-06 e05-06 e07-01 e07-08 e08-07 e09-05 e11-02 e12-02 e00-06 e01-03 e01-10 e02-07 e03-04 e04-07 e06-01 e07-02 e08-01 e08-08 e09-06 e11-03 e12-03 e00-07 e01-04 e02-01 e02-08 e04-01 e05-01 e06-02 e07-03 e08-02 e08-09 e09-07 e11-04 e12-04 |
Com a ajuda de uma ferramenta de OCR, o conteúdo destas páginas foi convertido em arquivos assembly no diretório build do projeto:
$ ls build/ cleansrc Makefile root u0.clean u2.clean u4.s u6.s u9.clean ux.clean images patched sh.0405 u0.s u2.s u4.s.orig u7.clean u9.s ux.s init.0405 protofs sh.clean u0.s.orig u3.clean u5.clean u7.s unix init.clean rf0.dsk sh.s u1.clean u3.s u5.s u8.clean usr init.s rk0.dsk sh.s.orig u1.s u4.clean u6.clean u8.s usyms |
Para os apreciadores da arte, segue um pedacinho de assembly do UNIX, responsável pelo tratamento das chamadas de sistema (arquivo u1.s):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
/ u1 -- unix unkni: / used for all system calls sysent: incb sysflg / indicate a system routine is beq 1f / in progress jmp panic / called if trap inside system 1: mov $s.syst+2,clockp mov r0,-(sp) / save user registers mov sp,u.r0 / pointer to bottom of users stack in u.r0 mov r1,-(sp) mov r2,-(sp) mov r3,-(sp) mov r4,-(sp) mov r5,-(sp) mov ac,-(sp) / "accumulator" register for extended / arithmetic unit mov mq,-(sp) / "multiplier quotient" register for the / extended arithmetic unit mov sc,-(sp) / "step count" register for the extended / arithmetic unit mov sp,u.sp / u.sp points to top of users stack mov 18.(sp),r0 / store pc in r0 mov -(r0),r0 / sys inst in r0 10400xxx sub $sys,r0 / get xxx code asl r0 / multiply by 2 to jump indirect in bytes cmp r0,$2f-1f / limit of table (35) exceeded bhis badsys / yes, bad system call bic $341,20.(sp) / set users processor priority to 0 and clear / carry bit jmp *1f(r0) / jump indirect thru table of addresses / to proper system routine. 1: sysrele / 0 sysexit / 1 sysfork / 2 sysread / 3 syswrite / 4 sysopen / 5 sysclose / 6 syswait / 7 syscreat / 8 syslink / 9 sysunlink / 10 sysexec / 11 syschdir / 12 systime / 13 sysmkdir / 14 syschmod / 15 syschown / 16 sysbreak / 17 sysstat / 18 sysseek / 19 systell / 20 sysmount / 21 sysumount / 22 syssetuid / 23 sysgetuid / 24 sysstime / 25 sysquit / 26 sysintr / 27 sysfstat / 28 sysemt / 29 sysmdate / 30 sysstty / 31 sysgtty / 32 sysilgins / 33 |
Para compilar o UNIX, basta executar o make:
$ make |
Depois de alguns segundos, as imagens estarão disponíveis no diretório images:
$ ls images/ m792low.load rf0.dsk rk0.dsk |
EMULANDO O UNIX
O UNIX original foi escrito em um PDP-7, e depois portado para o PDP-11. Os PDPs eram minicomputadores fabricados nas décadas de 70 e 80 pela antiga DEC (Digital Equipment Corp), comprada pela Compaq e hoje parte da HP. É considerado por muitos especialistas como o minicomputador mais popular da história da computação, influenciando a arquitetura de plataformas famosas como o x86 da Intel e o 68000 da Motorola.
O PDP-11/20, uma das versões deste minicomputador, era uma máquina de 16 bits com 56K de RAM, custando uma bagatela de $20.000! Olha a pose da criança na imagem abaixo:
E para testar a imagem do Unix, precisamos de um simulador do PDP-11. Para isso, podemos usar o SIMH.
$ mkdir -p ~/unix/simh && cd ~/unix/simh $ wget http://simh.trailing-edge.com/sources/simhv39-0.zip $ unzip simhv39-0.zip |
O simulador pode ser compilado com o comando abaixo:
$ make pdp11 |
No final da compilação, copie o binário do emulador para o diretório tools do código-fonte do UNIX:
$ cp -av BIN/pdp11 ~/unix/tools/ |
Agora é só retornar ao diretório do código-fonte do UNIX e iniciar a emulação da imagem gerada:
$ cd ~/unix/ $ ./simh.cfg PDP-11 simulator V3.9-0 ./simh.cfg> #!tools/pdp11 Unknown command Disabling CR Disabling XQ RF: buffering file in memory TC: creating new file TC0: 16b format, buffering file in memory Listening on port 5555 (socket 7) :login: |
Faça o login com o usuário root (sem senha).
Achievement unlocked: login on the first UNIX version! :)
Claro que é um sistema bem limitado, mas qualquer semelhança com o sistema operacional do pinguim não é mera coincidência! :)
# ls -l / total 5 57 sdrwr- 2 root 620 Jan 1 00:00:00 bin 42 sdrwr- 2 root 250 Jan 1 00:00:00 dev 43 sdrwr- 2 root 110 Jan 1 00:00:00 etc 53 sdrwr- 2 root 50 Jan 1 00:00:00 tmp |
Algumas curiosidades sobre a primeira versão do UNIX:
- São aproximadamente 4.200 linhas de código-fonte em assembly, que ocupam 16K de RAM.
- Muitas das características do UNIX, como um terminal para executar comandos (shell) e redirecionamento de I/O foram herdadas do Multics.
- Suporta no máximo 16 processos, onde apenas um pode estar em memória em um determinado momento (todos os outros processos são movidos para uma região de SWAP).
- Estão disponíveis 34 chamadas de sistema, e destas, 24 existem até hoje no código-fonte do kernel Linux, inclusive com o mesmo número identificador de chamada de sistema!
- O único editor de textos disponível é o ed, que até hoje é o editor de textos cuja presença é garantida em todo sistema UNIX.
Para os mais aventureiros, o manual da primeira edição do UNIX está disponível na Internet.
Have fun!
Sergio Prado