не использует сегментацию Linux, но только пейджинг?

Способ systemd заключается в создании шаблона службы, который запускает вашу альтернативную службу входа TTY...

[Unit]
Description=Qingy on %I
Documentation=info:qingy
BindTo=dev-%i.device
After=dev-%i.device systemd-user-sessions.service plymouth-quit-wait.service

[Service]
Environment=TERM=linux
ExecStart=/sbin/qingy %I --no-shutdown-screen
Restart=always
RestartSec=0
UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
KillMode=process
IgnoreSIGPIPE=no
KillSignal=SIGHUP

[Install]
WantedBy=getty.target

... и затем убедиться, что шаблон autovt@.service является псевдонимом для этого, а не для getty@.service, как это делается из коробки.

ln -s qingy@.service /etc/systemd/system/autovt@.service
systemctl daemon-reload

(Обратите внимание, что это не модификация предварительно упакованного /lib/systemd/system/autovt@.service, который поставляется в комплекте. Это использование обычной дихотомии systemd /etc//lib для замены ее на локальную, определяемую администратором.)

Остановите существующий autovt@ttyN.service и позвольте logind автоматически запустить его снова, чтобы увидеть, как это начнет действовать.

Further reading

24
15.09.2018, 21:16
5 ответов

Поскольку x86 имеет сегменты, их невозможно не использовать. Но базовые адреса сегмента кодаcs()и сегмента данныхds()установлены равными нулю, поэтому сегментация на самом деле не используется. Исключением являются локальные данные потока, один из обычно неиспользуемых сегментных регистров указывает на локальные данные потока. Но это в основном для того, чтобы избежать резервирования одного из регистров общего назначения для этой задачи.

Это не говорит о том, что Linux не использует сегментацию на x86, так как это было бы невозможно. Вы уже выделили одну часть,В Linux сегментация используется очень ограниченно . Вторая часть Linux использует сегментацию только тогда, когда этого требует архитектура 80x86

.

Вы уже приводили причины, пейджинг проще и переносимее.

9
27.01.2020, 19:41

Архитектура x86 -64 не использует сегментацию в длинном режиме (64 -битном режиме ).

Четыре сегментных регистра :CS, SS, DS и ES принудительно устанавливаются на 0, а ограничение на 2^64.

https://en.wikipedia.org/wiki/X86_memory_segmentation#Later_developments

ОС больше не может ограничивать доступные диапазоны «линейных адресов». Поэтому он не может использовать сегментацию для защиты памяти; он должен полностью полагаться на пейджинг.

Не беспокойтесь о деталях процессоров x86, которые применимы только при работе в устаревших 32-битных -режимах. Linux для 32-битных -режимов используется не так часто. Его можно даже считать «находящимся в состоянии доброкачественной запущенности в течение нескольких лет». См. 32 -Поддержка Bit x86 в Fedora [LWN.net, 2017].

(Бывает, что 32 -битный Linux тоже не использует сегментацию. Но вам не нужно доверять мне в этом, вы можете просто игнорировать :-).

24
27.01.2020, 19:41

Is each region in the diagram a segment?

Хотя система сегментации (в 32-битном -защищенном режиме на платформе x86 )предназначена для поддержки отдельных сегментов кода, данных и стека, на практике все сегменты устанавливаются в одну и ту же область памяти. То есть они начинаются с 0 и заканчиваются в конце памяти (*). Это делает логические адреса и линейные адреса равными.

Это называется "плоской" моделью памяти, и она несколько проще, чем модель, в которой у вас есть отдельные сегменты, а затем указатели внутри них. В частности, сегментированная модель требует более длинных указателей, так как селектор сегмента должен быть включен в дополнение к указателю смещения. (16 -селектор сегмента бит + 32-битное смещение, всего 48-битный указатель; по сравнению с 32 -битным плоским указателем.)

64 -битовый режим на самом деле даже не поддерживает сегментацию, кроме плоской модели памяти.

Если бы вы программировали в 16-битном -защищенном режиме на процессоре 286, вам потребовалось бы больше сегментов, поскольку адресное пространство составляет 24 бита, а указатели — только 16-битные.

(*Обратите внимание, что я не могу вспомнить, как 32-битный -Linux справляется с разделением пространства ядра и пользовательского пространства. Сегментация позволила бы это сделать, установив ограничения сегментов пользовательского пространства так, чтобы они не включали пространство ядра. Пейджинг допускает это, поскольку он обеспечивает уровень защиты каждой страницы -.)

Then why does it say that Linux doesn't use segmentation but only paging?

В x86 все еще есть сегменты, и их нельзя отключить. Просто их используют как можно меньше.В 32-битном -защищенном режиме сегменты должны быть настроены для плоской модели, и даже в 64-битном --битном режиме они все еще существуют.

12
27.01.2020, 19:41

Is each region in the diagram a segment?

Это 2 почти -совершенно -различных употребления слова «сегмент»

  • Сегментация/сегментные регистры x86:Современные ОС x86 используют плоскую модель памяти, в которой все сегменты имеют одинаковый base=0 и limit=max в 32-битном -битном режиме, так же, как аппаратно обеспечивает 64-битный -] битовый режим , что делает сегментацию рудиментарной. (За исключением FS или GS, используется для локального хранилища потока -даже в 64-битном -режиме.)
  • Линкер/программа -загрузчик разделов/сегментов.(В чем разница раздела и сегмента в формате файла ELF)

Использование имеет общее происхождение :, если вы использовали модель сегментированной памяти (, особенно без выгружаемой виртуальной памяти ), у вас могли бы быть данные и адреса BSS относительно DS база сегмента, стек относительно базы SS и код относительно базового адреса CS.

Таким образом, несколько разных программ можно было загружать по разным линейным адресам или даже перемещать после запуска без изменения 16- или 32-битного -смещения относительно основания сегмента.

Но тогда вам нужно знать, к какому сегменту относится указатель, поэтому у вас есть «дальние указатели» и так далее. (Фактические 16 -битные программы x86 часто не нуждались в доступе к своему коду как к данным, поэтому могли где-то использовать сегмент кода 64 КБ и, возможно, еще один блок 64 КБ с DS = SS, при этом стек растет вниз от больших смещений. и данные внизу. Или крошечная модель кода со всеми основаниями сегментов, равными ).


Как сегментация x86 взаимодействует с пейджингом

Отображение адресов в 32/64 -битном режиме равно:

  1. сегмент :смещение (основание сегмента, подразумеваемое регистром, содержащим смещение, или переопределяемое префиксом инструкции)
  2. 32- или 64-битный -линейный виртуальный адрес = база+смещение. (В плоской модели памяти, используемой в Linux,указатели/смещения = линейные адреса тоже. За исключением случаев доступа к TLS относительно FS или GS.)
  3. таблицы страниц (, кэшированные TLB ), отображают линейно на 32 (унаследованный режим ), 36 (унаследованный PAE )или 52 -бит (x86 -64 )физический адрес.(https://stackoverflow.com/questions/46509152/why-in-64bit-the-virtual-address-are-4-bits-short-48bit-long-compared-with-the).

    Этот шаг является необязательным. :пейджинг должен быть включен во время загрузки путем установки бита в управляющем регистре. Без пейджинга линейные адреса являются физическими адресами.

Обратите внимание, что сегментация , а не позволяет использовать более 32 или 64 бит виртуального адресного пространства в одном процессе (или потоке ), поскольку плоская (линейная )адресное пространство, в которое все отображается, имеет только то же количество битов, что и сами смещения. (Это было не так для 16 -бит x86, где сегментация была действительно полезной для использования более 64 КБ памяти с в основном 16 -битными регистрами и смещениями.)


ЦП кэширует дескрипторы сегментов, загруженные из GDT (или LDT ), включая базу сегментов. Когда вы разыменовываете указатель, в зависимости от того, в каком регистре он находится, он по умолчанию принимает либо DS, либо SS в качестве сегмента. Значение регистра (указатель )обрабатывается как смещение от основания сегмента.

Так как основание сегмента обычно равно нулю, процессоры делают -особый случай. Или, с другой точки зрения, если у вас есть не -база с нулевым сегментом, нагрузки имеют дополнительную задержку, потому что «особый» (нормальный )случай обхода добавления базового адреса не применять.


Как Linux настраивает регистры сегментов x86:

База и предел CS/DS/ES/SS равны 0 / -1 в 32- и 64-битном -режиме. Это называется плоской моделью памяти, поскольку все указатели указывают на одно и то же адресное пространство.

(Архитекторы процессоров AMD нейтрализовали сегментацию, внедрив плоскую модель памяти для 64-разрядного -битного режима, поскольку основные операционные системы все равно не использовали ее, за исключением отсутствия -защиты exec, которая была предусмотрена в гораздо лучший способ - разбиение на страницы в формате таблицы PAE или x86 -64 страницы -.)

  • TLS (Локальное хранилище потоков ):FS и GS не фиксируются на base=0 в длинном режиме. (Они были новыми с 386 и не использовались неявно ни в каких инструкциях, даже вrep-строковых инструкциях, использующих ES ). x86 -64 Linux устанавливает базовый адрес FS для каждого потока равным адресу блока TLS.

    напр. mov eax, [fs: 16]загружает 32 -битное значение из 16 байтов в блок TLS для этого потока.

  • дескриптор сегмента CS выбирает, в каком режиме находится ЦП (16/32/64 -битовый защищенный режим / длинный режим ). Linux использует одну запись GDT для всех 64 -битных пользовательских -космических процессов и другую запись GDT для всех 32 -битных пользовательских -космических процессов. (Чтобы ЦП работал правильно, DS/ES также должны быть установлены на допустимые записи, как и SS ). Он также выбирает уровень привилегий (ядро ​​(кольцо 0 )по сравнению с пользователем (кольцо 3 )), поэтому даже при возврате к 64 -битному пространству пользователя -ядро ​​все еще имеет чтобы организовать изменение CS, используя iretили sysretвместо обычной команды перехода или возврата.

  • В x86 -64 точка входа syscallиспользует swapgsдля переключения GS из пространства пользователя -в GS ядра, которое используется для поиска стека ядра для этого потока. (Специализированный случай локального хранилища потока -). Инструкция syscallне изменяет указатель стека так, чтобы он указывал на стек ядра; он по-прежнему указывает на пользовательский стек, когда ядро ​​​​достигает точки входа 1 .

  • DS/ES/SS также должны быть установлены на действительные дескрипторы сегментов, чтобы ЦП мог работать в защищенном режиме/длинном режиме, даже если базовый/лимит из этих дескрипторов игнорируется в длинном режиме.

Таким образом, в основном сегментация x86 используется для TLS и для обязательных функций osdev x86, которые требует аппаратное обеспечение.


Сноска 1 :Забавная история :есть архивы списков рассылки сообщений между разработчиками ядра и архитекторами AMD за пару лет до выпуска чипа AMD64, в результате чего дизайн syscallбыл изменен, чтобы его можно было использовать.. Подробнее см. ссылки в этом ответе .

6
27.01.2020, 19:41

Linux x86/32 не использует сегментацию в том смысле, что она инициализирует все сегменты одним и тем же линейным адресом и пределом. Архитектура x86 требует, чтобы программа имела сегменты :код может выполняться только из сегмента кода, стек может располагаться только в сегменте стека, с данными можно манипулировать только в одном из сегментов данных. Linux обходит этот механизм, устанавливая все сегменты одинаково (с исключениями, которые в любом случае не упоминаются в вашей книге ), так что один и тот же логический адрес действителен в любом сегменте. Фактически это эквивалентно полному отсутствию сегментов.

4
27.01.2020, 19:41

Теги

Похожие вопросы