Paper Title: The Evolution of the Unix Time-sharing System - Dannis M. Ritchie

Dennis Rich reviewed the history of creating Unix with Ken Thompson and others at Bell Labs, and then introduced the most important parts of Unix, including:

File system

  1. i-list: An array of i-nodes, each i-node describes a file. The i-node contains the metadata of the file: such as the protection mode, type and size, and the physical location of the content.
  2. Directory: A special file that contains a series of file names and related i-number. (I think i-number should be the ID of i-node)
  3. A special file is used to describe the device. A specific i-number corresponds to a specific device.

Process control mechanism

The approximate steps for the shell to execute a command are as follows:

  1. shell reads commands from the terminal
  2. Create a new process
  3. Child process execution command
  4. At the same time, the shell waits until the child process is completed
  5. shell back to the first step

It feels very interesting, I simulated it with 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

No matter what is entered, the uppercase input is returned.

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

how are u
HOW ARE U

fine
FINE

good bye
GOOD BYE

Well, it's boring, just understand the mode of process message passing in Unix.

A very interesting bug mentioned in the paper is that at the beginning, the chdir command, which is cd , was also executed as above. As a result, only the working directory of the child process was changed, which had no effect on the shell itself. So they changed cd Become a special command, which is only executed in the current process.

The paper also mentions an interesting bug, if there is the following command in a script file "comfile":

ls
who

Then we execute in the shell:

sh comfile >output

The expected result is ls and who are sequentially written to the output file. But in fact, because Unix initially saved the io pointer of the file in the process of executing the "open file", that is, the main shell process, and The write operation is performed by the sh we opened with the 060b9e49b86865 command, so the io pointer of the file has not changed, causing the output of ls who the output of 060b9e49b86868. In order to fix this problem, they added a table to the system. The io pointers of all open files are saved.

To make a digression, I suddenly thought that in elixir, it seems that the writing location of the file cannot be specified. It is OK to check:

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"

Finally, I also mentioned the | and the C language.


Ljzn
399 声望102 粉丝

网络安全;函数式编程;数字货币;人工智能