В Unix есть только один способ запустить пользовательский процесс - системный вызов fork(2)
.Он создает точную копию вызывающего процесса, разница состоит в том, что возвращаемое значение идентификатора вызова (pid
) нового процесса в родительском / вызывающем объекте равно нулю в дочернем.ОС поддерживает эти отношения родитель-потомок через свойство идентификатор родительского процесса (см., Например, вывод ps -f
).
Что происходит за сценой, так это то, что ядро ОС дублирует все пространство виртуальной памяти вызывающего абонента (здесь есть более подробная информация, Google для копирования страниц при копировании при записи и vfork
).Прямой доступ из одного адресного пространства в другое отсутствует, кроме случаев, когда он специально настроен через механизм разделяемой памяти , такой как mmap(2)
.Родительский процесс может wait(2)
завершить его дочерние процессы.
Я не собираюсь вдаваться в группы процессов , сессий иуправляющие терминалы.Это нуждается в хорошей картине.Посмотрите, скажем, книгу APUE для подробного объяснения.
Системный вызов execve(2)
заменяет текущий образ процесса на один из некоторых исполняемых файлов.из файла.
Теперь оболочка имеет stdin
, stdout
и stderr
, подключенные к терминальному эмулятору , унаследованному от login(1)
процесс на консоли или динамически распределяется сетевым демоном, например sshd
, или оконным менеджером (X).Когда вы набираете, скажем, vi
в оболочке, это fork
s, а затем exec
s /bin/vi
program, затем wait
s для него.Новый процесс наследует открытые файловые дескрипторы и может управлять ими через терминальное псевдоустройство через ioctl(2)
.
На самом деле веселье начинается с конвейеров , когдавы набираете что-то вроде ps -ef|grep bash
- это оставлено для читателя в качестве упражнения:)
Я тут упустил много интересных деталей, но надеюсь, что это может помочь в качестве краткого введения.