Процесс отличается для разных операционных систем и действительно отличается в зависимости от того, как создается новый процесс. Поскольку я больше знаком с тем, как современные Microsoft OS справляются с этим, я начну там и сделаю ссылку на nix в конце.
Когда ОС [Microsoft] создает процесс, он выделяет блок среды процесса для хранения данных, специфичных для этого процесса. Сюда входят, помимо прочего, аргументы командной строки, с которыми была вызвана программа. Этот блок среды процесса выделяется из адресного пространства целевого процесса, и указатель на него предоставляется в точку входа процесса. Блок среды процесса для дочернего процесса обычно инициализируется копированием блока среды родительского процесса в адресное пространство нового процесса - нет прямого обмена используемой памятью.
В случае программы на основе C точка входа не является функцией main()
, которую предоставляет программатор. Скорее, это процедура, предоставляемая библиотекой времени выполнения C, которая отвечает за инициализацию среды выполнения перед передачей управления программисту main()
.
Существует много вещей, чтобы инициализировать, но один из аспектов является создание в ARGC и ARGV значения. Чтобы это сделать, среда выполнения проверит блок среды процесса, чтобы найти имя и параметры программы, с которыми он был вызван. Затем он (обычно) выделяет значения для argv из кучи процесса (то есть, используя что-то вроде malloc()
) и присваивает argc количеству найденных параметров (плюс один, для имени программы).
Фактические значения для argc и argv помещаются в стек, как и любые другие параметры, переданные в C, поскольку вызов main()
по времени выполнения C является обычным вызовом функции.
Итак, когда код, который вы пишете внутри main()
, в дочернем процессе обращается к argv, он будет считывать значения из собственной кучи процесса. Источником этих значений является блок среды процесса (хранится ОС в локальном адресном пространстве), который был первоначально инициализирован путем копирования блока среды процесса из родительского процесса.
На платформах * nix все совсем по-другому. Основное различие для настоящего обсуждения заключается в том, что nix будет хранить аргументы командной строки для нового процесса непосредственно в стеке стека исходного потока процесса. (Здесь также хранятся переменные среды.) Так что на * nix, main
вызывается с параметром argv, указывающим на значения, хранящиеся в самом стеке.
Вы можете получить некоторые из этого в man-странице для execve, а в файле Linux Programming Interface от Michael Kerrisk есть хорошее описание в разделе 6.4, которое вы можете найти в онлайн-отрывке.
Можете ли вы добавить доказательства или ссылки на соответствующие источники? – xmojmr
Теперь как насчет указателей на аргументы (а именно указатель на argv)? Если сами аргументы бросаются в стек, указатель также помещается в стек или передается в регистр аргументов (я использую MIPS-архитектуру)? – audiFanatic
@audiFanatic by "arguments" Я имею в виду аргументы функции для вызывающего соглашения: 'argc',' argv' и 'envp'; аргументы функции всегда являются значениями; прежде чем вычисляются значения, которые являются указателями (хотя довольно часто используется «pop% esp» для первого и избавляется от пучка + 4s или + 8s). – o11c