Bash: почему остановка дочернего процесса приводит к тому, что мой дочерний и текущий процессы отображают одну и ту же командную строку в ps

#linux #bash #child-process #ps #suspend

#linux #bash #дочерний процесс #ps #приостановить

Вопрос:

У меня есть этот фрагмент кода в скрипте. Вот сценарий, test.sh который иллюстрирует это:

 #!/bin/bash
$@ amp;
pid=$!

#kill -STOP $pid

echo "PID = $pid"
echo '$@  = '"$@"

ps -p $pid -o uname,pid,command
echo
ps -A -o uname,pid,stat,command | grep 'script.sh' | grep -v grep

#kill -CONT $pid
wait $pid

exit 0
  

kill команды закомментированы, это предназначено. Что происходит:

  • Я запускаю этот скрипт с другим сценарием в качестве аргумента: ./test.sh ./script.sh
  • test.sh запускает ./script.sh , записывает его PID и показывает информацию
  • Информация показывает дочерний PID и процесс, соответствующий ./script.sh
 

    root@test# ./test.sh ./script.sh
    PID = 53370
    $@  = ./script.sh
    USER        PID   COMMAND
    root      53370   /bin/bash ./script.sh                  <-- Child process
    
    USER      PID    STAT   COMMAND
    root      53369  S      /bin/bash ./test.sh ./script.sh  <-- Current process
    root      53370  S      /bin/bash ./script.sh            <-- Child process

  

Все нормально.

Теперь, если я раскомментирую kill команды, скрипт отобразит эту информацию:

 

    root@test# ./test.sh ./script.sh
    PID = 53422
    $@  = ./script.sh
    USER        PID   COMMAND
    root      53422   /bin/bash ./test.sh ./script.sh          <-- Child process
    
    USER      PID    STAT   COMMAND
    root      53421  S      /bin/bash ./test.sh ./script.sh    <-- Current process
    root      53422  T      /bin/bash ./test.sh ./script.sh    <-- Child process

  

Я не уверен, что понимаю, почему, когда я приостанавливаю свой дочерний процесс, я получаю точно такое же COMMAND значение для моего текущего процесса и моего дочернего процесса на ps выходе.

Почему это происходит? Я хотел бы понять механизм взаимодействия родительского и дочернего процессов в этой ситуации.

Комментарии:

1. Хорошо, добавление sleep 0.01 между созданием дочернего процесса и ps изменением выходных данных дало мне тот же результат, что и без приостановки процесса. Так что, я думаю, это не имеет ничего kill -STOP общего с тем, как создается процесс? И я просто слишком быстро приостанавливал дочерний процесс, чтобы увидеть его фактическую командную строку? Остается вопрос: почему я вижу командную строку родителя? Как это работает?

Ответ №1:

Потому что вы остановили дочерний процесс, пока он находился между fork() и execve() , прежде чем он смог выполнить script.sh сценарий.

Добавьте a sleep 1 перед kill -STOP , чтобы увидеть эффект.

A fork() создает дочерний процесс как копию родительского процесса (что означает, что он будет отображаться в ps выходных данных с тем же именем процесса, аргументами командной строки и почти всем остальным, кроме pid). Когда дочерний элемент вызывает execve() системный вызов, он заменяет все это.

После a fork() нет гарантии, какой из родительских или дочерних процессоров будет запущен первым (и фактически, они могут выполняться одновременно на разных процессорах, или любой из них может быть вытеснен на неопределенный срок) — и любые «философские» выводы, сделанные из порядка, в котором они выполняют разные операции wrtдруг друга совершенно бессмысленно 😉

Комментарии:

1. Ах, я не знал fork() , что такое поведение. Я провел sleep тест, и действительно ps , вывод показывает COMMAND значение после execve() системного вызова, и оно выглядит так, как оно должно выглядеть в конце. Спасибо за объяснение