Чому номери системних викликів Linux у x86 та x86_64 відрізняються?


35

Я знаю, що інтерфейс системного виклику реалізований на низькому рівні і, отже, залежить від архітектури / платформи, а не "загального" коду.

Однак я не можу чітко бачити причину, чому системні дзвінки в 32-бітових ядрах x86 Linux мають номери, які не зберігаються однаковими в подібній архітектурі Linux 64-бітний x86_64? Яка мотивація / причина цього рішення?

Першим моїм припущенням стало те, що основна причина полягала в тому, щоб 32-бітні програми працювали в системі x86_64, щоб через розумне зміщення номера системного виклику система знала, що простір користувача 32-бітний або 64-бітний відповідно. Однак це не так. Принаймні, мені здається, що read (), який є системним викликом номер 0 в x86_64, не може бути узгоджений з цією думкою.

Ще одна здогадка полягає в тому, що зміна номерів системних викликів може мати захист / посилення, що я не зміг сам підтвердити.

Не знаючи труднощів із застосуванням кодових частин, залежних від архітектури, мені все ще цікаво, як змінювати номери системних викликів , коли немає необхідності (оскільки навіть 16-бітний реєстр міг би зберігати значно більше, ніж наразі ~ 346 чисел, щоб представляти всі дзвінки), допомогло б досягти будь-чого, крім порушення сумісності (хоча використання системних дзвінків через бібліотеку, libc, пом'якшує це).


3
Я думаю, ви задаєте неправильне запитання. Правильне питання, чому тримати їх однаково: Відповісти сумісність. Тож якщо x86 та x86_64 несумісні, то немає сил, щоб вони не змінювались. Тепер усі сили за останні 20 років, які хотіли змін, домінуватимуть (ми отримуємо шанс змінити їх). [Зауважте, це лише думка, а не заснована на внутрішньому розумі дизайнерів нової системи.]
ctrl-alt-delor

Відповіді:


34

Щодо міркувань конкретної нумерації, яка не відповідає жодній іншій архітектурі [окрім "x32", яка насправді є лише частиною архітектури x86_64]: У перші дні підтримки x86_64 в ядрі Linux, перш ніж були такі серйозні обмеження щодо сумісності ззаду, усі системні виклики були перенумеровані, щоб оптимізувати його на рівні використання кешліна .

Я не знаю достатньо про розробку ядра, щоб знати конкретну основу для цих виборів, але, мабуть, існує певна логіка, що стоїть за вибором перенумерувати все з цими конкретними номерами, а не просто копіювати список із існуючої архітектури та видаляти невикористані. Схоже, порядок може базуватися на тому, як часто вони називаються - наприклад, читати / писати / відкрити / закрити - це спереду. Вихід та форк можуть здатися "основоположними", але кожен з них викликається лише один раз у процесі.

Також може відбуватися щось із збереженням системних викликів, які зазвичай використовуються разом у межах однієї лінії кешу (ці значення є просто цілими числами, але в ядрі є таблиця з функціональними вказівниками для кожного, тому кожна група з 8 системних викликів займає 64-байтовий рядок кешу для цієї таблиці)


1
fork may seem "fundamental", but [...] called only once per process.Ага, що? Я розумію, ви можете розраховувати зателефонувати до виходу одного разу, але ви можете розігнати всередині батьків і дитини fork()дзвінка
кішка

5
@cat, якщо ви бачите fork, що це враховується як дочірній процес (тобто розглядає його як виклик створення процесу), а не батьківський процес, тоді твердження Random832 є правильним.
ікар

4
@cat Гаразд, ви можете зателефонувати fork () два-три рази, можливо, ще кілька. Але ви можете зателефонувати прочитати () мільйони чи навіть мільярди разів.
Майкл Гемптон

1
Так, це я мав на увазі. Кількість викликів вилки та кількість процесів протягом життя системи буде ідентичною, ігноруючи деталі, такі як init, клон [які можуть створювати процеси або потоки] тощо.
Random832

15

Дивіться цю відповідь на питання "Чому номери системних викликів відрізняються в Linux Linux amd64?" на стеку переповнення.

Підсумовуючи це: заради сумісності список системних викликів стабільний і може лише зростати. Коли з'явилася архітектура x86 64, ABI (передача аргументу, повернене значення) стала іншою, тому розробники ядра скористалися можливістю внести зміни, які довго чекали.


Класна моя здогадка була правильною.
ctrl-alt-delor

2
Інша відповідь, на яку ви посилаєтесь, є спекулятивною: там написано, що "хлопці з Linux, швидше за все, вирішили ..." (наголос додано). Я думаю, що це допоможе, якби ваша відповідь тут дала певну ознаку того, що вона, мабуть, заснована на спекуляціях, а не доказах. Між іншим, останній коментар, розміщений під пов’язаною відповіддю, свідчить про те, що справжня причина - це не загальне очищення грубих матеріалів (як ця відповідь спекулює), а конкретно щодо "використання кешліна", як пояснено в іншій відповіді тут .
DW

-3

Одним словом, тому, що хтось вважав, що " N+1безсумнівно несумісні способи зробити це краще, ніж Nспособи". Для історичних архівів номери системних викликів зазвичай вибиралися так, щоб вони відповідали деякому спадковому власнику Unix. Але для x86_64 розробники ядра могли вільно обирати будь-яку нумерацію, яка їм сподобалась. Замість того, щоб зробити простий вибір і повторно використовувати існуючу нумерацію, вони зробили вибір, щоб винайти новий стандарт. Тоді вони зробили це знову для aarch64 та купою інших. Це часто повторювана закономірність в розробці ядра Linux.


3
Зміна не була безоплатною. Є вагомі технічні причини. Якби не вимоги зворотної сумісності, подібні зміни були б застосовані і до існуючих архітектур.
Йорг W Міттаг

Різниця в нумерації є 100% безоплатною. Немає жодної технічної переваги в будь-якій конкретній нумерації.
Р ..

2
Як пояснюється в цій іншій відповіді , систематичні виклики згруповані таким чином, що системні виклики, які зазвичай використовуються разом, поділяють однакову кешлін в таблиці syscall. І цифри системних дзвінків вибираються такими, що вони є простими індексами в цій таблиці. Теоретично ми могли б використовувати шар непрямості, щоб зв'язати позицію syscall у таблиці syscall від номера syscall, але це, можливо, з'їсть частину прибутків від продуктивності, які ми отримуємо від розміщення гарячих syscall в тій же кеш-лінії.
Йорг W Міттаг

@ JörgWMittag: І це, очевидно, передчасна оптимізація, а не помірна поліпшення. Подивіться, скільки циклів займає системні виклики та скільки рядків кешу, які вони виводять. Збереження в кращому випадку одного кеш-рядка від впорядкування таблиці не змінить значення.
Р ..

2
@R .. "Я обрав нумерацію у функції інформації про профілювання ядра tpcc за допомогою популярних СУБД та страйкового виводу деяких мережевих та настільних додатків." Звичайно, звучить так, ніби були вимірювання. Однак автор не надав жодних цифр або адекватно пояснив методику.
користувач45891
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.