
- •1. Классификация программного обеспечения
- •1. Базовое программное обеспечение
- •2. Трансляторы
- •3. Языки программирования
- •4. Инструментальные средства (утилиты)
- •5. Прикладное программное обеспечение
- •2. Основные задачи ос
- •3. Типы ос
- •4. Базовая система ввода/вывода (bios)
- •5. Файловая система. Типы файловых систем. Их особенности.
- •6. Загрузчик ос
- •Addr1 - addr2
- •7. Ядро ос
- •8. Основные функции ядра
- •9. Драйвер ос
- •10. Типы драйверов
- •11. Типы многозадачности, их особенности
- •12. Понятие суперпроцесса
- •13. Потоки
- •Листинг 2. Окончание процедуры инициализации ядра Linux
- •14. Семафоры
- •15. Встроенные функции ос. Встроенные команды ос
- •16. Внешние команды
- •17. Понятие пользователя. Понятие идентификатора пользователя
- •18. Понятие группы. Понятие идентификатора группы
- •19. Виртуальная память. Swap
- •20. Историческое развитие ос
- •21. Ос unix
- •22. Типы unix
- •23. Особенности bsd. Особенности System 5
- •24. Ядро unix
- •25. Типы драйверов unix
- •26. Потоки в unix
- •27. Управление процессами в unix
- •28. Режимы ядра в Unix
- •29. Файловая система в unix
- •30. Реализация безопасности в unix на уровне файловой системы
- •31. Реализация безопасности в unix на уровне ос
- •32. Понятие пользователь, группа в unix
- •33. Бесправный пользователь. Пользователь ресурса. Пользователь ос
- •34. Понятие ресурса
- •35. Понятие консоли.
- •36. Основные команды в unix
- •37. Сеть в unix
- •38. Ос ms-dos
- •39. Особенности реализации ms-dos, как составной части unix
- •40. Реализация ядра в ms-dos
- •41. Реализация драйверов в ms-dos
- •42. Реализация потоков в ms-dos
- •43. Управление процессами в ms-dos
- •44. Ограничение на использование оп
- •45. Файловая система в ms-dos
- •46. Реализация безопасности в ms-dos
- •47. Реализация многозадачности в ms-dos
- •48. Встроенные команды ms-dos
- •49. Внешние стандартные команды ms-dos
- •50. Графическая оболочка X- Window
- •51. Графическая оболочка Windows
- •52. Ос Windows nt
- •53. Ядро Windows nt
- •54. Драйверы в Windows nt
- •55. Реализация многозадачности в Windows nt
- •56. Файловая система в Windows nt
- •57. Режимы использования оп в Windows nt
- •58. Реализация безопасности в Windows nt на уровне файловой системы
- •59. Реализация безопасности в Windows nt на уросне ос
- •1. Пользователи, ресурсы и операции доступа
- •2. Локальные, глобальные и специальные группы
- •3. Встроенные группы пользователей и их права
- •4. Возможности пользователей
- •5. Управление профилями пользователей
- •6. Аудит
- •7. Репликация каталогов в сети Windows nt
- •60. Сеть в Windows nt
- •1. Однодоменная сеть Windows nt
- •2. Многодоменная сеть Windows nt
12. Понятие суперпроцесса
Суперпроцессом называют такой процесс, который имеет наименьший приоритет. В каждой ОС существуют такие процессы. Они запускаются в первую и завершаются в последнюю очередь. При
13. Потоки
Процессы в системе
Рассказ о жизни процессов естественно начать с самого начала — с их появления на свет. Так вот, процессы размножаются... почкованием: системный вызов Linux, создающий новый процесс, называется clone, а дочерний процесс представляет собой почти точную копию родительского. Только далее он выполняет назначенную ему функцию, а исходный процесс — то, что написано в программе после вызова clone. Потом отличий может стать больше, так что пути-дороги процессов способны разойтись достаточно далеко. Но если нам нужно этому воспрепятствовать, вызов clone позволит задать флаги, указывающие, что порожденный процесс будет иметь со своим предком общие:
адресное пространство (CLONE_VM);
информацию о файловой системе (CLONE_FS): корневой и текущий каталоги, а также umask;
таблицу открытых файлов (CLONE_FILES);
таблицу обработчиков сигналов (CLONE_SIGHAND);
родителя (CLONE_PARENT) — конечно, в этом случае будет порожден не дочерний, а сестринский процесс.
Нить и задача
Нити, т. е. параллельно выполняемые части одной программы, в стандартной библиотеке поддержки многонитевых программ Linux реализованы просто как процессы, порожденные с указанием флага CLONE_VM, и с точки зрения ядра системы ничем не отличаются от любых других процессов. Однако в некоторых альтернативных реализациях многонитевых библиотек дело обстоит иначе.
Помимо процессов описанного выше вида бывают еще «ущербные», порождаемые с помощью функции kernel_thread для внутренних системных нужд. У них нет параметров командной строки, как правило, они не имеют открытых файлов и т. д. Поскольку, несмотря на свою ущербность, эти процессы все равно фигурируют в списке задач, в литературе иногда различают полноценные процессы, порожденные из «пространства пользователя» (userspace), и задачи, т. е. все процессы, включая внутренние процессы ядра.
Процесс и программа
Вы скажете: все это замечательно, но если новый процесс — всегда копия существующего, то каким образом в системе ухитряются работать разные программы? И откуда берется самая первая из них?
Процессы, выполняющие разные программы, образуются благодаря применению имеющихся в стандартной библиотеке Unix функций «семейства exec»: execl, execlp, execle, execv, execve, execvp. Эти функции отличаются форматом вызова, но в конечном итоге делают одну и ту же вещь: замещают внутри текущего процесса исполняемый код на код, содержащийся в указанном файле. Файл может быть не только двоичным исполняемым файлом Linux, но и скриптом командного интерпретатора, и двоичным файлом другого формата (например, классом java, исполняемым файлом DOS). В последнем случае способ его обработки определяется настраиваемым модулем ядра под названием binfmt_misc.
Таким образом, операция запуска программы, которая в DOS и Windows выполняется как единое целое, в Linux (и в Unix вообще) разделена на две: сначала производится запуск, а потом определяется, какая программа будет работать. Есть ли в этом смысл и не слишком ли велики накладные расходы? Ведь создание копии процесса предполагает копирование весьма значительного объема информации.
Смысл в данном подходе определенно есть. Очень часто программа должна совершить некоторые действия еще до того, как начнется собственно ее выполнение. Скажем, в разбиравшемся выше примере мы запускали две программы, передающие друг другу данные через неименованный канал. Такие каналы создаются системным вызовом pipe; он возвращает пару файловых дескрипторов, с которыми в нашем случае оказались связаны стандартный поток ввода (stdin) программы wc и стандартный поток вывода (stdout) программы dd. Стандартный вывод wc (как, кстати, и стандартный ввод dd, хотя он никак не использовался) связывался с терминалом, а кроме того, требовалось, чтобы командный интерпретатор после выполнения команды не потерял связь с терминалом. Как удалось этого добиться? Да очень просто: сначала были отпочкованы процессы, затем проделаны необходимые манипуляции с дескрипторами файлов и только после этого вызван exec.
Аналогичного результата (как показывает, в частности, пример Windows NT) можно было бы добиться и при запуске программы за один шаг, но более сложным путем. Что же касается накладных расходов, то они чаще всего оказываются пренебрежимо малыми: при создании копии процесса его индивидуальные данные физически никуда не копируются. Вместо этого используется техника, известная под названием copy-on-write (копирование при записи): страницы данных обоих процессов особым образом помечаются, и только тогда, когда один процесс пытается изменить содержимое какой-либо своей страницы, она дублируется.