Почему $$ возвращает тот же идентификатор, что и родительский процесс?

160

У меня проблема с Башом, и я не знаю почему.
Под оболочкой я ввожу:

echo $$    ## print 2433
(echo $$)  ## also print 2433
(./getpid) ## print 2602

«getpid» - это программа на C для получения текущего pid, например:

   int main() {
    printf("%d", (int)getpid());
    return 0;
   }

Что меня смущает, так это то, что:

  1. Я думаю, «(команда)» является подпроцессом (я прав?), И я думаю, что его pid должен отличаться от родительского pid, но они одинаковы, почему ...
  2. когда я использую свою программу, чтобы показать pid между круглыми скобками, pid, который он показывает, отличается, верно?
  3. '$$' - это что-то вроде макроса?

Вы можете помочь мне?

ruanhao
источник
8
Обратите внимание, что getpidбудет показан другой идентификатор процесса, даже если он не был запущен в подоболочке.
chepner
1
@Marian echo $$ $BASHPID ; ( echo $$ $BASHPID )демонстрирует это. Круглые скобки создают подоболочку. Операторы могут изменять значения переменных, и родительская оболочка не должна видеть эти изменения. Это реализовано как fork()операция.
Бен

Ответы:

223

$$определяется для возврата идентификатора процесса родителя в подоболочке; со страницы руководства в разделе «Специальные параметры»:

$ Расширяется до идентификатора процесса оболочки. В подоболочке () она расширяется до идентификатора процесса текущей оболочки, а не подоболочки.

В bash4 вы можете получить идентификатор процесса ребенка BASHPID.

~ $ echo $$
17601
~ $ ( echo $$; echo $BASHPID )
17601
17634
chepner
источник
17
«parent» немного вводит в заблуждение (по крайней мере, для меня), на самом деле это оболочка «верхнего уровня». Например: echo $$; (echo $$; (echo $$))трижды повторяет один и тот же
пид
1
Правильно; Я должен был сказать, что значение унаследовано от родительской оболочки (которая унаследовала свое значение от своего родителя и т. Д.). Оболочка верхнего уровня устанавливает его изначально, а не наследует от своего (не оболочечного) родительского процесса.
chepner
$ Expands to the process ID of the shellэто правда? echo $просто повторяет буквальный $.
Александр Миллс
@AlexanderMills Хорошо, да; $один не расширение параметров. Страница man ссылается на имя специального параметра, который является $; это не утверждение, что $одно расширяется.
Чепнер
Хорошо, я, честно говоря, понятия не имею, что это значит, но echo $BASHPIDработает в bash 4 и 5 (но не в версии 3.2.57 для MacOS)
Александр Миллс
81

Вы можете использовать один из следующих.

  • $! это PID последнего фонового процесса.
  • kill -0 $PID проверяет, все ли еще работает.
  • $$ это PID текущей оболочки.
craken
источник
2
Разве второй пули не должно быть, kill -0 $!если мы говорим о фоновых процессах? PIDпо умолчанию ничего не установлено.
Исаак Фриман,
26
  1. Круглые скобки вызывают подоболочку в Bash . Так как это только подоболочка, он может иметь одинаковый PID - зависит от реализации.
  2. Вызываемая вами программа на C - это отдельный процесс, который имеет свой уникальный PID - не имеет значения, находится ли он в подоболочке или нет.
  3. $$является псевдонимом в Bash для текущего PID скрипта . См. Различия между $$и $BASHPIDздесь , и прямо над этой дополнительной переменной, $BASH_SUBSHELLкоторая содержит уровень вложенности.
Нильс Кеурентьес
источник
4

Попробуйте, getppid()если вы хотите, чтобы ваша C-программа печатала PID вашей оболочки.

Alex
источник
2

Если бы вы спрашивали, как получить PID известной команды, она бы выглядела примерно так:

Если вы ввели команду ниже # Выдалась команда ***

дд если = / dev / diskx of = / dev / disky


Тогда вы бы использовали:

PIDs=$(ps | grep dd | grep if | cut -b 1-5)

Здесь происходит передача всех необходимых уникальных символов в поле, и это поле можно отобразить с помощью

echo $ PIDs

Дон-Пьер Халфуэй
источник
2

этот универсальный способ получить правильный пид

pid=$(cut -d' ' -f4 < /proc/self/stat)

такая же хорошая работа для саба

SUB(){
    pid=$(cut -d' ' -f4 < /proc/self/stat)
    echo "$$ != $pid"
}

echo "pid = $$"

(SUB)

проверить вывод

pid = 8099
8099 != 8100
АРТЕМ ЛАПКИН
источник
Хорошая идея, но разве это не принесет вам pid форка, который запустила оболочка, чтобы захватить вывод cut? Если я запускаю его дважды, один раз с echo $ (...) и один раз без, тогда я получу разные ответы.
Мартин Дори