Что на самом деле делает execvp?

Возможный дубликат:
Написание оболочки - как выполнять команды

Мне поручили написать оболочку на C. Пока я понимаю, что execvp попытается запустить программу в arg1 с arg2 в качестве параметров. Теперь кажется, что делать это

execvp ("ls", args); //assume args is {"ls", ">", "awd.txt"}

не эквивалентно вводу этого в консоли

ls > awd.txt

Я понимаю, что мне нужно использовать freopen для достижения тех же результатов, но мне любопытно, что делает execvp.


person TreeTree    schedule 27.01.2013    source источник


Ответы (3)


Семейство функций exec в конечном счете является системным вызовом. Системные вызовы поступают прямо в ядро ​​и обычно выполняют очень специфические функции, которые может выполнять только ядро.

С другой стороны, перенаправление — это функция оболочки.

Таким образом, когда кто-то вводит ls > awd.txt в оболочке, оболочка сначала выполняет fork(2), затем закрывает стандартный вывод в дочернем элементе, затем открывает awd.txt в файловом дескрипторе номер один, так что это новый стандартный вывод.

Тогда и только тогда оболочка выполнит системный вызов exec-family.

В вашем случае вы просто передали строки > и awd.txt в системный вызов exec, а оттуда в ls. Кстати, убедитесь, что вы завершаете массив execvp arg нулевым указателем.


Примечание. Как видите, операторы перенаправления никогда не видны исполняемой программе. До Unix направление вывода в файл должно было выполняться каждой программой на основе параметра. Еще одна мелочь: большинство программ никогда не узнают, что они были перенаправлены, но, по иронии судьбы, ls делает проверку, чтобы увидеть, является ли его вывод tty, и если это так, он выполняет форматирование вывода с несколькими столбцами.

person DigitalRoss    schedule 27.01.2013
comment
Абсолютно. Как программист оболочки, перенаправление и конвейерная обработка являются вашей работой. «ls» не знает, что делать с «›», кроме как попытаться открыть его для листинга, поэтому вам скажут, что он не может получить доступ к «›». Также не забудьте завершить свои аргументы указателем NULL, чтобы он знал, что нужно остановиться. - person Robert; 27.01.2013

Он выполняет ls с двумя аргументами: > и awd.txt. Это эквивалентно запуску:

'ls' '>' 'awd.txt'
person Ignacio Vazquez-Abrams    schedule 27.01.2013
comment
Итак, чтобы выполнить ls -a в execvp(), мы должны выполнить execvp (ls, args); //аргументы равны {ls, -a}? или, execvp (args[0], args)? Хорошее простое объяснение! - person ; 18.07.2016
comment
@SittingBull: Как отмечено в комментарии к вашему вопросу, вам понадобится char *args[] = { "ls", "-a", 0 };, где крайне важен завершающий нулевой указатель. - person Jonathan Leffler; 19.07.2016

Вы можете передать свою команду непосредственно в оболочку:

char * const args[] = { "sh", "-c", "ls > awd.txt", NULL};
execvp("/bin/sh", args);

Но это не кажется хорошей идеей.

person nameless    schedule 27.01.2013