Последний раз обновлено 10.02.014
Рассматривая историческое развитие IBM PC совместимых ПК за 30 лет их существования, можно сказать, что помимо появления большого количества технических улучшений, современные ПК (2004-2014 годы) заметно отличаются от своих предшественников крайне низким качеством программного обеспечения, а именно, ПК содержат в себе значительное количество программных компонентов, которые не работают должным образом и не могут быть исправлены.
Проблемы сосредоточены главным образом в ПО для устройств и контроллеров на базе микропроцессоров, в так называемом firmware. Экономическая причина "проблемы firmware" в том, что производитель реально не имеет обязанностей по качеству работы своих изделий, но при этом имеет права, вытекающие из авторства над этими изделиями. Техническая причина "проблемы firmware" в том, что для реализации своих авторских прав, для недопущения нелегального производства отдельных компонент своих изделий и пр., производитель отказывается от открытых интерфейсов и открытых реализаций для своих продуктов.
Опыт работы показывает, что firmware применимо только к монолитным системам, которые не предусматривают произвольное изменение конфигурации, добавления новых устройств и т.п., потому что производитель может выполнить подбор и настройку firmware сам. Примерами хороших монолитных систем являются мобильные телефоны и прочие современные устройства, которые добавляют к телефону разные опции - камеры, дисплеи и т.п.
Монолитные системы выгодны производителям-монополистам, но монолитность подразумевает ограниченный функционал системы. Проблема даже не столько в том, что функционал ограничен, сколько в том, что функционал жестко предопределен при производстве. Монолитные системы хорошо подходят для создания таких устройств как телефоны, но плохо подходят для создания таких устройств как ПК.
Почему же тогда в современных монолитных системах есть возможность выполнять многие действия, которые традиционно есть в ПК? Это потому, что программное обеспечение позволяет менять конфигурацию "исходного телефона" в достаточно широких пределах, но возможности программы все равно ограничены исходными аппаратными ресурсами.
Можно ли построить "монолитный ПК"? Нет, но можно построить монолитное устройство с фиксированным, но достаточно широким функционалом, который подойдет для "домашнего использования", для "офисного использования" и т.п. Такие монолитные устройства (не будучи мобильными) появились давно и одновременно с ПК, но исторический факт популярности ПК по отношению к таким устройствам показывает, что добровольно пользователи монолитные устройства не выбирают и покупают их в основном тогда, когда у них нет иного выбора.
Итак, производители решили отказаться от ПК в пользу монолитных устройств, останутся ли у ПК приверженцы? Безусловно, все дело в том, что ПК это не бытовое устройство, у ПК всегда был и до сих пор есть вполне определенный сегмент потребителей - радиолюбители, студенты, инженеры и т.п., для них фиксированная конфигурация аппаратуры может быть совершенно недопустимой. У них свои задачи, которых просто нет у домохозяек или у офисных работников.
Я считаю, что у монолитных устройств есть очень хорошие применения не только в качестве телефонов, поскольку монолитность позволяет удешевить продукт, функциональность которого хорошо определена; но монолитность повсеместно вытесняющая ПК из "бытовых компьютеров" не даст возможность интегрировать разные устройства в одну систему, находить новые применения для ПК, что в конечном итоге замедлит развитие компьютерной техники.
Сам по себе "ПК с открытой архитектурой" не может возникнуть из хаотических усилий разных производителей. Для такого ПК нужен некий базовый проект, основа. Такой основой для ПК был IBM PC, пока не исчерпались возможности его архитектуры. Новой основы создано не было.
Как мы уже выяснили, идеология firmware неприменима для построения ПК с открытой архитектурой, заместо firmware такие ПК должны применять ПО как минимум с открытыми интерфейсами, но производители это делать отказываются, производителей мало и рыночный механизм также не работает (иногда мне кажется, что я вообще не знаю примеров, когда бы в наше время работал "рыночный механизм").
Как и для случая аппаратной архитектуры ПК, "ПО с открытыми интерфейсами" не может возникнуть самопроизвольно, также необходимо выполнять организованную, целенаправленную работу по проектированию интерфейсов.
Всем известно, что помимо коммерческого ПО, существует бесплатное ПО с открытым исходным кодом. Может ли такое ПО быть заменой для идеологии firmware? Рассматривая существующие продукты с открытым исходным кодом, мы можем отметить ряд проблем такого ПО.
а) Концептуально, неисправимо, разработчик ПО с открытым исходным кодом не имеет коммерческого интереса, что в целом отрицательно сказывается на результате. Также есть случаи, когда ПО с открытым исходным кодом используется прямо или косвенно для последующей коммерческой деятельности. Такое ПО как правило сочетает в себе худшие качества firmware и ПО с открытым исходным кодом.
б) ПО с открытым исходным кодом требует повышенной культуры программирования, может быть даже иной, по сравнению с коммерческим ПО, технологии программирования. Почему?
Представьте себе автомобиль размерами 2х3 метра. Чтобы построить такой автомобиль надо иметь огромные заводы, с огромными цехами, где грудами навалены материалы и трудится огромное число людей. Коммерческая программа построена именно так. Производитель на своих мощностях делает автомобиль и не поставляет с ним ничего лишнего.
ПО с открытым исходным кодом вместо автомобиля поставляет вам даже не разобранный автомобиль, вам поставляется весь завод, поэтому чтобы построить такой автомобиль вам надо развернуть завод, на котором затем будет произведен автомобиль. Какой технологический уровень нужен для такого завода, чтобы ему уместиться на площади хотя бы в 100х100 метров?
Как вы понимаете, это просто невозможно, поэтому ПО с открытым исходным кодом должно чем то жертвовать по сравнению с коммерческим софтом. Одна из жертв это необходимость повторного использования кода. Говорят, что многие разные программы внутри совершенно идентичны и писать каждую программу с нуля это переливать из пустого в порожнее, поэтому написав один элемент кода его затем можно использовать многократно.
Использовать многократно это легче сказать, чем сделать. Технологии ООП и паттерны проектирования это как раз то, что призвано для эффективного повторного использования кода. В том виде, как они стали известны широкой публике, это технологии 2000 года, до этого времени такие технологии даже не обсуждались к практическому применению.
Кроме повторного использования элементов кода, при смене аппаратной части готовый программный продукт повторно используется целиком. Это свойство называют переносимостью или портируемостью.
в) Коммерческое ПО обычно объявляется "не портируемым", но это не совсем правда, поскольку такое ПО абсолютно переносимо на уровне своего интерфейса, но этот интерфейс работает на уровне процессора, а не на уровне человека. Коммерческое ПО поставляется обычно в виде исполнимого файла. Почему? Потому что этой информации абсолютно достаточно для "портируемости" на уровне процессора.
В свою очередь ПО с открытым исходным кодом обычно объявляется "портируемым" и поставляется обычно в виде исходных файлов. Достаточно ли такой информации для человека? Нет. Безусловно, человек может вносить некоторые изменения в исходные файлы, но для того чтобы эффективно и осмысленно "портировать" программу из одной системы в другую (выполнять действия, которые на своем уровне совместимости эффективно делает процессор), человеку нужна проектная документация на программу.
Можно сказать, что ПО с открытым исходным кодом должно на 90% состоять из хорошей проектной документации и на 10% из хорошего исходного кода, документация и ПО с открытым исходным кодом это вещи совершенно неразрывные, вместе они являются аналогом исполнимого файла для уровня совместимости процессора.
Проектная документация должна описать структуру ПО, предназначение компонент и интерфейсов, причины принятия проектных решений и содержать всю остальную необходимую информацию, нужную для внесения изменений в эту структуру. В случае работы с конкретной периферией проектная документация должна содержать описание интерфейса работы с данной аппаратурой.
Без проектной документации ПО с открытым исходным кодом это просто вариант откомпилированного машинного языка, аналогично коммерческому ПО, но не для реального, а для некоего виртуального процессора такого типа, что человек может вносить изменения в код, а процессор автоматически правильно пересчитает смещения для переходов на не изменявшийся код.
г) Реальный процессор имеет довольно примитивные команды, которые одинаково исполняются на всех совместимых процессорах, а "виртуальный процессор" уровня человека имеет "команды", которые на всех "совместимых" процессорах выполняются непредсказуемо по разному.
Чтобы устранить такую проблему для ПО с открытым исходным кодом требуется очень хорошо определенная "виртуальная машина уровня человека", которая будет выполняться на всех реальных процессорах абсолютно одинаково. Эти требования реализует язык программирования. Как только мы используем язык программирования, мы имеем дело с виртуальной машиной.
д) Проблема виртуальной машины не только в том, что ее надо определить, но и в том, что любая виртуальная машина ухудшает качество работы программы по сравнению с программой, которая пользуется всеми возможностями реальной системы.
Требования при определении виртуальной машины взаимоисключающие: улучшение портируемости обязательно ведет к ухудшению эффективности на конкретном процессоре. Если бы это было не так, то все процессоры были бы абсолютно совместимы между собой.
Исторически эта проблема решается так. Вместо того, чтобы выбрать виртуальную машину в виде 50% совместимости и 50% эффективности, в программе выделяются абсолютно портируемая и абсолютно не портируемая части. Первая часть реализуется на 100% совместимой виртуальной машине, а вторая часть реализуется на языке на 100% приближенном к конкретной системе, так что первая часть так или иначе использует вторую часть.
В качестве языка второй части часто используется макроассемблер или язык С с макроассемблерными вставками. Роль языка С заключается не в обеспечении портируемости, а в предоставлении операторов структурного языка, фреймов функций и т.п. "макро деятельности". Код второй части имеет портируемым только интерфейс, реализацию второй части, несмотря на применение языка С, на другую систему перенести нельзя.
е) В качестве языка первой части (виртуальной машины) часто также используется язык С или С++. Вот тут и начинаются хорошо известные проблемы. С одной стороны, взять совсем абстрактную виртуальную машину (типа Java) нельзя из соображений эффективности, с другой стороны, эффективный язык С и С++ не имеет хорошо определенной абстрактной машины, поэтому есть риск, что код первой части будет перемешан с кодом второй части, визуально это все трудно будет отличить, в результате программа откажется переноситься на другую платформу или нормально на ней работать по совершенно неясной причине.
У языка типа JAVA есть хорошие применения даже в системе с хорошо определенными открытыми интерфейсами, например, пользовательская настройка расширенных параметров сетевых устройств: с помощью стандартного интерфейса можно настроить стандартные параметры маршрутизатора, но стандартизировать "тонкие" настройки конкретного устройства невозможно, чтобы задействовать особенности конкретного сетевого устройства нужно выполнять уникальный для этого устройства код на компьютере с неизвестной архитектурой. Для таких целей язык типа JAVA подходит, для обычной работы язык типа JAVA подходит плохо.
Традиционное решение этих проблем также известно. Языки С/С++ не совсем безнадежны в плане абстракции, при их небольших модификациях, а также при выдержке программистом определенного стиля программирования, можно получить некую абстрактную машину для кода первой части.
Применяя С/С++ в первой части мы пытаемся построить 100% совместимую абстрактную машину так, чтобы в рамках этой машины программа была бы на 100% эффективной на каждом конкретном процессоре.
Это кажется возможным, например, абстрактная машина С может иметь оператор целочисленного умножения. На процессорах, где такой команды нет, этот оператор будет эмулироваться, но эффективность, при необходимости умножать, у абстрактной машины не станет хуже (виноват будет конкретный процессор).
Можно догадаться, что "абстрактных машин С" может быть сколько угодно, в зависимости от потребностей в тех или иных абстрактных операторах, т.е. в зависимости от того, на какой примерно аппаратуре эта программа будет выполняться. Абстрактная машина для многоядерного суперкомпьютера не может быть такой же, как для контроллера дисковода.
Если абстрактных машин будет слишком много, то они станут "конкретными машинами" и программы потеряют совместимость, если же абстрактных машин будет слишком мало, то они станут неэффективными.
Я не готов предложить универсальную теорию о том, как правильно создавать абстрактные машины, но в этой работе мы рассмотрим требования к абстрактным машинам С для их исполнения на ПК периода 2004-2014 годов.