Главная » Ядро Linux » Реализация  потоков в ядре  Linux

0

Многопоточность — это  популярная сегодня  программная абстракция. Она  обеспечивает выполнение нескольких потоков в совместно используемом адресном пространстве памяти.  Потоки  также  могут  совместно использовать открытые файлы и другие  ресурсы. Многопоточность используется для  параллельного программирования (concurrent programming),  что  на  многопроцессорных  системах  обеспечивает истинный параллелизм.

Реализация  потоков в операционной системе   Linux  уникальна. Для  ядра  Linux не  существует  отдельной  концепции  потоков.  В  ядре  Linux  потоки  реализованы  так же, как  и  обычные процессы.  В  ОС  Linux  нет  никакой  особенной семантики для планирования  выполнения  потоков  или  каких-либо  особенных  структур   данных для  представления  потоков.  Поток—  это  просто   процесс,  который  использует некоторые  ресурсы  совместно  с  другими   процессами.  Каждый  поток  имеет  структуру task_struc t  и  представляется для  ядра  обычным  процессом  (который  совместно использует ресурсы,  такие  как  адресное пространство, с  другими  процессами).

В  этом   смысле   Linux  отличается  от  других  операционных  систем,  таких  как Microsoft  Windows  или  Sun  Solaris,  которые  имеют   явные  средства   поддержки  потоков  в  ядре  (в  этих  системах   иногда  потоки называются процессами  с быстрым  переключением контекста, lightweight process). Название "процесс с быстрым переключением  контекста" показывает разницу между философией Linux  и других  операционных систем.   Для  остальных операционных  систем   потоки—   это  абстракция,  которая обеспечивает облегченные,  более  быстрые   для  исполнения  сущности,  чем  обычные тяжелые  процессы. Для  операционной системы Linux  потоки — это  просто  способ совместного использования  ресурсов  несколькими  процессами  (которые и  так  имеют достаточно малое  время  переключения контекста)11 .

Допустим, у нас  есть  процесс,  состоящий из  четырех  потоков.  В  операционных системах   с  явной  поддержкой потоков должен   существовать дескриптор  процесса, который  далее  указывает  на  четыре   потока.  Дескриптор  процесса  описывает совместно  используемые ресурсы, такие  как  адресное пространство  и  открытые файлы.  Потоки описываются ресурсами, которые принадлежат только   им.  В  ОС  Linux, наоборот,  существует  просто   четыре  процесса и,  соответственно, четыре   обычные структуры   task_struct .  Четыре   процесса построены так,  чтобы  совместно  использовать   определенные  ресурсы.

Потоки  создаются так  же,  как  и  обычные задания,  за  исключением того,  что  в системный вызов  clon e ()  передаются флаги  с указанием, какие  ресурсы  должны  использоваться  совместно:

Clone (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0);

11Как приме р можно  привести тесты по измерени ю времени создания процессов (и даже потоков) и операционно й  системе  Linux  по сравнени ю с другими  операционным и системами. Результаты очень хорошие.

Результат выполнения  показанного кода  будет таким  же, как  и  при  выполнении обычного вызова for k (), за исключением того, что  адресное пространство, ресурсы  файловой системы, дескрипторы файлов и  обработчики сигналов останутся общими. Другими словами, новая  задача, так  же  как  и родительский процесс, — обычные  потоки. В  отличие от  этого, обычный вызов   for k ()   может  быть  реализован следующим образом:

clone (SIGCHLD, 0);

а вызов  vfor k ()  в таком виде:

clone (CLONE_VFORK | CLONE_VM | SIGCHLD,  0);

Флаги,  которые передаются в системный вызов  clon e () , помогают указать  особенности поведения нового процесса и детализировать, какие ресурсы должны быть общими для  родительского и порожденного процессов. В табл.  3.1  приведены флаги системного вызова  clon e ()  и их эффект.

Таблица 3.1 . Флаги системного вызова clon e ()

Флаг                                       Описание

CLONE_FILES CLONE_FS CLONE_IDLETASK

CLONE_NEWNS

CLONE_PARENT

CLONE_PTRACE CLONE_SETTID CLONE_SETTLS

CLONE_SIGHAND CLONE_SYSVSEM CLONE_THREAD CLONE_VFOK

CLONE_ONTRACED

CLONE_3T0P CLONE_CHILD_CLEARTID CLONE_CHILD_SETTID CLONE_PARENT_SETTID CLONE_VM

Родительский и порожденный процессы совместно используют открытые файлы

Родительский и порожденный процессы совместно используют информацию о файловой  системе

Установить значение PID в нуль (используется только для холостых

(idle) задач)

Создать новое пространство имен для порожденной задачи

Родительский процесс вызывающего процесса становится родительским и для порожденного

Продолжить трассировку и для порожденного процесса

Возвратить значение идентификатора TID в пространство пользовател? Для порожденного процесса создать новую область локальных дан-

ных потока (thread local storage, TLS)

У порожденного и родительского процессов будут общие обработчики сигналов

У родительского и порожденного процессов будет общая семантика обработки флага SEM_UNDO ДЛЯ семафоров System V

Родительский и порожденный процессы будут принадлежать одной группе потоков

Использовать vf or k ():  родительский процесс будет находиться

а приостановленном состоянии, пока порожденный процесс не возобновит его работу

Запретить родительскому процессу использование флага

CLONE_PTRAC E для порожденного процесса

Запустить процесс в состоянии TASK_STOPPE D

Очистить идентификатор TID для порожденного процесса Установить идентификатор TID для  порожденного процесса Установить идентификатор TID для родительского процесса

У порожденного и родительского процессов будет общее адресное пространство

Потоки в пространстве  ядра

Часто  в ядре  полезно выполнить некоторые операции в фоновом режиме. В ядре такая возможность реализована с помощью потоков пространства ядра (kernel thread) — обычных процессов,  которые выполняются  исключительно в  пространстве ядра. Наиболее существенным отличием между  потоками пространства ядра  и  обычными процессами является то,  что  потоки в пространстве ядра  не  имеют  адресного пространства (значение указателя mm для них равно  NULL). Эти  потоки работают только в  пространстве ядра, и  их контекст не  переключается в пространство пользователя. Тем  не  менее  потоки в пространстве ядра  планируются и вытесняются так  же, как  и обычные процессы.

В  ядре   Linux  потоки  пространства ядра  выполняют  определенные  задания, наиболее часто  используемые, — это   pdflush  и  ksoftirq. Эти  потоки создаются при  загрузке  системы другими   потоками  пространства ядра.  В действительности поток   в пространстве ядра  может  быть  создан  только  другим  потоком,  работающим в пространстве ядра.   Интерфейс для  запуска нового   потока в  пространстве ядра  из  уже существующего потока  следующий:

int kernel_thread(int (*fn) (void *) , void * arg, unsigned long flags)

Новая задача  создается с помощью обычного системного вызова  clon e ()   с  соответствующими значениями флагов, указанными в параметре flags . При  возврате из системного  вызова  родительский поток  режима ядра  завершается и  возвращает указатель  на  структуру   task_struc t  порожденного  процесса.  Порожденный  процесс выполняет функцию,  адрес  которой указан   в  параметре  fn , в  качестве аргумента этой  функции передается параметр arg . Для указания обычных флагов  потоков пространства ядра  существует флаг  CLONE_KERNEL,   который объединяет в  себе  флаги CLONE_FS, CLONE_FILES и CLONE_SIGHAND, так как большинство потоков пространства  ядра  должны указывать эти  флаги   в  параметре  flags .

Чаще  всего  поток  пространства ядра  продолжает выполнять свою  функцию вечно (или, по крайней мере, до перегрузки системы, но  когда  она  произойдет в случае  ОС Linux  неизвестно). Функция потока обычно содержит замкнутый цикл,  в котором поток   пространства ядра  по  необходимости возобновляет  выполнение,  исполняет свои  обязанности и снова  переходит в приостановленное состояние.

В следующих главах  более  детально будут  рассмотрены конкретные  примеры  потоков  пространства ядра.

Источник: Лав,  Роберт. Разработка ядра  Linux, 2-е  издание. : Пер.  с англ.  — М.  : ООО  «И.Д.  Вильяме» 2006. — 448 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии