Видеоролик на канале Computerphile посвящен исторической роли и непреходящему влиянию языка программирования C на компьютерную индустрию. Ведущий и приглашенный эксперт обсуждают эволюцию операционных систем от эпохи мейнфреймов до современных архитектур, а также объясняют, почему C стал эталоном системного программирования. Особое внимание уделяется балансу между эффективностью низкоуровневого кода и абстракцией современных языков.
💾 Эпоха мейнфреймов и вызов для операционных систем 0:00
Язык программирования C занимает особое место в иерархии технологий, и для этого есть веские причины. Его главная сила и основное преимущество раскрываются в том случае, если рассматривать его как классический язык реализации системного программного обеспечения.
Чтобы понять это, необходимо вернуться к эпохе ранних мейнфреймов, которая началась в 1960-х годах. По стандартам того времени эти компьютеры были невероятно мощными, но при этом настолько дорогими, что их приходилось использовать в режиме разделения времени между множеством пользователей. Это, в свою очередь, требовало создания системного программного обеспечения, способного поддерживать многозадачность, распределяя кванты процессорного времени между программами разных людей, одновременно загруженными в память.
Со временем компьютерные системы эволюционировали. Им требовалось не просто выводить результаты вычислений на печать, но и сохранять их в файлы, что привело к необходимости создания полноценных файловых систем. К началу 1970-х годов программисты столкнулись с невероятным вызовом: одной из самых сложных задач реального времени, от которой зависела удовлетворенность пользователей, стала сама операционная система.
🛠️ Появление макроассемблеров и закон Мура 2:01
Долгое время в индустрии господствовало убеждение, что операционную систему можно написать исключительно на ассемблере. Среди разработчиков того времени, как иронично отмечает эксперт, существовал определенный стереотип: «настоящие мужчины используют ассемблер». Тем не менее многие специалисты искали способы сохранить рассудок и пытались привнести в низкоуровневое программирование элементы языков более высокого уровня, если это не приводило к критическому замедлению работы.
Программисты постепенно улучшали ассемблеры, превращая их в макроассемблеры. Однако им противостояла целая «армия» критиков, утверждавших, что языки высокого уровня слишком неэффективны и для любых задач все равно потребуется ассемблер.
Этому противостоянию положил конец закон Мура. В начале 1970-х годов компьютерная индустрия получила возможность использовать высокоуровневые языки для гораздо большего спектра задач. Началась волна экспериментов по адаптации существующих языков под нужды системного программирования. Особое внимание уделялось внедрению низкоуровневых операций для работы с битами и байтами, что становилось критически важным для извлечения символов из памяти.
В этот же период на горизонте появились 8-битные архитектуры, которые поначалу казались разработчикам «игрушечными» по сравнению с 16-битными системами. Индустрии требовался язык, способный эффективно справляться с объектами разной разрядности. По мере удешевления аппаратного обеспечения ситуация на рынке менялась: компания DEC выпустила миникомпьютеры PDP-11, а затем и 32-битные машины VAX, производство которых наконец-то стало экономически выгодным. В это время дискретные транзисторы и компоненты на печатных платах уступили место технологии больших интегральных схем (БИС/LSI).
🚀 Триумф языка C и фактор портативности 4:14
Изменения в архитектуре железа напрямую повлияли на выбор языков программирования. По мнению эксперта, C стал самым успешным языком реализации систем за всю историю. Разумеется, существовали и другие альтернативы — например, языки Bliss, Algol 68 или BCPL, однако C обладал колоссальным преимуществом, которое заключалось в его портативности.
Разработчики Деннис Ритчи и Кен Томпсон создавали C на базе PDP-11, но язык можно было перенести и на архитектуру VAX. Когда на рынке внезапно появились серверы компании Sun Microsystems, перед инженерами встала задача перенести на них операционную систему Unix. Для этого требовалось в первую очередь запустить компилятор C, что было успешно реализовано. Способность адаптироваться к любым аппаратным платформам позволила C выдержать испытание временем. Эксперт указывает, что достаточно посмотреть на список архитектур, поддерживаемых современным компилятором GCC, чтобы убедиться в универсальности этого языка.
⛓️ Проблема указателей и эволюция языков высокого уровня 5:22
Со временем разница между системными и прикладными языками программирования стала более выраженной. В середине и конце 1980-х годов Джеймс Гослинг из Sun Microsystems, наблюдая за работой программистов, проанализировал количество ошибок, совершаемых при использовании указателей. По воспоминаниям эксперта, одним из главных требований при проектировании языка Java было полное исключение указателей на уровне пользователя. Создатели Java исходили из логики, что раз указатели являются основной причиной сбоев в программах, то их необходимо запретить.
Приглашенный эксперт соглашается с этим подходом, отмечая, что если у разработчика нет прямой необходимости в низкоуровневом манипулировании памятью, то эту задачу должен брать на себя сам язык. В качестве альтернативы он приводит C++, где можно не писать сложную логику «под капотом» самостоятельно (если только вы не пишете операционную систему), а использовать проверенные и эффективные библиотеки функций.
Параллельно развивались функциональные языки программирования. Долгое время их критиковали за медлительность, однако с ростом вычислительных мощностей они стали более применимыми. Как утверждал Брайан Керниган, они становились «все менее и менее неэффективными». Эксперт называет появление мощного и быстрого железа главным освобождением в своей профессиональной карьере, поскольку оно позволило тестировать идеи без многочасовых ожиданий.
🔨 Универсальный инструмент или «каждому заданию своя лошадь» 7:42
Ведущий канала, позиционируя себя как не-программиста, задается вопросом: почему в ИТ-индустрии не существует одного универсального языка, который подходил бы для абсолютно любых задач?
Эксперт отвечает на это аналогией из повседневной жизни. Профессиональный инструмент для работы практически всегда отличается от инструмента бытового уровня. Обычная дрель с ударным механизмом из магазина стройматериалов принципиально похожа на промышленный перфоратор, используемый для разрушения стен зданий, но их технические характеристики и конструкция кардинально различаются.
В современном программировании действует тот же принцип: язык нужно подбирать под конкретную задачу.
- Если задача требует использования Python — нужно использовать Python.
- Если для анализа данных необходим язык R — следует выбрать его.
- Для быстрой обработки текстов или автоматизации эксперт часто применяет язык Awk, на котором он в свое время оперативно написал программу для декодирования кодов Рида — Мюллера, поступавших с Марса.
Если же готовое решение оказывается недостаточно эффективным, разработчик всегда может спуститься на уровень ниже и переписать критические участки на более быстром языке.
🏛️ Проблема устаревшего ПО и сила симуляции 8:49
Несмотря на появление новых технологий, индустрия сталкивается с серьезной проблемой legacy-софта. Огромное количество программного обеспечения следовало бы переписать еще много лет назад. Однако на практике, если система работает и выполняет свои функции, у руководства возникает соблазн оставить ее нетронутой из-за высокой зависимости других процессов от этого кода.
По этой причине в вооруженных силах до сих пор можно встретить работающие программы для 8-битных процессоров Z80, а крупные коммерческие компании продолжают использовать COBOL на мейнфреймах. В современных реалиях симуляция работы мейнфрейма обходится в копейки, в то время как переписывание старого софта будет стоить целое состояние и неизбежно приведет к возникновению новых ошибок в отлаженной системе.
Ведущий напоминает известную поговорку: «Если оно не сломалось — не чини его». Эксперт добавляет, что сегодня для поддержки старого ПО нет необходимости физически воссоздавать экзотическое железо 1960-х годов. Достаточно направить усилия на создание качественного программного симулятора, что позволяет успешно выполнять код, написанный 30 или 40 лет назад.
В завершение беседы участники упоминают архивные изыскания: из-за постепенного размагничивания старых дискет программистам приходится делать резервные копии данных, благодаря чему удается спасать уникальные исторические программы — например, старую трехмерную игру Lander, ставшую предтечей знаменитой игры Zarch.