Вы здесь

Слабые стороны Unix

В момент своего создания в 1970-х годах Unix был очень простой ОС, созданной как один большой хак. Многие детали внутреннего устройства UNIX появились на свет просто по тому, что у авторов не было времени и желания писать сложный код там, где можно было обойтись временной "затычкой". К сожалению, в тот момент когда Unix стал популярной системой, одновременно произошли две вещи - а) стало понятно, что многие архитектурные решения, заложенные в Unix, не годятся для реальной ОС и б) уже ничего нельзя сделать не потеряв совместимости с существующими программами.

Ниже приведен конспект книги The UNIX-HATERS Handbook под редакцией Simson Garfinkel, Daniel Weise и Steven Strassmann, опубликованной IDG Books в 1994 году. За последние двадцать лет несколько из упомянутых в книге ошибок были сглажены, но в целом ситуация в мире Unix/Linux осталась прежней, поскольку слабость Unix'а заложена в самых базовых его концепциях.


"Два самых знаменитых продукта, вышедших из стен университета в Беркли, это LSD и Unix. И похоже что это не случайное совпадение" (Anonymous)

Unix это вирус - он маленький, переносимый, жрёт ресурсы хозяина, быстро мутирует.

Unix это наркотик. Как опытный наркоделец AT&T раздавала первые версии бесплатно.

Что означают названия языков C и C++? Это оценки. (В США оценки обозначаются буквами А - отлично, В - хорошо, С - так себе).


Мифы о Unix'е

  1. Он стандартен
  2. Он быстр и эффективен
  3. Он пригоден для любых приложений
  4. Он маленький простой и элегантный
  5. Шелловские программы и пайпы позволяют создавать сложные системы
  6. Он имеет электронную документацию
  7. Он имеет документацию
  8. Он написан на языке высокого уровня
  9. X-Window и Motif (Gnome, KDE) делают его дружественным к пользователю как Mac (Windows)
  10. Процессы не добавляют накладных расходов
  11. Он ввёл в обиход:
    • иерархическую файловую систему
    • электронную почту
    • сетевые и интернетовские протоколы
    • удалённый доступ к файлам
    • секретность/пароли/права доступа к файлам
    • программу finger
    • единообразный подход к устройствам ввода/вывода
  12. Он предоставляет удобную среду программирования
  13. Он - современная ОС
  14. Он, то что нужно людям
  15. Исходные коды:
    • доступны
    • понятны
    • соответствуют двоичному коду, который вы запускаете

Мистические имена

На ранних этапах разработки Unix в качестве терминала использовалась электрическая пишущая машинка - телетайп. Поскольку по клавишам приходилось бить с большой силой, программисты старались давать командам загадочные, но короткие имена - rm, cp, wc и т.п. Теперь ситуация изменилась, многие используют оконные системы и оболочки с автодополнением, но переименовать команды во что-то более осмысленное уже нельзя, не потеряв совместимость с миллионами накопленных скриптов.


Случайная порча данных в Unix'е

  1. Unix не поддерживает версии файлов. Случайное изменение нельзя откатить.
  2. Многие Unix программы (на момент написания) не проверяют коды ответов системных вызовов. Такая программа может получить ошибку при создании копии файла, но всё равно уничтожить первоисточник.
  3. Шелл выполняет подстановку метасимволов, таких как "*", не сохраняя для программы исходные параметры. В отличие от DOS, где команда del *.* выдаёт предупреждение пользователю, в Unix невозможно отличить rm * от rm file1 file2 file3...
  4. Файлы в Unix'е удаляются мгновенно без возможности последующего восстановления.

Примеры:

Опечатка rm *>o вместо rm *.o уничтожит все файлы в каталоге и создаст пустой файл "o" . Лишний пробел в rm * .o также приведёт к печальным последствиям.

Удаление администратором подкаталога, совпадающего по имени со стандартным - опасно. Вместо rm -r ./etc легко напечатать rm -r /etc, что убьёт систему. Unix не предусматривает особой защиты для системных каталогов.

Замена rm на альяс rm -i или на что-то совсем другое (например mv $@ ~/.Deleted) не является панацеей, т.к. не влияет на команды удаления файлов, встроенные в оконную систему, среду разработки и т.п. Кроме того использование альяса может нарушить работу скриптов (скрипт начнёт запрашивать подтверждения) и сбить с толку сисадмина, который будет пытаться понять, почему у пользователя неверно работает программа.

Команда rm *, выполненная в одном каталоге, сохраняется в истории команд и может быть случайно вызвана в другом подстановкой !r (последняя команда в истории на букву r).

Удаление файла с именем "*" - отдельное искусство.


Отсутствие стиля как стиль

Программы в Unix не имеют общего стиля. Каждый волен придумать свой набор опций, свой конфигурационный файл и свою систему оповещения об ошибках. Не существует требования по использованию определённых библиотек. Так ed, sed, grep и shell имеют схожие, но различные форматы регулярных выражений.

Заявленная философия простоты и самодостаточности отдельных утилит (делает мало, но делает хорошо) в реальном Unix'е не соблюдается. Простейшая команда cat, изначально предназначенная для объединения содержимого нескольких файлов в один поток, имеет несколько опций, которые предполагают, что команда используется для просмотра содержимого файла на терминале.

С другой стороны плодятся лишние программы. Вместо программы, вырезающей несколько строк из середины файла, существуют программы head- вырезание строк из начала файла и tail - вырезание из хвоста. Программы написаны разными авторами имеют разный набор опций.

Уже упоминалось, что подстановка "*" при обработке шеллом (вместо использования стандартной функции в самой программе) приводит к потере части информации о командной строке. В сочетании с тем, что Unix не отличает в командной строке имена файлов от опций, это приводит к катастрофическим последствиям. Имена файлов, начинающиеся с "-" нельзя отличить от опций. Например, команда rm * в каталоге, содержащем файл "-r" приведёт к рекурсивному удалению подкаталогов, но сохранит сам файл "-r".

Обратная ситуация. Некоторые утилиты могут воспринимать имена файлов, начинающиеся с "-" как неверные опции и не смогут обработать такие файлы:

$ mv -file file
mv: invalid option -- l
$  rm -file
usage: rm [-rif] file ...
$ rm ?file
usage: rm [-rif] file ...
$ rm ?????
usage: rm [-rif] file ...
$ rm *file
usage: rm [-rif] file ..

(В современном Linux'е выдаётся подсказка Try 'rm ./-file' to remove the file '-file', но само поведение команды не изменилось).

MAN-страница по rm в Linux'е предлагает использовать rm -- -foo для удаления -foo, но это не является частью стандарта. Авторам оригинальной книге в MANе предложили использовать rm - -foo.

Шутка с ls. Готовим каталог и файл

% mkdir foo
% touch foo/foo~

Теперь зовём ничего не подозревающего соседа и просим объяснить результат выполнения команд

% ls foo*
foo~
% rm foo~
rm: foo~ nonexistent
% rm foo*
rm: foo directory
% ls foo*
foo~
%

Попробуйте объяснить, что делает команда cat - - - (подсказка: тройное нажатие ^D завершит её работу).


Электронная документация

Основой электронной документации в Unix являются man-страницы. К сожалению, часть команд являются исполняемыми файлами (wc,ls,rm), а часть встроенными командами шелла (fg,job,alias). man-страницы описывают внешние команды и шелл в целом. Если новичок не знает какой у него шелл, он не сможет добраться до описания встроенных команд.


Предупреждения и сообщения об ошибках в Unix - ИХ НЕТ!

Ошибка в порядке написания имён файлов cc -o prog.c prog вместо cc -o prog prog.с при запуске компилятора молча уничтожит исходные тексты. Ошибка в опциях архиватора tar cf bigarchive.tar вместо tar xf bigarchive.tarмолча уничтожит архив.


Управление терминалом

То, что ранние версии Unix'а разрабатывались на компьютере с примитивным телетайпом в качестве терминала, привело к тому, что в ядре Unix'а вообще отсутствуют средства для работы с интеллектуальными средствами взаимодействия с пользователями.

Телетайпы умели построчно печатать текст и (по приходу специального символа) переходить на следующую строку (NL \n), возвращать каретку в начало строки (CR \r) и звенеть звонком (BELL \b). После телетайпов на рынок вышли текстовые видео терминалы, которые выводили текст существенно быстрее и позволяли (с помощью управляющих последовательностей символов) проделывать разные трюки с текстом на экране. К сожалению, у разных производителей управляющие последовательности были разными.

Бил Джой во время разработки редактора vi создал базу управляющих последовательностей - termcap, которая позволяла извлекать последовательности, выполнявшие определённые функции на конкретном терминале. К сожалению termcap отражала не те функции, которые были придуманы производителями, а те которые были нужны для работы редактора vi. (В последующем набор функций был несколько расширен, но сути дела это не меняет). Кроме того, код работавший с termcap в vi так и не был оформлен в отдельную библиотеку, что заставляло программистов самостоятельно изобретать собственные API.

В конце концов Кен Арнольд написал библиотеку для управления текстовым терминалом под названием curses. К сожалению, библиотека ориентировалась на ту же урезанную базу терминальных функций termcap и к тому же была не очень профессионально написана. В результате curses стала полустандартом в мире Unix. В книге есть фраза: ...и сейчас в 1994 году стандарта управления терминалом по прежнему нет. Нет его и двадцать лет спустя.

Вместо того, чтобы включить в ядро вызовы для манипулирования с абстрактным терминалом, разработчики Unix'а вынесли всю логику в относительно стандартные библиотеки или вообще зашили работу с терминалом в код программ. В первую очередь такой подход лишил Unix-программы совместно использовать один экран. Кроме того, в Unix (отчасти из из за идеи, что всё есть последовательный файл, а отчасти из за ограничений termcap и curses) никогда не была реализована работа с "умными" терминалами, которые позволяют создавать экранные формы, рисовать изображения и т.п.

Даже в тех случаях, когда можно было программно реализовать любой механизм управления экраном, например в виртуальной консоли Linux или в графическом оконном терминале xterm, разработчики шли по пути эмуляции относительно примитивного текстового терминала vt100. И всё это лишь для того, чтобы обеспечить совместимость с редактором vi.