64-битное ядро, но все 32-битные исполняемые ELF-процессы, как это?

9

Выход из uname:

root@debian:~ # uname -a
Linux 5asnb 2.6.32-5-amd64 #1 SMP Mon Jun 13 05:49:32 UTC 2011 x86_64 GNU/Linux

Однако /sbin/initисполняемый файл отображается как 32-разрядный:

root@debian:~ # file /sbin/init
/sbin/init: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped

Другие аспекты системы, кажется, также противоречат вещам:

root@debian:~ # echo $HOSTTYPE
i486

root@debian:~ # getconf LONG_BIT
32
kiiwii
источник

Ответы:

13

64-битное ядро ​​может быть установлено на Debian 32bit. Вы можете увидеть, что ядро ​​amd64 доступно для 32-битного Debian на странице пакета . Это можно использовать в качестве альтернативы использованию ядра с поддержкой PAE для поддержки более 4 ГБ общего ОЗУ. Обратите внимание, что 32-разрядные двоичные файлы по-прежнему не могут получить доступ к более чем 3 ГБ ОЗУ на процесс.

jordanm
источник
Спасибо! ваши ответы так же ясны, как хрустальный шар ~: D Никогда не замечал, что Debian раньше рассматривал пакет ядра таким образом.
kiiwii
1
Это не так: 32-разрядные программы могут использовать весь 4Gio своего виртуального адресного пространства при работе на 64-разрядном ядре (если они не работают с индивидуальностью ADDR_LIMIT_3GB).
YSDX
@ysdx То есть ограничение в 2 ГБ - это особенность Windows, а адреса выше 0x80000000 будут разрешены в 32-разрядном пользовательском пространстве?
Пол Стелян
1
@PaulStelian, В 32-битной Windows вы по умолчанию ограничены минимальным 2 ГБ виртуальной памяти для ретро-совместимости (я думаю, что некоторые программы использовали для резервирования указателей на максимальные 2 ГБ виртуальной памяти для специальных целей). Вы можете установить флаг LARGEADDRESSAWARE в своем исполняемом файле ( docs.microsoft.com/fr-fr/cpp/build/reference/… ), чтобы отказаться от получения доступа ко всем 4 ГБ виртуальной памяти.
ysdx
15

Все процессоры, которые поддерживают набор инструкций x64 (также известный как x86_64 или amd64), также поддерживают набор инструкций x86 (также известный как i386 или i686, которые являются строго определенными версиями x86). То же самое касается ARM A64 (новый 64-битный набор команд, появившийся в ARMv8) и A32 (название для «классического» 32-битного набора инструкций), для SPARC64 и SPARC , и я верю для MIPS64 и MIPS . Таким образом, во всех этих семействах архитектуры, если процессор может выполнять 64-битный код, он также может запускать 32-битный код.

Ядро Linux поддерживает запуск 32-битного пользовательского кода с 64-битным ядром (я думаю, что во всех упомянутых выше семействах архитектур). Ядро должно быть однородным (все 64-разрядные или все 32-разрядные), и каждый процесс должен быть однородным, но в 64-разрядном ядре может быть смесь 32-разрядных и 64-разрядных процессов. Обратное невозможно: с 32-битным ядром вы не можете запускать 64-битные процессы.

Это выбор дизайна в Linux, мотивированный желанием запустить существующие 32-разрядные двоичные файлы в 64-разрядных установках. Другие варианты Unix сделали другой выбор: Solaris может запускать 64-разрядные программы на 32-разрядном ядре, а также наоборот, в то время как OpenBSD не может запускать 32-разрядные программы на 64-разрядном ядре.

Вы можете получить информацию о процессоре в /proc/cpuinfo. Если ваш процессор x86 имеет lmфлаг, это 64-битный процессор.

По умолчанию uname -mили archпоказывает архитектуру, для которой было скомпилировано ядро. Linux может установить «индивидуальность» процесса (с помощью personality) системного вызова. Вы можете запустить подпроцесс в другой личности с помощью setarchкоманды; setarch i686 someprogramили linux32 someprogramзапускает указанную программу в среде, в которой происходит uname -mвозврат i686, setarch amd64 someprogramили linux64 someprogramзапускает указанную программу в среде, в которой uname -mвозвращается amd64.

file /sbin/initговорит вам, для какой архитектуры initскомпилирована программа. Хотя в установке можно смешивать 32-разрядные и 64-разрядные исполняемые файлы, обычно все основные программы ОС имеют одинаковую архитектуру, поскольку ими намного легче управлять.

$HOSTYPEявляется переменной bash и сообщает вам, для какой архитектуры bashбыла скомпилирована программа.

getconf LONG_BITпозволяет узнать, настроен ли компилятор C по умолчанию для компиляции 32-битных или 64-битных программ. Более точный тест состоит в том, чтобы скомпилировать и запустить программу, которая печатает sizeof(void*)или sizeof(size_t)- вызов getconfможет дать только информацию о том, что getconfсчитает компилятором по умолчанию.

Жиль "ТАК - перестань быть злым"
источник
1
Действительно, 32-битный Solaris переключается в 64-битный режим для переключения на 64-битный процесс, а затем обратно? Это должно иметь огромные накладные расходы и просто не имеет смысла, потому что тогда ядро ​​фактически 64-битное.
Руслан
1
@Ruslan Почему у него огромные накладные расходы? Переключение режимов при переключении контекста не требует больших затрат (во всяком случае, я недостаточно хорошо знаю x86 на низком уровне). Ядро остается 32-битным: 32-битные виртуальные адреса для отображений ядра, использование 32-битного набора команд.
Жиль "ТАК - перестать быть злым"
1
Ядро должно поддерживать некоторые 64-битные структуры данных для поддержки 64-битных приложений, по крайней мере 64-битных таблиц страниц. Это делает его не совсем 32-битным ядром. Я не пытался углубиться в арку amd64, но думаю, что отключение 64-битной поддержки будет иметь значительные издержки в отличие от использования специально разработанного режима совместимости.
Руслан
1
@Ruslan Только 64-битные таблицы страниц с осознанным вниманием и действительно необходимы, и это небольшая стоимость. Всего остального можно избежать с помощью правильного дизайна ядра. Я никогда не копался в ядре Solaris, полагаю, что они сделали его достаточно гибким (у них был опыт работы с SPARC64).
Жиль "ТАК - перестать быть злым"