. | Содержание
| 2
Управление процессами.
1. Понятие процесса как такового в Колибри очень зачаточное: процесс
- объединение потоков с одним и тем же адресным пространством. У всех таких
объединяемых потоков одно и то же имя и один и тот же размер используемой
памяти.
Потоки, впрочем, существуют и обладают следующими
характеристиками (memmap.inc из исходников ядра):
- идентификатор (TID), каждому создаваемому потоку назначается уникальный
идентификатор;
- состояние потока: активен (выполняется прямо сейчас либо ждёт
переключения задач на него), заморожен, завершается, ждёт
- окно: каждый поток имеет ровно одно окно, которое может быть невидимым,
но обязательно существует;
- использование процессора: число тактов за последнюю секунду, которое
процессор убил на выполнение именно этого потока;
- имя процесса (имя исполняемого файла);
- маска событий, о которых система извещает поток;
- системный стек;
- список объектов ядра, ассоциированных с этим потоком;
- карта разрешённых портов ввода/вывода;
- текущая папка для функций файловой системы;
- буфер для сообщений IPC (присутствует, только если поток его явно
определил)
2. Процесс не идентифицируется никак; информация о потоках внутри ОС
собрана в статический массив на 255 входов (нумеруемых от 0 до 255, причём
0-й слот не может использоваться, так что всего в системе может быть не
более 255 потоков) (технически не в один массив, а в два разных, но сути
дела это не меняет).
Некоторые системные функции принимают номер слота, некоторые -
идентификатор.
3. Создание нового процесса отличается от создания потока (пожалуй,
это единственное место в API, где такое отличие есть). Создание процесса:
[core/taskman.inc, fs_execute] принимает на вход имя бинарного файла для
загрузки, параметры командной строки для нового процесса и флаги, сейчас
только то, запускается процесс как отлаживаемый или как обычный.
- загружает бинарник (целиком в память ядра; если он упакован kpack'ом, то
распаковывается в памяти);
- проверяет заголовок исполняемого файла, вычисляются нужные параметры
(есть две версии заголовка, мало отличающиеся);
- захватывает мьютекс application_table_status, управляющий доступом на
запись к таблице потоков (вышеупомянутым двум массивам);
- находит пустой слот для нового потока; если такого нет (255 потоков уже
запущены) - выход с ошибкой;
- заполняет имя процесса;
- создаёт новое адресное пространство (это отдельная история);
- вызывает функцию set_app_params, заполняющую остальные поля структуры
потока (подробнее - ниже);
- освобождает мьютекс application_table_status.
Создание нового потока: [core/taskman.inc, new_sys_threads] принимает на
вход entry point нового процесса и указатель на user-mode стек.
- захватывает application_table_status;
- находит пустой слот для нового потока; если такого нет - выход с
ошибкой;
- копирует имя процесса и информацию об адресном пространстве вызывающего
потока в структуру для нового;
- вызывает set_app_params;
- освобождает application_table_status.
Функция set_app_params:
- выделяет в адресном пространстве ядра буфер под стек ядра и область для
сохранения состояния FPU и SSE;
- инициализирует разные параметры потока значениями по умолчанию;
- копирует командную строку и путь к приложению в адресное пространство
процесса по адресам, записанным в заголовке бинарника (или не копирует, если
эти значения в заголовке нулевые, что означает, что программа в них не
нуждается);
- выделяет очередной идентификатор (каждый следующий TID равен предыдущему
+ 1);
- инициализирует user-mode контекст, значения eip и esp берутся из
параметров вызова для sys_new_threads и из заголовка для fs_execute;
- если новый процесс загружается как отлаживаемый, то помечает его
состояние как замороженное, иначе - как работающее (начиная с этого места на
новый поток возможны переключения задач).
Завершение процесса: [core/sys32.inc, terminate] когда системный поток
получает управление (главный цикл системы), одним из его действий является
проход по списку процессов, поиск потоков в завершающемся состоянии и
убийство таких процессов. Все нижеследующие действия происходят в контексте
системного потока.
- захватывает application_table_status;
- проходит по списку объектов ядра и вызывает деструкторы;
- если этот поток - последний в своём процессе, уничтожает адресное
пространство;
- освобождает разные системные ресурсы, которые мог выделить этот поток и
которых нет в списке объектов ядра (список горячих клавиш, список кнопок,
определённых потоком);
- если поток отлаживается, посылает извещение отладчику;
- освобождает память под kernel-mode стек и область сохранения FPU/SSE;
- освобождает карту ввода/вывода (если она была изменена - есть
стандартная карта ввода/вывода, которая создаётся при загрузке и разделяется
между всеми потоками);
- если окно потока было на вершине оконного стека, активирует следующее
окно;
- если поток рухнул (или был прибит) в процессе работы с жёстким диском,
освобождает мьютекс занятости жёсткого диска; то же самое для CD и дискеты;
- освобождает выделенные потоком IRQ и порты;
- если текущий прибиваемый процесс - отладчик, помечает как завершающиеся
все отлаживаемые им процессы;
- перерисовывает экран;
- освобождает application_table_status.
4. Взаимодействия процессов практически нет - есть только специальная системная функция для передачи данных от
процесса-источника процессу-приёмнику, причём приёмник должен заранее
подготовить буфер и ожидать этих данных, и некоторые возможности по отладке
приложений.
5. Соответственно синхронизации тоже практически нет - один процесс
может только проверить, завершился ли другой.
6. Состояния перечислены выше.
- Активный/ждущий -> замороженный: вызов (кем-то) функции заморозки 69.4
- Активный -> завершающийся: либо сам поток вызывает функцию завершения
-1, либо какой-то поток решает его прибить функциями
18.2 или 18.18.
- Активный -> ждущий: вызов (потоком) функции ожидания события 10.
- Замороженный -> активный/ждущий: вызов (кем-то) функции разморозки 69.5; поток возвращается в состояние до заморозки
- Замороженный -> завершающийся: 18.2, 18.18
- Ждущий -> активный: прибытие события (разрешённого маской событий
потока)
7. Планировщик циклически выделяет процессорное время всем активным
потокам. Без всяких дополнительных ухищрений.
8. Другие системные функции управления потоками:
. | Содержание
| 2
Pterox' DocPack R6. Last Edition: 29.05.2010. История выпусков