#c #linux #shell
#c #linux #оболочка
Вопрос:
Я хочу запустить команду оболочки в моей программе на C. Но дело в том, что я не хочу заставлять свою программу ждать, пока команда не будет выполнена. Нет необходимости читать выходные данные команды оболочки (она все равно не возвращает никаких данных) Итак, в принципе, возможно ли это?
Комментарии:
1. Кстати, не имеет значения, хотите ли вы запустить команду оболочки или какой-либо другой исполняемый файл. Используете ли вы
system()
илиfork()/exec()
подход, все, что требуется, — это исполняемый файл. Может быть, вы хотите соответствующим образом отредактировать заголовок вашего вопроса?
Ответ №1:
Конечно, просто fork
и exec
: используйте fork
для создания нового процесса, а в дочернем процессе используйте exec
для запуска командной строки с вашей командой. execv
принимает аргументы, которые вы обычно передаете командной строке.
Ваш код может выглядеть следующим образом:
pid_t child_pid = fork();
if (child_pid == 0)
{ // in child
/* set up arguments */
// launch here
execv("/bin/sh", args);
// if you ever get here, there's been an error - handle it
}
else if (child_pid < 0)
{ // handle error
}
дочерний процесс отправит SIGCHLD
сигнал, когда он завершит работу. Этот код, приведенный из стандарта POSIX (SUSv4), справится с этим:
static void
handle_sigchld(int signum, siginfo_t *sinfo, void *unused)
{
int status;
/*
* Obtain status information for the child which
* caused the SIGCHLD signal and write its exit code
* to stdout.
*/
if (sinfo->si_code != CLD_EXITED)
{
static char msg[] = "wrong si_coden";
write(2, msg, sizeof msg - 1);
}
else if (waitpid(sinfo->si_pid, amp;status, 0) == -1)
{
static char msg[] = "waitpid() failedn";
write(2, msg, sizeof msg - 1);
}
else if (!WIFEXITED(status))
{
static char msg[] = "WIFEXITED was falsen";
write(2, msg, sizeof msg - 1);
}
else
{
int code = WEXITSTATUS(status);
char buf[2];
buf[0] = '0' code;
buf[1] = 'n';
write(1, buf, 2);
}
}
Комментарии:
1. exec не использует оболочку. предположим, что операционная система хочет выполнить
ls | grep -v hello
. Это будет работать с system, но не будет работать с exec.2. операционная система может передавать их в оболочку — система делает то же самое (но делает другое
fork
amp;exec
за кулисами).
Ответ №2:
fork()
и system()
это то, что вам нужно
Комментарии:
1. Возможно, вместе с exec() или его вариантами.
2.
system
заставил бы дочерний процесс ожидать команды оболочки —exec
заменил бы дочерний процесс оболочкой..3. @Ronald: нет. Дочерний процесс заменяется другим процессом. Из OP неясно, хочет ли он запустить другую программу или командную строку оболочки, но если это последнее, то только system () справится с задачей. exec не использует оболочку.
4. это произойдет, если вы передадите ей надлежащие аргументы (т. Е. запустите /bin/sh и передадите ему скрипт, который вы хотите запустить).
Ответ №3:
Попробуйте код, подобный этому:
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char ** argv)
{
if (!fork())
{
execv("ls", {"myDir"}); /* Your command with arguments instead of ls. */
}
}
Комментарии:
1. Это кажется мне слишком быстрым и грязным, поскольку это создало бы процесс-зомби с момента завершения работы команды до завершения работы main. Хорошо управляемая программа Unix хотела бы избежать этого. Смотрите другие ответы, которые используют
waitpid
.
Ответ №4:
Как насчет простого усиления команды с помощью system ("command amp;")
?