Чому саме програмне забезпечення ОС?


77

Я намагаюся визначити технічні деталі, чому програмне забезпечення, яке виробляється на мовах програмування для певних операційних систем, працює лише з ними.

Наскільки я розумію, що двійкові файли є специфічними для певних процесорів завдяки специфічній для процесора мовою мови, яку вони розуміють, і різним наборам інструкцій між різними процесорами. Але звідки береться специфіка операційної системи? Раніше я припускав, що це API, надані ОС, але тоді я побачив цю діаграму в книзі: Діаграма

Операційні системи - внутрішні та принципи дизайну 7-е видання - W. Stallings (Pearson, 2012)

Як бачимо, API не вказані як частина операційної системи.

Якщо, наприклад, я будую просту програму на C, використовуючи наступний код:

#include<stdio.h>

main()
{
    printf("Hello World");

}

Чи компілятор робить щось специфічне для ОС під час компіляції цього?


15
Ви друкуєте до вікна? чи консоль? чи до графічної пам'яті? Як ви розміщуєте там дані? Дивлячись на printf для Apple] [+ буде тихо інакше, ніж для Mac OS 7 і знову зовсім інше, ніж Mac OS X (просто дотримуючись однієї 'лінії' комп'ютерів).

3
Тому що, якщо ви написали цей код для Mac OS 7, він з'явиться у тексті у новому вікні. Якби ви це зробили в Apple] [+, це було б записування безпосередньо в якийсь сегмент пам'яті. У Mac OS X він записує його на консоль. Таким чином, це три різні способи написання обробки коду на основі апаратного забезпечення виконання, яким обробляється рівень бібліотеки.

2
@StevenBurnap yep - en.wikipedia.org/wiki/Aztec_C

10
Ваша функція FFT з радістю працюватиме під Windows або Linux (на тому ж процесорі), навіть не перекомпілюючись. Але тоді як ви збираєтеся відображати результат? Звичайно, використовуючи API операційної системи. ( printfвід msvcr90.dll не те саме, що printfвід libc.so.6)
immibis

9
Навіть якщо API не "є частиною операційної системи", вони все одно відрізняються, якщо ви переходите від однієї ОС до іншої. (Що, звичайно, ставить питання про те, що насправді означає словосполучення "не частина операційної системи", відповідно до діаграми.)
Теодорос Чатзіґянакікіс

Відповіді:


78

Ви згадуєте про те, як, якщо код є специфічним для процесора, чому він повинен бути специфічним і для ОС. Це насправді більше цікавого питання, на яке припускають багато відповідей тут.

Модель безпеки процесора

Перша програма, запущена в більшості архітектур процесора, працює всередині того, що називається внутрішнім кільцем або кільцем 0 . Те, як конкретна арка CPU реалізує кільця, змінюється, але видно, що майже кожен сучасний процесор має щонайменше 2 режими роботи, один привілейований і працює з «голим металом» коду, який може виконувати будь-яку юридичну операцію, яку може виконувати процесор, а інший - ненадійний і працює захищений код, який може виконувати лише визначений безпечний набір можливостей. Деякі процесори мають набагато більшу деталізацію, але для безпечного використання VM необхідні принаймні 1 або 2 додаткові кільця (часто позначені негативними номерами), однак це не виходить за межі цієї відповіді.

Куди входить ОС

Ранні одиночні операційні завдання

У дуже ранніх DOS та інших ранніх системах, що базуються на одній задачі, весь код запускався на внутрішньому кільці, кожна програма, яку ви коли-небудь запускали, мала повну владу над усім комп’ютером і могла робити буквально все, щоби недобре поводилося, включаючи стирання всіх ваших даних або навіть пошкодження обладнання. в декількох крайніх випадках, таких як встановлення недійсних режимів відображення на дуже старих екранах дисплея, що ще гірше, це може бути викликано просто баггі-кодом без жодної злісті.

Цей код був насправді агностичним ОС, доки у вас був завантажувач, здатний завантажувати програму в пам'ять (досить простий для ранніх бінарних форматів), і код не покладався на жодні драйвери, реалізуючи весь апаратний доступ, до якого він повинен працювати. будь-яка ОС, якщо вона запускається в кільці 0. Зверніть увагу, дуже просту ОС на зразок цієї, як правило, називають монітором, якщо вона просто використовується для запуску інших програм і не пропонує додаткових функціональних можливостей.

Сучасні багатозадачні ОС

Більш сучасні операційні системи, включаючи UNIX , версії Windows, що починаються з NT та інші інші тепер неясні ОС, вирішили покращити цю ситуацію, користувачі хотіли додаткових функцій, таких як багатозадачність, щоб вони могли запускати відразу кілька додатків і захист, тому помилка ( або шкідливий код) у додатку більше не може завдати необмеженої шкоди машині та даним.

Це було зроблено за допомогою згаданих вище кілець, ОС займе єдине місце, що працює в кільці 0, а програми працюватимуть у зовнішніх ненадійних кільцях, лише в змозі виконувати обмежений набір операцій, які дозволяла ОС.

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

Кожна ОС вирішила іншу реалізацію цих захистів, частково спираючись на архітектуру, для якої ОС була розроблена, а частково ґрунтувалася на дизайні та принципах відповідної ОС, UNIX, наприклад, зосередила увагу на машинах, які корисні для багатокористувацького використання та зосереджені доступні функції для цього в той час, як Windows було розроблено простіше, працювати на більш повільному обладнання з одним користувачем. Те, як програми для простору користувачів також розмовляють з ОС, на X86 зовсім інший, як це було б, наприклад, на ARM або MIPS, змушуючи багатоплатформенну ОС приймати рішення, грунтуючись на потребі роботи над обладнанням, на яке вона орієнтована.

Ці специфічні взаємодії з ОС зазвичай називають "системними дзвінками" і охоплюють те, як програма простору користувача взаємодіє з обладнанням через ОС повністю, вони принципово відрізняються залежно від функції ОС, і, отже, програма, яка виконує свою роботу через системні дзвінки, потребує бути специфічним для ОС.

Завантажувач програми

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

Цей заголовок раніше був досить простим, що написання завантажувача для іншого формату було майже тривіальним, однак із сучасними форматами, такими як elf, які підтримують розширені функції, такі як динамічне посилання та слабкі декларації, зараз ОС майже неможливо спробувати завантажувати бінарні файли які не були призначені для цього, це означає, що навіть якщо не було несумісності системного виклику, надзвичайно важко навіть розмістити програму в операційному режимі таким чином, щоб її можна було запустити.

Бібліотеки

Програми рідко використовують системні дзвінки безпосередньо, проте вони майже виключно набувають своєї функціональності, хоча бібліотеки, які завершують системні виклики у трохи дружнішому форматі для мови програмування, наприклад, у C є стандартна бібліотека C та glibc під Linux та аналогічні та win32 libs під У Windows NT і вище, більшість інших мов програмування також мають подібні бібліотеки, які належним чином переносять функціональність системи.

Ці бібліотеки можуть певною мірою навіть подолати проблеми міжплатформенності, як описано вище. Існує цілий ряд бібліотек, які розроблені навколо надання єдиної платформи для додатків при внутрішньому керуванні дзвінками до широкого кола операційних систем, таких як SDL , це означає, що хоча програми не можуть бути бінарними сумісними, програми, які використовують ці бібліотеки, можуть мати загальне джерело між платформами, що робить перенос таким же простим, як і перекомпіляція.

Винятки з вищевикладеного

Незважаючи на все, що я тут говорив, були спроби подолати обмеження неможливості запуску програм на більш ніж одній операційній системі. Деякі хороші приклади - проект Wine, який успішно наслідував завантажувач програм win32, бінарний формат і системні бібліотеки, що дозволяє програмам Windows запускатися на різних UNIX. Також існує рівень сумісності, який дозволяє декільком операційним системам BSD UNIX запускати програмне забезпечення Linux, і, звичайно, власний лайф Apple, який дозволяє запускати старе програмне забезпечення MacOS під MacOS X.

Однак ці проекти працюють через величезний рівень зусиль, спрямованих на розробку вручну. Залежно від того, наскільки обидві ОС відрізняються, складність варіюється від досить невеликої лайки до майже повної емуляції іншої ОС, яка часто є більш складною, ніж написання всієї операційної системи сама по собі, і це виняток, а не правило.


6
+1 "Чому специфічна ОС для програмного забезпечення?" Тому що історія.
Пол Дрейпер

2
чи походить модель безпеки процесора x86? чому і коли була винайдена модель?
n611x007

8
@naxa Ні, він давно передує x86, він був вперше частково реалізований для Multics в 1969 році, і це перша ОС з корисними функціями обміну часом для багатьох користувачів, що вимагають використання цієї моделі на комп'ютері GE-645 , однак ця реалізація була неповною і покладалася на Програмне забезпечення, перша повна і безпечна реалізація апаратних засобів була його спадкоємцем Honeywell 6180 . Це було повністю апаратно і дозволило Multics запускати код від кількох користувачів без можливості перехресного втручання.
Vality

@Vality Також IBM LPAR становить ~ 1972 рік.
Елліот Фріш

@ElliottFrisch вау, це вражає. Я не здогадувався, що це вже досить рано. Дякую за цю інформацію.
Vality

48

Як бачимо, API не вказані як частина операційної системи.

Я думаю, ви занадто багато читаєте в діаграмі. Так, ОС задасть бінарний інтерфейс для того, як викликаються функції операційної системи, і він також визначить формат файлу для виконуваних файлів, але він також надасть API, в сенсі надання каталогу функцій, які можуть бути викликані додаток для виклику служб ОС.

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

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


4
Що робити, якщо вся програма зробила це додати два числа, без введення чи виводу. Ця програма все ще буде специфічною для ОС?
Пол

2
OS'es призначені для розміщення більшості специфічних для апаратури речей за / в шарі абстракції. Однак сама ОС (абстракція) може відрізнятися від реалізації до реалізації. Є POSIX деякі ОС (більш-менш) дотримуються і, можливо, деякі інші, але загальні ОС просто відрізняються занадто сильною "видимою" частиною абстракції. Як було сказано раніше: ви не можете відкрити / додому / користувача у Windows та не можете отримати доступ до HKEY_LOCAL_MACHINE \ ... у системі * N * X. Ви можете написати для цього віртуальне програмне забезпечення ("емуляція"), щоб допомогти зблизити ці системи, але це завжди "третя сторона" (від OS POV).
РобІІІ

16
@Paul Так. Зокрема, спосіб його упаковки у виконуваний файл повинен бути специфічним для ОС.
OrangeDog

4
@TimSeguine Я не погоджуюся з вашим прикладом XP проти 7. Багато що робить Microsoft, щоб забезпечити існування того ж API в 7, що і в XP. Очевидно, що тут сталося те, що програма була розроблена для роботи проти певного API або контракту. Нова ОС просто дотримувалася того ж API / контракту. Що стосується Windows, то API дуже власницький, тому жоден інший постачальник ОС не підтримує його. Навіть тоді є ще маса прикладів програм, які НЕ працюють 7
ArTs

3
@Paul: Програма, яка не вводить / виводить, - це порожня програма , яка повинна компілюватися в неоперативний режим.
Бергі

14

Чи компілятор робить щось специфічне для ОС під час компіляції цього?

Мабуть. У якийсь момент під час процесу компіляції та зв’язування ваш код перетворюється на двійковий файл, орієнтований на ОС, і пов'язаний з будь-якими необхідними бібліотеками. Вашу програму потрібно зберегти у форматі, який очікує операційна система, щоб ОС могла завантажити програму та почати її виконувати. Крім того, ви викликаєте стандартну функцію бібліотеки printf(), яка на певному рівні реалізується з точки зору послуг, які надає операційна система.

Бібліотеки забезпечують інтерфейс - шар абстракції від операційної системи та обладнання - і це дозволяє перекомпілювати програму для іншої операційної системи або іншого обладнання. Але ця абстракція існує на рівні джерела - як тільки програма компілюється та зв’язується, вона підключається до конкретної реалізації цього інтерфейсу, специфічного для даної ОС.


12

Причин є декілька, але одна дуже важлива причина - операційна система повинна знати, як читати ряд байтів, що складають вашу програму в пам'ять, знаходити бібліотеки, які йдуть із цією програмою, і завантажувати їх у пам'ять, і потім почніть виконувати свій програмний код. Для цього творці ОС створюють певний формат для цієї серії байтів, щоб код ОС знав, де шукати різні частини структури вашої програми. Оскільки основні операційні системи мають різних авторів, ці формати часто мають мало спільного між собою. Зокрема, виконуваний формат Windows має мало спільного з форматом ELF у більшості варіантів Unix. Отже, весь цей завантажувальний, динамічний зв'язуючий та виконуючий код повинен бути специфічним для ОС.

Далі кожна ОС забезпечує інший набір бібліотек для спілкування з апаратним рівнем. Це API, які ви згадуєте, і вони, як правило, бібліотеки, які представляють простіший інтерфейс розробнику, переводячи його на більш складні, конкретніші виклики в глибину самої ОС, ці виклики часто не є документально зареєстрованими або захищеними. Цей шар часто буває досить сірим, новіші API «ОС» побудовані частково або повністю на старих API. Наприклад, в Windows багато нових API, створених Microsoft за ці роки, по суті є шарами поверх оригінальних API-програм Win32.

Проблема, яка не виникає у вашому прикладі, але є однією з найбільших проблем, з якою стикаються розробники, - це інтерфейс з менеджером вікон для представлення графічного інтерфейсу. Чи є менеджер вікон частиною "ОС" іноді залежить від вашої точки зору, а також самої ОС, при цьому графічний інтерфейс в Windows інтегрований з ОС на більш глибокому рівні, тоді як графічні інтерфейси для Linux та OS X є більш безпосередньо відокремлений. Це дуже важливо, оскільки сьогодні те, що люди зазвичай називають "Операційна система", є набагато більшим звіром, ніж те, що описують підручники, оскільки воно включає багато, багато компонентів рівня додатків.

Нарешті, не суто проблемою ОС, але важливою проблемою у створенні виконуваних файлів є те, що різні машини мають різні цілі мови складання, і тому фактично згенерований код об'єкта повинен відрізнятися. Це не суворо кажучи про проблему "ОС", а скоріше апаратну проблему, але це означає, що вам знадобляться різні версії для різних апаратних платформ.


2
Можливо, варто відзначити, що більш прості формати, які можна виконати, можна завантажувати, використовуючи лише невеликий об'єм оперативної пам’яті (якщо такий є), що перевищує необхідний для утримання завантаженого коду, тоді як складніші формати можуть вимагати значно більшого сліду оперативної пам’яті під час, а в деяких випадках навіть після, завантаження. MS-DOS завантажує файли COM розміром до 63,75 К, просто зчитуючи послідовні байти в ОЗУ, починаючи з зміщення 0x100 довільного сегмента, завантажуючи CX з кінцевою адресою та переходьте до цього. Компіляція з одним проходом може бути здійснена без зворотного виправлення (корисно з дискетами) за допомогою ...
supercat

1
... маючи компілятор, включіть у кожну процедуру список всіх патч-точок, кожен з яких повинен містити адресу попереднього такого списку, а адресу останнього списку ставити в кінці коду. ОС буде просто завантажувати код як необроблені байти, але невеликий розпорядок в коді міг застосувати всі необхідні адресні виправлення перед запуском основної частини коду.
supercat

9

З іншої моєї відповіді:

Розглянемо ранні машини DOS і який реальний внесок Microsoft у світ:

Autocad повинен був написати драйвери для кожного принтера, на який вони могли надрукувати. Так само зробив лотос 1-2-3. Насправді, якщо ви хотіли друкувати ваше програмне забезпечення, вам довелося написати власні драйвери. Якщо було 10 принтерів і 10 програм, то 100 різних фрагментів по суті одного і того ж коду доводилося писати окремо і незалежно.

Те, що Windows 3.1 намагався досягти (разом із GEM та багатьма іншими шарами абстракції), це зробити так, щоб виробник принтера написав один драйвер для свого принтера, а програміст написав один драйвер для класу принтерів Windows.

Тепер із 10 програм та 10 принтерів потрібно написати лише 20 фрагментів коду, а оскільки сторона коду microsoft була однаковою для всіх, то приклади з MS означали, що вам належить зробити дуже мало роботи.

Тепер програма не обмежувалась лише тими 10 принтерами, які вони обрали для підтримки, а всіма принтерами, виробники яких надавали драйвери для Windows.

Таким чином, ОС надає послуги додаткам, тому додатки не повинні виконувати надмірні роботи.

У вашому прикладі програма C використовує printf, який надсилає символів до stdout - специфічного для ОС ресурсу, який відображатиме символи в інтерфейсі користувача. Програмі не потрібно знати, де знаходиться інтерфейс користувача - він може бути в DOS, він може знаходитись у графічному вікні, його можна перенести на іншу програму і використовувати як вхід до іншого процесу.

Оскільки ОС забезпечує ці ресурси, програмісти можуть досягти набагато більше за невелику роботу.

Однак навіть запустити програму складно. ОС очікує, що виконуваний файл на початку матиме певну інформацію, яка повідомляє ОС, як його слід запустити, а в деяких випадках (більш розвинені середовища, такі як Android або iOS), які ресурси будуть потрібні та потребують схвалення, оскільки вони торкаються ресурсів поза "пісочниця" - захід безпеки для захисту користувачів та інших програм від недобросовісних програм.

Тож навіть якщо виконавчий машинний код той самий, і немає необхідних ресурсів ОС, програма, складена для Windows, не працюватиме в операційній системі OS X без додаткового рівня емуляції чи перекладу, навіть на тому ж саме апаратному забезпеченні.

Ранні операційні системи стилю DOS часто могли ділитися програмами, оскільки вони реалізували один і той же API в апаратному забезпеченні (BIOS) і ОС, підключені до апаратних засобів для надання послуг. Отже, якщо ви написали та склали програму COM - яка є лише зображенням пам’яті з серії інструкцій процесора - ви можете запустити її на CP / M, MS-DOS та декількох інших операційних системах. Насправді ви все ще можете запускати програми COM на сучасних машинах Windows. Інші операційні системи не використовують ті самі гачки BIOS API, тому програми COM не будуть працювати на них без повторного рівня емуляції чи перекладу. Програми EXE дотримуються структури, яка включає набагато більше, ніж прості інструкції процесора, і, поряд з проблемами API, вона не працюватиме на машині, яка не розуміє, як завантажити її в пам'ять і виконати.


7

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

Звичайно, реальність це не так. EXEФайл не має такої ж формат , як ELFфайл, навіть якщо обидва містять двійковий код для того ж процесора. * Таким чином , кожна операційна система повинна буде мати можливість інтерпретувати всі формати файлів, і вони просто не робили цього в на початку, і у них не було причин починати робити це пізніше (майже напевно з комерційних причин, а не з технічних).

Крім того, вашій програмі, ймовірно, потрібно робити те, що бібліотека С не визначає, як це робити (навіть для простих речей, таких як перелік вмісту каталогу), і в цих випадках кожна ОС забезпечує власні функції (функції) для досягнення вашого завдання, природно означає, що для вас не буде найнижчого загального знаменника (якщо ви самі не зробите цей знаменник).

Отже, в принципі, це цілком можливо. Фактично, WINE запускає виконувані файли Windows безпосередньо в Linux.
Але це тонна робота та (як правило) комерційно невиправдана.

* Примітка. Виконаного файлу є набагато більше, ніж просто двійковий код. Є тонна інформація, яка розповідає операційній системі, від яких бібліотек залежить файл, скільки пам’яті стека потрібно, які функції він експортує в інші бібліотеки, які можуть залежати від нього, де операційна система може знайти відповідну інформацію про налагодження, як « повторно знайдіть "файл у пам'яті, якщо необхідно, як зробити так, щоб обробка винятків працювала правильно, і т. д. і т. д. .... знову ж, для цього може бути єдиний формат, про який всі згодні, але їх просто немає.


Веселий факт: існує стандартизований бінарний формат пози, який можна запускати через всі ОС. Це просто не використовується.
Marcin

@Marcin: Схоже, ви не вважаєте Windows ОС. (Або ви кажете, що Windows може запускати бінарні файли POSIX ?!) Для моєї відповіді POSIX не є типом стандарту, про який я маю на увазі. X в POSIX означає UNIX. Він ніколи не був призначений для використання, наприклад, Windows, навіть якщо Windows, як правило, має підсистему POSIX.
Мехрдад

1. Щось може працювати через декілька ОС, не працюючи на всіх ОС; 2. Windows з тих пір, як NT змогла запускати бінарні файли posix.
Marcin

1
@Marcin: (1) Як я вже сказав, X у POSIX означає UNIX . Це не стандарт, якого повинні були дотримуватися інші ОС, це була лише спроба досягти спільного знаменника між різними Unix, що чудово, але не так дивно. Те, що існує декілька різновидів ОС Unix, абсолютно не має значення для того, що я намагався зробити щодо сумісності в інших операційних системах, ніж Unix. (2) Чи можете ви надати посилання на номер 2?
Мехрдад

1
@Mehrdad: Марцін правий; Windows SUA (підсистема для додатків Unix) сумісна з POSIX
MSalters

5

На діаграмі шар "програми" (в основному) відокремлений від шару "операційної системи" "бібліотеками", і це означає, що "застосуванню" та "ОС" не потрібно знати один про одного. Це спрощення діаграми, але це не зовсім вірно.

Проблема полягає в тому, що в "бібліотеці" є насправді три частини: реалізація, інтерфейс до програми та інтерфейс до ОС. В принципі, перші два можна зробити "універсальними", що стосується ОС (це залежить від місця, коли ви її нарізаєте), але третя частина - інтерфейс до ОС - взагалі не може. Інтерфейс до ОС обов'язково залежатиме від ОС, API, які вона надає, механізму упаковки (наприклад, формат файлу, використовуваний Windows DLL) тощо.

Оскільки "бібліотека" зазвичай стає доступною як єдиний пакет, це означає, що після того, як програма вибирає "бібліотеку" для використання, вона зобов'язується до певної ОС. Це відбувається одним із двох способів: а) програміст вибирає повністю заздалегідь, і тоді прив'язка між бібліотекою та додатком може бути універсальною, але сама бібліотека прив’язана до ОС; або b) програміст налаштовує такі речі, щоб бібліотека вибиралася під час запуску програми, але тоді сам механізм прив'язки між програмою та бібліотекою залежить від ОС (наприклад, механізм DLL у Windows). У кожного є свої переваги та недоліки, але в будь-якому випадку ви повинні зробити вибір заздалегідь.

Тепер це не означає, що це неможливо зробити, але ви повинні бути дуже розумними. Щоб подолати проблему, вам доведеться пройти маршрут вибору бібліотеки під час виконання, і вам доведеться придумати універсальний механізм прив'язки, який не залежить від ОС (тому ви відповідально підтримуєте її, набагато більше роботи). Деколи це того варте.

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

Ви вже мали помітити, куди я йду. Мовні платформи, такі як Java, роблять саме це. Час виконання Java (бібліотека) визначає нейтральну прив'язку між вашою програмою Java та бібліотекою (як спосіб виконання Java відкриває та запускає вашу програму), і забезпечує реалізацію, характерну для поточної ОС. .NET робить те ж саме в тій чи іншій мірі, за винятком того, що Microsoft не надає "бібліотеку" (час виконання) ні для чого, окрім Windows (але інші - див. Mono). І насправді Flash теж робить те ж саме, хоча за обсягом обмежений Браузером.

Нарешті, є способи зробити те ж саме без спеціального механізму прив’язки. Можна використовувати звичайні інструменти, але відкладати крок прив’язки до бібліотеки, поки користувач не вибере ОС. Саме це і відбувається, коли ви поширюєте вихідний код. Користувач приймає вашу програму і прив'язує її до процесора (компілює його) та ОС (пов'язує його), коли користувач готовий запустити його.

Все залежить від того, як ви розрізаєте шари. Зрештою, у вас завжди є обчислювальний пристрій, виготовлений із конкретним апаратним забезпеченням, що працює під конкретним машинним кодом. Шари існують там значною мірою як концептуальні рамки.


3

Програмне забезпечення не завжди є специфічним для ОС. Як Java, так і більш рання система p-коду (і навіть ScummVM) дозволяють використовувати програмне забезпечення, яке переноситься через операційні системи. Інфоком (виробники Zork та Z-машини ) також мав реляційну базу даних на основі іншої віртуальної машини. Однак на певному рівні щось перетворює навіть ці абстракції у фактичні вказівки, що виконуються на комп'ютері.


3
Однак Java працює на віртуальній машині, яка не є перехресною ОС. Ви повинні використовувати різні двійкові
файли

3
@Izkata Правда, але ви не перекомпілюєте програмне забезпечення (лише JVM). Також дивіться моє останнє речення. Але зазначу, у Sun був мікропроцесор, який міг би безпосередньо виконувати байт-код.
Елліот Фріш

3
Java - це ОС, хоча зазвичай її не вважають єдиною. Програмне забезпечення Java характерне лише для ОС Java, а для більшості "справжніх" ОС є емулятори Java OS. Але ви можете зробити те ж саме з будь-яким хостом і цільовою ОС - як, наприклад, запуск програмного забезпечення Windows в Linux за допомогою WINE.
іммібіс

@immibis Я був би більш конкретний. Класи Java Foundation (JFC, стандартна бібліотека Java) є основою. Сама Java - це мова. JVM схожий на ОС: він має "Віртуальну машину" у своєму імені та виконує аналогічні функції ОС, з точки зору коду, що працює в ній.

1

Ти кажеш

програмне забезпечення, вироблене з використанням мов програмування для певних операційних систем, працює лише з ними

Але програма, яку ви наводите як приклад, буде працювати в багатьох операційних системах і навіть в деяких голих металах.

Тут важливим є відмінність вихідного коду від складеного двійкового коду. Мова програмування на C розроблена спеціально для незалежної ОС у вихідній формі. Це робиться, залишаючи інтерпретацію таких речей, як "друк на консолі", до виконавця. Але C може відповідати чомусь специфічному для ОС (див. Інші відповіді з причин). Наприклад, виконувані формати PE або ELF.


6
Здається, цілком зрозуміло, що ОП запитує про бінарні файли, а не про вихідний код.
Калеб

0

Інші люди добре висвітлювали технічні деталі, я хотів би зазначити менш технічну причину, сторону UX / UI:

Пишіть раз, відчувайте себе незручно всюди

Кожна операційна система має власні API інтерфейсу користувача та стандарти дизайну. Можна написати один користувальницький інтерфейс для програми та запустити його в декількох операційних системах, однак це все, але гарантує, що програма буде відчувати себе поза місцем скрізь. Створення хорошого інтерфейсу користувача вимагає налаштування деталей для кожної підтримуваної платформи.

Дуже багато цих дрібниць, але помиліться їх, і ви розчаруєте своїх користувачів:

  • У діалогових вікнах підтвердження є кнопки в різному порядку в Windows та OSX; помиліться, і користувачі натиснуть на неправильну кнопку за допомогою м'язової пам’яті. У Windows в такому порядку є "Ок", "Скасувати". У OSX розміщено замовлення, а текст кнопки "виконайте" - це короткий опис дії, яку потрібно виконати: "Скасувати", "Перемістити в кошик".
  • Поведінка "Повернутися назад" відрізняється для iOS та Android. Програми iOS за необхідності малюють власну кнопку назад, як правило, у верхньому лівому куті. Android має спеціальну кнопку в нижній лівій або нижній правій частині залежно від обертання екрана. Швидкі порти для Android будуть поводитись неправильно, якщо ігнорувати кнопку повернення ОС.
  • Швидкість прокрутки відрізняється між iOS, OSX та Android. На жаль, якщо ви не пишете рідний код інтерфейсу, вам, ймовірно, доведеться написати власну поведінку прокрутки.

Навіть коли технічно можливо створити одну кодову базу інтерфейсу, яка працює всюди, найкраще вносити корективи для кожної підтримуваної операційної системи.


-2

Важливою відмінністю на даний момент є відокремлення компілятора від лінкера. Компілятор, швидше за все, дає більш-менш однаковий вихід (різниці, в основному, обумовлені різними #if WINDOWSs). З іншого боку, лінкер повинен обробляти всі конкретні платформи - зв'язування бібліотек, створення виконавчого файлу тощо.

Іншими словами, компілятор переймається в основному архітектурою процесора, оскільки він створює фактичний код, який можна виконати, і повинен використовувати вказівки та ресурси CPU (зауважте, що байтовий код .NET або байт-код JVM вважатиметься набором інструкцій віртуального процесора на цей погляд). Ось чому ви повинні компілювати код окремо x86і ARM, наприклад.

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

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

Програмне забезпечення епохи DOS часто було більш бінарним портативним, але ви повинні розуміти, що воно також було складено не проти DOS або Unix, а проти певного контракту, який був загальним для більшості ПК у стилі IBM - вивантажуючи те, що сьогодні викликає API програмне забезпечення перериває. Для цього не потрібно було статичного зв’язку, оскільки вам потрібно було лише встановити необхідні регістри, викликати, наприклад, int 13hдля графічних функцій, і процесор просто перейшов до вказівника пам'яті, оголошеного в таблиці переривань. Звичайно, знову ж таки, практика була набагато складнішою, тому що для того, щоб виконати педалі до металу, вам довелося писати всі ці методи самостійно, але це, як правило, взагалі обійшло ОС. І звичайно, є щось, що незмінно потребує взаємодії з API API - припинення програми. Але все ж, якщо ви використовували найпростіші доступні формати (наприклад,COMна DOS, який не має заголовка, просто інструкції) і не хотів виходити, ну - щастить вам! І звичайно, ви також можете керувати належним завершенням під час виконання, так що ви можете мати код як для завершення Unix, так і для закінчення DOS в одному і тому ж виконаному файлі, а також визначати під час виконання, який саме використовувати :)


це здається лише повторюваним пунктом, поясненим у цьому та цьому попередньому відповіді, які були опубліковані вчора
гнат
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.