Если компьютеры начинают считать с 0, почему процесс init имеет pid 1?

27

Не так много, чтобы положить здесь, в теле.

benwaffle
источник
18
pid0 имеет особое значение для kill(2)системного вызова , где это означает себя и waitpid(2)где это означает , что любой процесс в моей группе процессов , по крайней мере. Не говоря уже о том, что fork()возвращение 0означает, что мы в ребенке.
Стефан Шазелас
1
Вы должны опубликовать это как ответ
Джонатан Мюллер
3
Ноль приводит к тому, что флаги автоматически устанавливаются в большинстве регистров состояния ЦП, когда он загружается в регистр, что позволяет использовать для него ветвь без специального сравнения / тестирования для него. Поэтому он очень часто используется в качестве значения «дозорного», то есть значения, которое здесь означает «недействительный», «конец данных» или «особый случай». Таким образом, даже если компьютеры начинают считать с 0, во многих случаях 1 является первым действительным значением для рассматриваемого приложения или структуры данных.
LawrenceC
4
Примечание: компьютеры не начинают считать с нуля. Многие языки программирования, и я считаю, что все машинные языки используют смещения, когда другие (и большинство людей) используют индексы, но, несмотря ни на что, подсчет считается подсчетом. Массив с двумя элементами имеет два элемента (считайте их), независимо от того, ссылается ли ваш язык на них по смещению или по индексу.
Jthill
скорее всего, это случай противоположных основополагающих парадигм программирования: тяготение программиста к особым значениям флага (ноль, отрицание) превосходит меньшую тягу склонности для систем нумерации с нулями.
Майкл

Ответы:

29

Процессы должны иметь родителя (PPID). Ядро, несмотря на то, что оно не является реальным процессом, тем не менее вручную создает некоторые реальные процессы, такие как, по крайней мере, init, и присваивает себе идентификатор процесса 0. В зависимости от ОС оно может отображаться или не отображаться как psвыходной процесс, но всегда отображается в качестве PPID:

например, в Linux:

$ ps -ef|head
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 09:09 ?        00:00:00 /sbin/init
root         2     0  0 09:09 ?        00:00:00 [kthreadd]
root         3     2  0 09:09 ?        00:00:00 [ksoftirqd/0]
...

на солярисе:

$ ps -ef|head
     UID   PID  PPID   C    STIME TTY         TIME CMD
    root     0     0   0   Oct 19 ?           0:01 sched
    root     5     0   0   Oct 19 ?          11:20 zpool-rpool1
    root     1     0   0   Oct 19 ?           0:13 /sbin/init
    root     2     0   0   Oct 19 ?           0:07 pageout
    root     3     0   1   Oct 19 ?         117:10 fsflush
    root   341     1   0   Oct 19 ?           0:15 /usr/lib/hal/hald --daemon=yes
    root     9     1   0   Oct 19 ?           0:59 /lib/svc/bin/svc.startd
...

Также обратите внимание, что pid 0-1другие отрицательные значения в этом отношении) имеют разные значения в зависимости от того, какая функция их использует kill, forkи waitpid.

Наконец, в то время как initпроцессу традиционно присваивается pid #1, это больше не тот случай, когда виртуализация на уровне ОС используется как зоны Solaris, так как может быть несколько initзапущенных:

$ ps -ef|head
     UID   PID  PPID   C    STIME TTY         TIME CMD
    root  4733  3949   0 11:07:25 ?           0:26 /lib/svc/bin/svc.configd
    root  4731  3949   0 11:07:24 ?           0:06 /lib/svc/bin/svc.startd
    root  3949  3949   0 11:07:14 ?           0:00 zsched
  daemon  4856  3949   0 11:07:46 ?           0:00 /lib/crypto/kcfd
    root  4573  3949   0 11:07:23 ?           0:00 /usr/sbin/init
  netcfg  4790  3949   0 11:07:34 ?           0:00 /lib/inet/netcfgd
    root  4868  3949   0 11:07:48 ?           0:00 /usr/lib/pfexecd
    root  4897  3949   0 11:07:51 ?           0:00 /usr/lib/utmpd
  netadm  4980  3949   0 11:07:54 ?           0:01 /lib/inet/nwamd
jlliagre
источник
5

Есть две задачи со специально выделенными идентификаторами процессов: swapper или sched имеет идентификатор процесса 0 и отвечает за подкачку страниц, как jlliagre, приведенный в предыдущих примерах, и фактически является частью ядра, а не обычным процессом пользовательского режима.

Идентификатор процесса 1 обычно является процессом инициализации, главным образом ответственным за запуск и выключение системы. Первоначально, идентификатор процесса 1 не был специально зарезервирован для init никакими техническими мерами: он просто имел этот идентификатор как естественное следствие того, что ядро ​​было первым процессом, вызванным ядром. Более поздние системы Unix обычно имеют дополнительные компоненты ядра, видимые как «процессы», и в этом случае PID 1 активно резервируется для процесса init, чтобы поддерживать согласованность со старыми системами.

curratore
источник
4

В общем, 0 часто используется для обозначения «нулевой ссылки». Это означало, что, хотя значение 0 существует, вы можете его не использовать, потому что вы хотите, чтобы ноль означал специальное значение.

user606723
источник