Прежде чем обсуждать реализацию RunCommand
, давайте рассмотрим этот фрагмент кода:
string psOutput = RunCommand("ps -elf","");
string grepOutput = RunCommand("grep somequerytext", psOutput);
В приведенном выше фрагменте кода проблема заключается в том, что команды выполняются последовательно, а не параллельно / параллельно. (См. Программирование с потоками POSIX стр.9 ). Например, ps -elf
генерирует огромное количество данных, которые будут сохранены в psOutput
и затем переданы следующей команде. , Но в реальной реализации каждый процесс в конвейере запускается одновременно, и данные передаются с pipe
(с некоторой буферизацией, конечно), и нет необходимости ждать выполнения одного процесса, прежде чем начинать выполнение другого процесса.
Я предлагаю вам взглянуть на Расширенное программирование Ричарда Стивена в среде Unix глава 8 "Управление процессами" стр.223 для реализации system
. На основе кода Ричарда Стивена пример реализации RunCommand
будет выглядеть следующим образом (только скелетный код, без проверки ошибок):
int RunCommand(string command)
{
pit_t pid;
if ( ( pid = fork() ) < 0 ) return -1;
else if (pid == 0)
{
execl("/bin/sh", "sh", "-c", command.c_str(), (char*) 0);
}
else
{
/* The parent waits for the child */
wait(pid, ...);
}
}
и затем можно вызвать вышеуказанные функции как:
string s("ps -elf | grep somequerytext");
int status = RunCommand(s);
Оболочка заботится о синтаксическом анализе своего ввода и выполнении команд, устанавливая pipe
s между ними.
Если вы заинтересованы в понимании того, как реализована оболочка, см. «Пример Minishell» в Terrence Chan Системное программирование Unix с использованием C ++ глава 8 «Процессы Unix» ( ответ Джонатана Леффлера довольно много описывает реализацию оболочки!)