乐趣区

关于程序员:感悟篇-阅读-Unix-分时系统的进化

论文名: The Evolution of the Unix Time-sharing System — Dannis M. Ritchie

丹尼斯 - 里奇 回顾了与 肯 - 汤普森 等在贝尔实验室发明 Unix 的历程, 而后介绍了一下 Unix 中最重要的几个局部, 包含:

文件系统

  1. i-list: 一个由 i-nodes 组成的数组, 每个 i-node 形容一个文件. i-node 里蕴含文件的元数据: 例如保护模式, 类型和大小, 以及内容所在的物理地位.
  2. 目录: 一种非凡的文件, 蕴含了一系列的文件名以及相干的 i-number.(我感觉 i-number 应该就是 i-node 的 ID 吧)
  3. 非凡的文件用于形容设施. 特定的 i-number 对应特定的设施.

过程管制机制

shell 执行命令的大略的步骤是这样:

  1. shell 从终端读取命令
  2. 新建一个过程
  3. 子过程执行命令
  4. 同时, shell 开始期待直到子过程执行结束
  5. shell 回到第一步

感觉挺乏味的, 我用 elixir 模仿了一下:

defmodule MF.PC do
  def loop do
    cmd = IO.read(:line)
    pid = self()

    spawn(fn ->
      exec(cmd, pid)
    end)

    wait()
  end

  defp exec(cmd, pid) do
    send(pid, {:done, String.upcase(cmd)})
  end

  defp wait do
    receive do
      {:done, msg} ->
        IO.puts(msg)
        loop()
    end
  end
end

无论输出什么, 都返回大写的输出.

iex(2)> MF.PC.loop
hello
HELLO

how are u
HOW ARE U

fine
FINE

good bye
GOOD BYE

好吧, 挺无聊的, 只是了解一下 Unix 里过程消息传递的模式.

论文里提到很好玩的一个 bug, 就是一开始 chdir 命令, 也就是 cd, 也是像下面那样执行的, 后果, 只有子过程的工作目录变更了, 对 shell 自身齐全不起作用. 所以他们把 cd 变为非凡命令, 只在以后过程里执行.

论文里还提到一个乏味的 bug, 如果在一个脚本文件 “comfile” 里有如下命令:

ls
who

而后咱们在 shell 里执行:

sh comfile >output

料想的后果是 lswho 的执行后果被顺次写入到 output 文件中. 但实际上, 因为最后 unix 将文件的 io 指针保留在了执行 “ 关上文件 ” 的过程里, 也就是主 shell 过程, 而执行写入操作的, 是咱们用 sh 命令开启的子 shell, 所以文件的 io 指针始终没有变动, 导致 who 的输入把 ls的输入笼罩了. 为了修复这个问题, 他们在零碎中增加了一个表, 保留了全副的关上状态的文件的 io 指针.

说个题外话, 我忽然想到在 elixir 里如同不能指定文件的写入地位, 查了一下是能够的:

iex(4)> :file.read_file "comfile"
{:ok, "ls\nwho\n"}
iex(5)> {:ok, device} = :file.open "comfile", [:raw, :write]
{:ok,
 {:file_descriptor, :prim_file,
  %{
    handle: #Reference<0.1011150086.1394212882.243351>,
    owner: #PID<0.110.0>,
    r_ahead_size: 0,
    r_buffer: #Reference<0.1011150086.1394212865.243949>
  }}}
iex(6)> :file.pwrite(device, 1, 'hello')                  
:ok
iex(7)> :file.read_file "comfile"                           
{:ok, <<0, 104, 101, 108, 108, 111>>}
iex(8)> <<104, 101, 108, 108, 111>>
"hello"

最初是还提到了一下管道操作符 | 和 C 语言的来历.

退出移动版