Функция C для системы («$ BASHPID») не работает

#c #linux #process

#c #linux #процесс

Вопрос:

У меня есть простая программа, написанная на C с использованием функции system () в Ubuntu 12.04 следующим образом:

 #include <stdio.h>
#include <unistd.h>

int main()
{
    printf("getpid() = %dn", getpid());
    printf("getppid() = %dn", getppid());
    printf("cmd process ID:n");

    system("echo $BASHPID");
    return 0;
}
  

и запустил ее с помощью gcc в терминале, что дало следующие результаты.

 $ gcc -o exmpl_bashpid exmpl_bashpid.c
$ ./exmpl_bashpid 
getpid() = 2892
getppid() = 2060
cmd process ID:

$
  

мой вопрос в том, что функция system («echo $ BASHPID») ничего не даст. когда я попытался использовать некоторые распространенные команды, такие как date, она выдает в терминале при запуске исполняемого файла. Только этот приведенный выше случай не дает надлежащих результатов. Какое может быть возможное объяснение? Я меньше всего знаком с процессами Linux и системными вызовами в программировании на C. Любая информация будет полезна для моего дальнейшего изучения. Спасибо.

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

1. Почему именно вы спрашиваете? Я предполагаю, что извлечение BASHPID из программы на C — неправильный способ достижения вашей цели.

2. @BasileStarynkevitch, мне нужно знать, действительно ли system () создаст другой процесс или нет, просто зная его идентификатор процесса.

3. Чтобы получить идентификатор процесса оболочки, используйте echo $$ который намного более переносим и не является bash специфичным.

Ответ №1:

system работает нормально /bin/sh и, предположительно, это не устанавливается $BASHPID . Попробуйте использовать:

 system("/bin/bash -c 'echo $BASHPID'")
  

Обратите внимание, что при этом всегда будет выводиться только PID дочернего процесса bash, вызываемого system , что не очень полезно. Похоже, вы пытаетесь получить PID родительского процесса bash, который не будет работать, поскольку BASHPID переменная родительского bash не экспортируется, поскольку ввод

 /bin/sh -c 'echo $BASHPID'
  

в командной строке будет продемонстрировано.

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

1. Если я изменю приведенный выше код, как вы предложили, он выдаст другой PID для каждого случая. Использую ли я здесь 3 процесса, включая shell в качестве одного из них? если да, то / bin / bash выполнит какой-либо другой процесс?

2. Ну, system () запускает новый процесс, поэтому они, скорее всего, получат другой pid

Ответ №2:

Чтобы получить переменную среды внутри программы на C, используйте getenv(3).

Итак, если вы считаете, что ваша программа запускается в среде, которая BASHPID задана (т. Е. export отредактирована в bash), попробуйте:

 int bashpid = 0;
char*bashpidstr = getenv("BASHPID");
if (bashpidstr amp;amp; isdigit(bashpidstr[0]))
  bashpid = atoi(bashpidstr);
  

Однако довольно часто оболочка является родительским процессом, к которому вы можете запросить с помощью getppid(2). Или это руководитель группы процессов, см. getpgid(2)

Если вы хотите получить вывод какой-либо команды, используйте popen(3), например

 int bashpid = 0;
FILE* cmd = popen("echo $BASHPID", "r");
if (cmd) { fscanf(cmd, "%d", amp;bashpid); pclose(cmd); }
else { perror("popen"); exit(EXIT_FAILURE); }
  

Но это, вероятно, не будет работать так, как вы хотите, поскольку popen или system может возникнуть форк /bin/sh a bash , который может быть a, и, возможно, вам следует echo $$

Кроме того, BASHPID специфичен для bash . Моя интерактивная оболочка (для входа) — zsh, поэтому она не будет установлена.

Обратите внимание, что обычно вам следует вызывать fflush(3) (например fflush(NULL); …) перед любой функцией разветвления, такой как popen или system , чтобы убедиться, что буферы stdio очищены.

дополнения

Если вы хотите знать, создает ли system (3) другой процесс, прочитайте его документацию:

Библиотечная функция system() использует fork(2) для создания дочернего процесса, который выполняет команду оболочки, указанную в command, используя execl(3) следующим образом:

       execl("/bin/sh", "sh". "-c", command, (char *) 0);
  

system() возвращается после завершения команды.

Однако существует особый случай, если вы передаете NULL аргумент в system :

Если команда равна нулю, то system() возвращает статус, указывающий, доступна ли оболочка в системе

Кроме того, изучите исходный код некоторой реализации, например, process / system.c из musl-libc

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

1. BASHPID не будет отправлен в программу C, поскольку он не экспортирован (насколько я могу судить)