Подтвердить что ты не робот

Что происходит при запуске программы?

Я хотел бы собирать здесь, что происходит, когда вы запускаете исполняемый файл в Windows, Linux и OSX. В частности, я хотел бы точно понять порядок операций: я предполагаю, что исполняемый формат файла (PE, ELF или Mach-O) загружается ядром (но я игнорирую различные разделы ELF (Исполняемый и связанный формат) и их значение), а затем у вас есть динамический компоновщик, который разрешает ссылки, затем выполняется __init часть исполняемого файла, затем основной, затем __fini, а затем программа завершена, но я уверен, что она очень грубая и, вероятно, неправильная.

Изменить: вопрос теперь - CW. Я заполняюсь для Linux. Если кто-то захочет сделать то же самое для Win и OSX, это будет здорово.

4b9b3361

Ответ 1

Это просто на очень высоком и абстрактном уровне, конечно!

Executable - No Shared Libary: 

Client request to run application
  ->Shell informs kernel to run binary
  ->Kernel allocates memory from the pool to fit the binary image into
  ->Kernel loads binary into memory
  ->Kernel jumps to specific memory address
  ->Kernel starts processing the machine code located at this location
  ->If machine code has stop
  ->Kernel releases memory back to pool

Executable - Shared Library

Client request to run application
  ->Shell informs kernel to run binary
  ->Kernel allocates memory from the pool to fit the binary image into
  ->Kernel loads binary into memory
  ->Kernel jumps to specific memory address
  ->Kernel starts processing the machine code located at this location
  ->Kernel pushes current location into an execution stack
  ->Kernel jumps out of current memory to a shared memory location
  ->Kernel executes code from this shared memory location
  ->Kernel pops back the last memory location and jumps to that address
  ->If machine code has stop
  ->Kernel releases memory back to pool

JavaScript/.NET/Perl/Python/PHP/Ruby (Interpretted Languages)

Client request to run application
  ->Shell informs kernel to run binary
  ->Kernel has a hook that recognises binary images needs a JIT
  ->Kernel calls JIT
  ->JIT loads the code and jumps to a specific address
  ->JIT reads the code and compiles the instruction into the 
    machine code that the interpretter is running on
  ->Interpretture passes machine code to the kernel
  ->kernel executes the required instruction
  ->JIT then increments the program counter
  ->If code has a stop
  ->Jit releases application from its memory pool

Как говорит routeNpingme, регистры устанавливаются внутри CPU, и происходит волшебство!

Обновление: Да, я не могу сказать сегодня правильно!

Ответ 2

Хорошо, Отвечая на мой собственный вопрос. Это будет сделано постепенно, и только для Linux (и, возможно, Mach-O). Не стесняйтесь добавлять больше вещей к своим личным ответам, чтобы они были подняты (и вы можете получить значки, так как теперь CW).

Я начну на полпути, и оставлю все, как узнаю. Этот документ был составлен с помощью x86_64, gcc (GCC) 4.1.2.

Открытие файла, инициализация

В этом разделе мы описываем, что происходит, когда программа вызывается с точки зрения ядра, пока программа не будет готова к выполнению.

  • Открывается ELF.
  • Ядро ищет раздел .text и загружает его в память. Помечает его как только для чтения.
  • ядро ​​загружает раздел .data​​li >
  • ядро ​​загружает раздел .bss и инициализирует все содержимое до нуля.
  • ядро ​​передает управление динамическому компоновщику (имя которого находится внутри файла ELF, в разделе .interp). Динамический компоновщик разрешает все вызовы разделяемой библиотеки.
  • элемент управления передается в приложение

Выполнение программы

  1. вызывается функция _start, поскольку заголовок ELF указывает ее как точку входа для исполняемого файла
  2. _start вызывает __libc_start_main в glibc (через PLT), передавая ему следующую информацию

    • адрес фактической основной функции
    • адрес argc
    • адрес argv
    • адрес подпрограммы _init
    • адрес подпрограммы _fini
    • указатель функции для регистрации atexit()
    • доступен самый высокий адрес стека
  3. _init получает вызов

    • вызывает call_gmon_start для инициализации профилирования gmon. не связанные с исполнением.
    • вызывает frame_dummy, который обертывает __register_frame_info (адрес секции eh_frame, адрес секции bss) (FIXME: что делает эта функция?), очевидно, инициализирует глобальные vars из раздела BSS)
    • вызывает __do_global_ctors_aux, роль которого заключается в вызове всех глобальных конструкторов, перечисленных в разделе .ctors.
  4. main получает вызов
  5. основные концы
  6. _fini вызывается, который поочередно вызывает __do_global_dtors_aux для запуска всех деструкторов, как указано в разделе .dtors.
  7. программа завершает работу.

Ответ 3

Как только изображение загружается в память, магия берет верх.

Ответ 4

В Windows сначала загружается изображение в память. Ядро анализирует, какие библиотеки (чтение "DLL" ) потребуется, и загружает их тоже.

Затем он редактирует изображение программы для вставки адресов памяти для каждой из требуемых им функций библиотеки. Эти адреса уже имеют пробел в двоичном формате .EXE, но они просто заполнены нулями.

Каждая процедура DLL DllMain() затем запускается один за другим из наиболее необходимой DLL до последней, например, следуя порядку зависимостей.

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

Ответ 5

Хорошо, в зависимости от вашего точного определения вам приходится учитывать компиляторы JIT для таких языков, как .Net и Java. Когда вы запускаете .NET "exe", который не является технически "исполняемым", компилятор JIT включает и компилирует его.