Как я могу Shell иметь более одной работы в Linux - PullRequest
0 голосов
/ 16 ноября 2018

Я новичок в Linux, просто у меня есть несколько вопросов о работе и группе процессов.

В моем учебнике написано: «Оболочки Unix используют абстракцию задания для представления процессов, которые создаются в результате оценки одной командной строки. В любой момент времени существует не более одной приоритетной задачи и ноль или более фоновых заданий.

Допустим, у нас есть этот простой шелл-код (я пропускаю некоторый неважный код, т. Е. Настройку argv и т. Д.): enter image description here

enter image description here

Когда мы набираем первый комнад, например: ./exampleProgram &

Q1- Создана ли работа? если да, какой процесс содержит задание?

вызывается main () shellex.c, поэтому при выполнении строки 15: fork () создает новый дочерний процесс, скажем, родительский процесс - p1, а недавно созданный дочерний процесс - c1 и если это фоновое задание, то мы можем ввести в командной строке другую команду, ./anotherProgram & и ввести enter

Q2- Я почти уверен, что в настоящий момент это просто p1 и c1, а p1 выполняет вторую команду, когда она снова выполняет строку 15: fork (), у нас есть p1, c1 и вновь созданный c2, верно ли мое понимание?

Q3- Сколько там работы? это только одна работа, которая содержит p1, c1 и c2?

Q4 - если это только одно задание, поэтому, когда мы будем продолжать вводить новые команды, у нас будет только одно задание, содержащее один родительский процесс p1 и множество дочерних процессов c1, c2, c3, c4 ... так почему в моем учебнике говорится, что у Shell может быть более одной работы? и почему существует не более одной приоритетной работы и ноль или более фоновых заданий.

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Работа - это не вещь Linux, это не фоновый процесс, это что-то ваша конкретная оболочка определяет как "работу".

Обычно оболочка вводит понятие "работа" для выполнения управления работой . Обычно это включает в себя способ определения работы и выполнения действий над ней, например

  • вывести на передний план
  • положить в фон
  • остановка
  • резюме
  • убить

Если оболочка не имеет возможности сделать что-либо из этого, бессмысленно говорить о рабочих местах.

0 голосов
/ 16 ноября 2018

На эту тему можно сказать немало, некоторые из которых могут уместиться в ответе, а большая часть требует дальнейшего чтения.

Для Q1 , я бы сказал концептуально да, но задания не являются автоматическими, а отслеживание и контроль заданий не являются волшебными. Я не вижу никакой логики в фрагментах кода, которые вы показываете, например. устанавливает и поддерживает таблицу заданий. Я понимаю, что это всего лишь пример, поэтому, возможно, логика управления работой в другом месте. Управление заданиями является функцией общих существующих оболочек Unix, но если человек пишет новую оболочку Unix с нуля, необходимо добавить функции управления заданиями в виде кода / логики.

Для Q2 , то, как вы это выразили, совсем не так, как я бы сказал. После первого вызова fork(), да, есть p1 и c1, но следует признать, что сначала p1 и c1 являются различными экземплярами одной и той же программы (shellex); * только после вызова execve() работает exampleProgram. fork() создает дочерний экземпляр shellex, а execve() вызывает замену дочернего экземпляра shellex (в оперативной памяти) на exampleProgram (при условии, что это значение argv[0]).

Нет никакого реального смысла в том, чтобы родитель "казнил" ребенка, ни процесс, который заменяет ребенка после execve(), кроме как просто заставить его работать. Родитель запускает дочерний процесс и может ждать завершения дочернего выполнения, но на самом деле родительский процесс и вся его иерархия дочерних процессов выполняют каждый самостоятельно, будучи выполненными ядро.

Но да, если сказано, что запускаемая программа должна запускаться в фоновом режиме, то shellex примет дальнейший ввод, и при следующем вызове fork() будет родитель shellex с двумя дочерними элементами. процессы. И снова, сначала дочерний c2 будет экземпляром shellex, быстро замененным на execve() любой программой, которая была названа.

(Относительно работы в фоновом режиме, будет ли & иметь такой эффект, зависит от логики внутри функции с именем parseline() в примере кода. Оболочки, с которыми я знаком, используют &, чтобы сказать «запустите это» на заднем плане ", но в этом нет ничего особенного или волшебного. Недавно написанная оболочка Unix может сделать это каким-то другим способом, с завершающим +, или ведущим BG:, или с чем угодно, что решит автор оболочки. .

Для Q3 и Q4 первое, что нужно распознать, это то, что родитель, которого вы вызываете p1 , является программой оболочки, которую вы показали , Так что, нет, p1 не будет частью работы.

В Unix задание - это набор процессов, которые выполняются как часть одного конвейера. Таким образом, работа может состоять из одного процесса или нескольких. Такие процессы остаются подключенными к терминалу, из которого они выполняются, но могут находиться на переднем плане (работающем и интерактивном), приостановленном или на заднем плане (работающем, не интерактивном).

one process, foreground    : ls -lR
one process, background    : ls -lR &
one process, background    : ls -lR, then CTRL-Z, then bg
many processes, foreground : ls -lR | grep perl | sed 's/^.*\.//'
many processes, background : ls -lR | grep perl | sed 's/^.*\.//' &

Чтобы эмпирически увидеть задания и процессы, запустите конвейер в фоновом режиме (5-й из 5 приведенных выше примеров) и во время его работы используйте ps, чтобы показать вам идентификаторы процессов и идентификаторы группы процессов. например, на моей версии bash для моего Mac это:

$ ls -lR | grep perl | sed 's/^.*\.//' &
[1] 2454                     <-- job 1, PID of the sed is 2454

$ ps -o command,pid,pgid
COMMAND         PID  PGID
vim            2450  2450    <-- running in a different tab
ls -lR         2452  2452    }
grep perl      2453  2452    }-- 3 PIDs, 1 PGID
sed s/^.*\.//  2454  2452    }

В отличие от этого прикрепления к оболочке и терминалу, демон отсоединяется от обоих. При запуске демона родитель использует fork() для запуска дочернего процесса, но затем завершает работу, оставляя только дочерний процесс, и теперь с родителем PID 1. Ребенок закрывается stdin, stdout и stderr, поскольку это бессмысленно, так как демон работает "без головы".

Но в оболочке родительский объект (который, опять же, является оболочкой) продолжает работать либо wait() ing (дочерняя программа переднего плана), либо не wait() ing (фоновая дочерняя программа), а дочерний процесс обычно сохраняет использование stdin, stdout и stderr (хотя они могут быть перенаправлены в файлы и т. д.)

И оболочка может вызывать вложенные оболочки, и, конечно, любая запускаемая программа может fork() иметь свои собственные дочерние процессы и так далее. Так что иерархия процессов может стать довольно глубокой. В противном случае без специальных действий дочерний процесс будет находиться в той же группе процессов, что и его родитель.

Вот несколько статей для дальнейшего чтения:

В чем разница между заданием и процессом в Unix?

https://unix.stackexchange.com/questions/4214/what-is-the-difference-between-a-job-and-a-process

https://unix.stackexchange.com/questions/363126/why-is-process-not-part-of-expected-process-group

Справочное руководство Bash; Job Control

Справочное руководство Bash; Основы управления заданиями

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...