Проектирование и реализация ядра Linux

задняя часть Операционная система Linux

1. Введение в ядро ​​Linux

1. Введение в линукс

1.1 Особенности Unix

  • unix очень лаконичен, предоставляет всего несколько сотен системных вызовов и имеет очень четкую цель разработки
  • Все в unix рассматривается как файл, и эта абстракция позволяет получать доступ как к данным, так и к устройствам через один и тот же набор интерфейсов системных вызовов.
  • Ядро написано на C, переносимость сильная
  • Быстрое создание процессов, уникальные форк-вызовы
  • Предоставляет краткие, но стабильные примитивы межпроцессного взаимодействия

1.2 юникс и линукс

  • Linux клонирует Unix, но не Unix
  • Linux Unix рисует много дизайна и реализации API Unix
  • Linux не использует напрямую исходный код Unix, но полностью отражает цели разработки Unix и обеспечивает согласованные программные интерфейсы.

2. Введение в операционную систему и ядро

  • Ядро обычно включает в себя:
    • Процедура обслуживания прерываний: отвечает за реагирование на прерывания.
    • Планировщик: управляет несколькими процессами, распределяет процессорное время
    • Диспетчер памяти: управление объемом памяти
    • Программа системы обслуживания: включая сеть, межпроцессное сообщение
  • Приложения запускаются через системные вызовы и взаимодействие с ядром
  • Приложения обычно вызывают библиотечные функции, а библиотечные функции позволяют ядру использовать их для выполнения различных задач через системные вызовы.
  • Управление ядром аппаратных устройств: когда оборудование хочет установить связь, оно отправляет асинхронный сигнал для прерывания ядра, и ядро ​​находит обработчик по номеру прерывания.
  • специфическая для разработки ядра Linux
    • Стандартная библиотека c не может быть связана. Библиотека c слишком велика и влияет на размер и эффективность. Однако большинство часто используемых функций C реализованы в ядре.
    • Нет механизма защиты памяти, обратите внимание на несанкционированный доступ к адресам памяти
    • Не используйте числа с плавающей запятой легко, чтобы вручную сохранять и восстанавливать регистры с плавающей запятой.
    • Пространство стека небольшое и фиксированное. 32 это 8кб для машины, 64 это 16кб
    • Ядро подвержено гонкам, обратите внимание на синхронизацию и параллелизм.
    • Обратите внимание на портативность

2. Управление процессами

1. Основные понятия

  • Два абстрактных объекта системы unix: процесс и файл. Для получения подробной информации см. остальные триСтатьи Последовательность процессов и файлов на Unix
  • Процесс — это программа в фазе выполнения, и Linux обычно также называет процесс задачей.
  • К процессам относятся: сегменты кода, сегменты данных, открытые файлы, ожидающие сигналы, адресные пространства, потоки и т. д.
  • Поток — это активный объект выполнения в процессе.
  • Каждый поток имеет независимый счетчик программ, стек процесса и набор регистров процесса.
  • Объектом планирования ядра является поток, а не процесс
  • Реализация потоков Linux очень особенная и не различает нити и процессы.
  • Процессы предоставляют два виртуальных механизма: виртуальные процессоры и виртуальную память.
  • Потоки внутри одного процесса могут совместно использовать виртуальную память, но иметь собственные виртуальные процессоры.

2. Дескриптор процесса и очередь задач

2.1 Основные понятия

  • Ядро хранит процессы в двусвязных списках, называемых очередями задач.
  • Каждый элемент в связанном списке представляет собой тип task_struct, называемый дескриптором процесса, включая всю информацию о процессе. Путь: /include/linux/sched.h

2.2 Как назначить дескрипторы процесса

  • Linux выделяет свою структуру task_struct через slab, что позволяет добиться повторного использования объектов и окраски кеша.
  • За счет предварительного выделения и повторного использования task_struct можно избежать потери производительности, вызванной динамическим выделением и освобождением, поэтому процесс создания выполняется быстро.
  • Структура task_struct помещается в конец стека ядра, чтобы позволить аппаратной системе с небольшим количеством регистров вычислять позицию только через указатель стека, избегая использования дополнительных регистров для хранения.
  • Распределитель slab создает новую структуру thread_info в конце стека ядра, а внутренняя задача указывает на фактическую задачу task_struct. Расположение thread_info:

2.3 Где хранятся дескрипторы процессов?

  • Текущий макрос может найти дескриптор текущего запущенного процесса.
  • Конкретная реализация этого макроса варьируется в зависимости от соответствующей архитектуры аппаратного обеспечения
  • Система X86, найдите дескриптор процесса через указатель задания структуры Thream_info в конце стека
  • В некоторых системах (IBM RISC) для хранения адреса task_struct выделяется специальный регистр.

2.4 Состояние процесса

  • Поле состояния дескриптора процесса описывает текущее состояние процесса, и каждый процесс находится в одном из пяти состояний.
    • TASK_RUNNING: Выполняется. Процессы исполняемые.
    • TASK_INTERRUPTIBLE: прерываемая. Процесс заблокирован, ожидая пробуждения
    • TASK_UNINTERRUPTIBLE: бесперебойная работа. При получении сигнала ответа не происходит. В представлении команды ps отобразится буква D.
    • Task_zombie: зомби. Процесс закончился, но родительский процесс не назвал системный вызов Wait4
    • TASK_STOPPED: остановить. Процесс перестает выполняться
  • диаграмма перехода состояний
  • Установите текущий процесс: set_task_state(задача, состояние) или set_current_state

2.5 Контекст процесса

  • Как правило, программа выполняется в пространстве пользователя, когда выполняется системный вызов или срабатывает исключение, она входит в пространство ядра, а ядро ​​выполняется от имени процесса и находится в контексте процесса.
  • Интерфейс системного вызова к ядру и обработке исключений является четко определен, все доступ к ядру только через эти интерфейсы
  • Процесс Linux имеет четкие отношения наследования, все процессы являются потомками процесса PID 1 INIT.
  • Каждый процесс в системе должен иметь родительский процесс, и каждый процесс может иметь один или несколько дочерних процессов.
  • Отношения между процессами хранятся в дескрипторах процессов. Родительская переменная в task_struct указывает на task_struct и хранит адрес родительского процесса. Переменная Children представляет собой связанный список, указывающий на все дочерние процессы.

3. Создание процесса

3.1 Основные понятия

  • Создание процесса Unix делится на два этапа: fork и exec.
  • fork создает дочерние процессы, копируя текущий процесс. Дочерний процесс и родительский процесс имеют лишь несколько отличий: pid, ppid, определенные ресурсы и статистика
  • exec отвечает за чтение исполняемого файла и загрузку адресного пространства для запуска

3.2 Копирование при записи (COW)

  • Традиционный форк прямого копирования ресурсов неэффективен, Linux использует технологию копирования при записи для повышения эффективности.
  • COW не копирует все адресное пространство, а позволяет родительским и дочерним процессам совместно использовать память только для чтения, а данные копируются только при записи.

3.3 функция вилки

  • by linux clone) системный вызов fork() (, этот вызов с идентификацией параметра (много типов) указывает на необходимость совместного использования ресурсов
  • clone вызывает do_fork внутри для завершения основной работы (kernel/fork.c)
  • do_fork вызывает copy_process внутренне, затем позволяет процессу работать
  • процесс вызова copy_process:
    • Вызовите dup_task_struct, чтобы создать стек ядра, структуру thread_info и task_struct для нового процесса, эти значения такие же, как у текущего процесса, и дескрипторы точно такие же в это время
    • Проверьте, не превышает ли количество процессов, принадлежащих системе, лимит
    • сброс многих членов
    • Установите статус task_uninterruptible, чтобы гарантировать, что он не будет запущен
    • вызовите copy_flags, чтобы обновить элемент flags в task_struct
    • Вызовите get_pid, чтобы получить новый pid
    • В соответствии с идентификацией параметра копируйте или делитесь открытыми файлами, информацией о файловой системе, функциями обработки сигналов, адресным пространством процесса, пространством имен и т. д. Как правило, эти ресурсы совместно используются потоками.
    • Родительский и дочерний процессы делят квант времени поровну
    • Sweep работает и возвращает указатель на дочерний процесс
  • Вновь созданный процесс пробуждается и введен в эксплуатацию. Как правило, приоритетный дочерний процесс выполняется в первую очередь.

3.4 функция вилки

  • Та же функция, что и fork, за исключением того, что составляет запись таблицы страниц родительского процесса.
  • путем передачи специального флага системному вызову clone
  • Дизайн этой функции не очень хорош

4. Реализация потоков в linux

4.1 Обзор потоков liunx

  • Набор адресного пространства памяти в наборе процессов совместного использования потоков, открытых файлов и других ресурсов.
  • Механизм потока поддерживает параллельные технологии программирования и обеспечивает истинную параллельную обработку на нескольких процессорах
  • Механизм реализации потоков в Linux очень уникален, с точки зрения ядра понятие потоков отсутствует.
  • В Linux все потоки реализованы как процессы. В ядре нет специального алгоритма планирования или структуры данных для описания потоков. Оно рассматривается как процесс, использующий некоторые общие ресурсы.
  • Каждый поток имеет свою собственную структуру task_struct, как и обычный процесс, этот процесс разделяет некоторые ресурсы с другими процессами.
  • Реализация сильно отличается от других систем (Windows, Solaris), ядра этих систем специально обеспечивают поддержку потоков.

4.2 создание потока Linux

  • Создание потоков и общие типы создания процессов, за исключением того, что при вызове клона вам необходимо передать некоторые флаги параметров, чтобы указать ресурсы, которые необходимо разделить.
  • Логотип параметра Описание:
    • CLONE_VM: родительский и дочерний процессы совместно используют адресное пространство
    • CLONE_SIGHAND: родительский и дочерний процессы совместно используют обработчики сигналов.
    • CLONE_THREAD: родительский и дочерний процессы помещаются в одну и ту же группу потоков.
    • CLONE_FS: родительский и дочерний процессы совместно используют информацию о файловой системе.
    • CLONE_FILES: общие открытые файлы ...

4.3 Тема ядра

  • Поток ядра: стандартный процесс, который выполняется независимо в пространстве ядра.
  • Отличие от обычных процессов: нет независимого адресного пространства, он может работать только в пространстве ядра
  • Создание может быть создано только другими потоками ядра, функция kernel_thread

4.4 Завершение процесса

бесплатные ресурсы

  • Когда процесс завершается, ядро ​​должно освободить имеющиеся у него ресурсы и уведомить об этом родительский процесс.
  • Окончание может быть нормальным, нештатным, также можно завершить функции очистки регистрации, как описано в другой статье:Цикл статей о процессах и файлах unix
  • В конце будет вызван do_exit (kenel/exit.c), и выполненная работа включает в себя:
    • Установите элемент flags из task_struct в PF_EXITING.
    • Если включена функция учета процессов, для вывода статистики будет вызываться acct_process
    • Вызовите функцию _exit_mm, чтобы отказаться от mm_struct, занятой процессом, и полностью освободить ее, если она не используется совместно.
    • Позвоните Sem_exit. Если сигнал в очереди IPC, чтобы оставить очередь
    • Вызов __exit_files: дескриптор файлов уменьшения; __exit_fs: данные о файловых системе; EXIT_NAMESSAPEASE: Количество ссылочного пространства имен; EXIT_SIGHAND: Количество ссылок функции обработки сигналов, если вы можете быть выпущены
    • Код выхода из task_struct устанавливает код выхода.
    • Вызовите exit_notify, чтобы отправить сигнал процессу, родительский процесс изменен на другой поток или процесс инициализации, а состояние процесса установлено на TASK_ZOMBLE (зомби, не запланировано).
    • Наконец, расписание вызовов для переключения на другие процессы
  • После вызова do_exit все ресурсы, относящиеся к процессу, освобождаются, и единственные ресурсы, которые он занимает, — это стек ядра, сообщающий об ошибке thread_info, и небольшой slab, сохраняющий task_struct.Единственная цель существования — предоставить информацию процессу. родительский процесс.

удалить дескриптор процесса

  • После звонка Do_exit, Thread Dead, но сохраняет дескриптор файла
  • После того, как родительский процесс получает информацию о дочернем процессе, структура Task_sturct дочернего процесса освобождается.
  • Функция ожидания вызывает реализацию системной функции wait4, которая приостанавливает вызывающий ее процесс до тех пор, пока не завершится один из дочерних процессов, а функция возвращает pid дочернего процесса.
  • Когда, наконец, потребуется освободить дескриптор процесса, будет вызвана функция release_task для выполнения следующей работы:
    • Вызовите free_uid, чтобы уменьшить счетчик использования процесса владельцем процесса.
    • Вызовите unhash_process, чтобы удалить процесс из pidhash и удалить процесс из task_list.
    • Если процесс отслеживается ptrace, сбросьте родительский процесс трассировки.
    • Наконец, вызовите put_task_struct, чтобы освободить страницы, занятые стеком ядра и структурой thread_info, и освободите slab-кеш, занятый task_struct.
    • В это время освобождаются все ресурсы и дескрипторы.

Обработка потерянных процессов

  • Если родительский процесс завершается раньше дочернего процесса, он должен найти нового родителя, иначе он умрет навсегда.
  • Функция notify_present, вызываемая функцией поиска отца в do_exit, внутренне вызывает forgot_original_parent, эта функция реализует конкретный процесс поиска.
  • Эта функция устанавливает родителем другие процессы в группе потоков, если нет, используйте процесс инициализации

3. Планирование процесса

1 Обзор

  • Планировщик — это компонент ядра, отвечающий за выбор следующего запускаемого процесса.
  • Планировщик отвечает за выделение ресурсов процессорного времени исполняемым процессам.
  • Многозадачные системы можно разделить на: вытесняющие задачи (как современные операционные системы, такие как Linux) и невытесняющие задачи.
  • Время выполнения, выделяемое каждому процессу, называется временным интервалом.

2. Стратегия планирования

2.1 Интенсивный процессор и интенсивный ввод-вывод

  • Интенсивность ЦП: выполнять код большую часть времени
  • Интенсивный ввод-вывод: отправляйте ввод-вывод и ждите ввода-вывода большую часть времени, часто работоспособный, но очень короткое время выполнения
  • Учитывая скорость отклика системы, стратегия планирования Linux более склонна сначала планировать процессы с интенсивным вводом-выводом.

2.2 Приоритет процесса

  • Самый простой тип алгоритма планирования: планирование на основе приоритетов, идея градации в соответствии со значением процесса и его потребностью в процессорном времени.
  • Планировщик всегда выбирает процесс, запущенный временной средой и наивысший приоритет.
  • Linux реализует алгоритм планирования, основанный на динамическом приоритете. Установите базовый приоритет в начале, а затем динамически увеличивайте или уменьшайте приоритет в соответствии с потребностями: если время ожидания процесса ввода-вывода превышает время выполнения, он является интенсивным вводом-выводом и будет увеличивать приоритет; наоборот, если время процесса фрагмент не заканчивается, он загружает процессор и снижает приоритет
  • Linux предоставляет два отдельных набора диапазонов приоритетов:
    • хорошее значение: -20~19, по умолчанию 0. Стандартный диапазон приоритетов. Чем выше значение, тем ниже приоритет и короче интервал времени. Поле static_prio в task_struct указывает
    • Приоритет в реальном времени: 0~99

2.3 Временной интервал

  • Указывает, как долго процесс может продолжать работать, прежде чем будет вытеснен
  • Политика планирования должна указать нарезку времени по умолчанию. Если это слишком долго, интерактивный ответ не будет хорошо работать; если оно слишком короткое, оно значительно увеличит время процессора, вызванного переключением процессов.
  • Многие системы имеют очень короткий временной интервал по умолчанию: 20 мс.
  • Linux предоставляет механизм для динамической настройки приоритета и длины временного интервала, что делает производительность планирования стабильной и надежной.
  • Процесс не должен использовать временной интервал за один раз, его можно использовать несколько раз, чтобы гарантировать, что он может работать как можно дольше.

2.4 Вытеснение процесса

  • Когда процесс находится в состоянии TASK_RUNNING, ядро ​​проверяет, выше ли его приоритет, чем запущенный процесс, и если он удовлетворен, планировщик пробуждается, и процесс выбирается для повторного запуска.
  • Когда квант времени процесса равен 0, он будет вытеснен, и планировщик может выбрать новый процесс для выполнения.

3. Алгоритм планирования

3.1 Обзор

  • определение планировщика linux с помощью kernel/sched.c
  • Версия ядра 2.5 переписывает алгоритм планирования, который сильно отличается от предыдущей версии, и достигает следующих целей.
    • Полностью реализовать планирование O (1), каждый алгоритм может выполняться за постоянное время независимо от количества процессов или входных данных.
    • У каждого процессора своя блокировка и своя исполняемая очередь
    • Попробуйте назначить тот же набор задач для одного и того же процессора для непрерывного выполнения для уменьшения движущихся процессов между процессорами
    • Улучшенная интерактивная производительность для обеспечения быстрого отклика системы даже при ее нагрузке.
    • Гарантия честности. Устраните голодные потоки и сократите количество процессов, требующих кванта времени.

3.2 Исполняемая очередь

  • Исполняемая структура данных очереди находится в очереди выполнения в файле kernel/sched.c.
  • Представляет связанный список исполняемых процессов на данном процессоре, по одному на каждый процессор.
  • Исполняемая очередь — это структура данных в основе планировщика, и для получения этого указателя предусмотрено множество макросов.
    • cpu_rq (процессор): возвращает указанный указатель исполняемой очереди процессора.
    • this_rq: текущий указатель исполняемой очереди процессора
    • task_rq: указатель на очередь, в которой находится данная задача
  • При работе с очередью необходимо заблокировать очередь и заблокировать функцию
    • task_rq_lock
    • task_rq_unlock
    • this_rq_lock
    • this_rq_unlock
    • double_rq_lock
    • double_rq_unlock

3.3 Массив приоритетов

  • Каждая исполняемая очередь имеет два массива приоритетов, один активный и один с истекшим сроком действия.
  • Структура данных — это prio_array в файле kernel/sched.c.
  • Структура данных, обеспечивающая алгоритмическую сложность уровня O(1).
  • Массив приоритетов делает так, чтобы каждый приоритет исполняемого процессора содержал соответствующую очередь, содержащую связанный список исполняемых процессов с этим приоритетом.
  • Массив приоритетов также имеет растровое изображение приоритета, помогающее эффективно запрашивать исполняемый процесс с наивысшим приоритетом.
  • MAX_PRIO: количество приоритетов в системе, по умолчанию 140.
  • BITMAP_SISE: размер массива растровых изображений приоритетов, unsigned long составляет 32 бита, для представления 140 приоритетов требуется 5 длинных целых чисел, всего 160 бит.
  • Каждый массив приоритетов должен содержать элемент растрового изображения. В начале все битовые карты равны 0. Когда начинает выполняться процесс с приоритетом, соответствующая битовая карта становится равной 1, а поиск с наивысшим приоритетом становится первым значением битовой карты поиска, равным 1, а время поиска остается постоянным. Функция sched_find_first_bit
  • Чтобы найти задачу с заданным приоритетом и опросом, просто перейдите к списку приоритетов
  • nr_active указывает количество исполняемых процессов в массиве приоритетов

3.4 Пересчет кванта времени

  • Когда все кванты времени потока израсходованы, старая версия Linux пересчитывает квант времени путем вычисления циклического обхода.
  • Новая версия планировщика поддерживает два массива приоритетов: активный массив и массив с истекшим сроком действия.Поток, время истечения которого истекло, помещается в массив с истекшим сроком действия, а квант времени массива с истекшим сроком действия вычисляется асинхронно. Наконец, просто поменяйте местами два массива

3.5 Вычислительный приоритет и квант времени

Динамический расчет приоритета

  • После того, как статический приоритет указан пользователем, его нельзя изменить, то есть введенное ранее значение nice
  • Динамический приоритет рассчитывается на основе статического приоритета и функции интерактивности процесса.
  • Функция Effective_prio возвращает динамический приоритет процесса: функция берет значение nice в качестве основы, а затем добавляет значение вознаграждения и наказания (от -5 до 5) в соответствии со степенью взаимодействия.
  • Обмен оценкой степени: вычислить время выполнения и время ожидания процесса. Переменная sleep_avg в task_struct, по умолчанию 10 мс, увеличьте это значение (продолжительность сна) во время сна и уменьшите это значение при работе.

Динамический расчет временных интервалов

  • При создании процесса родительский и дочерний процессы делят квант времени поровну. Предотвратите создание нескольких процессов, чтобы получить больше процессорного времени
  • Когда квант времени задачи истекает, квант времени рассчитывается в соответствии с задачей с динамическим приоритетом. Функция task_timeslice. Значение приоритета значения времени масштабируется. До 200 мс, минимум 10 мс, по умолчанию 100 мс
  • Если высокоинтерактивный процесс (макрос TASK_INTER_ACTIVE) после того, как квант времени будет израсходован, он будет снова помещен в активный массив вместо массива с истекшим сроком действия. Избегайте необходимости взаимодействовать и не выполнять, потому что он не ждет, пока два массива будут заменены местами. Код реализации: функция scheduler_tick

3.6 Сон и пробуждение

  • Бездействующий поток входит в очередь ожидания, которая содержит простой связанный список всех процессов, ожидающих определенных событий.
  • Структура данных очереди ожидания — wake_queue_head_t.
  • Ожидание создания очереди: DECLEAR_WAITQUEUE или init_waitqueue_head
  • Присоединяйтесь к очереди ожидания: add_wait_queue
  • Когда очередь ожидания, связанная с инцидентом, процесс очереди будет пробужден, функция, использующая wake_up

3.7 Балансировщик нагрузки

  • Балансировщик нагрузки предназначен для несбалансированной загрузки исполняемых программ в многопроцессорной системе.
  • Это функция load_balance в файле kernel/sched.c.
  • Время вызова: когда исполняемая очередь пуста, она будет вызываться регулярно (каждую 1 мс, когда система простаивает, и каждые 200 мс в других случаях). Эта функция не требуется для однопроцессорных систем.
  • Когда вызывается балансировка нагрузки, текущая очередь должна быть заблокирована, а прерывания экранированы.
  • шаги операции load_balance:
    • Позвоните Find_busiest_Queue, чтобы найти самую загруженную очередь. Очередь имеет наибольшее количество процессов. Если нет более 25% текущей очереди, просто заканчивается и вернуться
    • Выберите массив приоритетов из очереди занятости, чтобы использовать его для извлечения процессов, предпочтительно массив с истекшим сроком действия.
    • Обращается к связанному списку с наивысшим приоритетом (наименьшее значение) и распределяет высокоприоритетные процессы.
    • Найдите процесс в связанном списке, который не выполняется, может быть перемещен и не находится в кеше, и используйте pull_task для извлечения процесса в текущую очередь.
    • Описанные выше шаги выполняются всякий раз, когда очередь несбалансирована. Наконец, отпустите замок.

4. Упреждение и переключение контекста

4.1 Обзор

  • Переключение контекста переключается с одного процесса на другой.
  • Переключение контекста определено в функции context_switch в файле kernel/sched.c, которая выполняет две основные задачи.
    • Вызов switch_mm, определенный в include/asm/menu_context.h, отвечает за переключение виртуальной памяти из предыдущего сопоставления процесса в новый процесс.
    • Вызов switch_to, определенный в include/asm/system.h, отвечает за переключение из состояния процессора предыдущего процесса в состояние процессора нового процесса. Включая сохранение, восстановление информации о стеке и информацию о регистрах.
  • Ядро предоставляет флаг need_resched, чтобы указать, требуется ли повторное планирование. Schedule_tick устанавливает этот флаг, когда процесс исчерпал временной интервал; try_to_wake_up также устанавливает этот флаг, когда высокоприоритетный процесс переходит в исполняемое состояние.
  • Каждый процесс включает флаг need_resched

4.2 Преимущество пользователя

  • Пользовательское вытеснение: когда ядро ​​​​возвращается в пространство пользователя, если установлено need_reshed, вызывающее вызов расписания, для выполнения будет выбран более подходящий процесс.
  • Вытеснение пользователя происходит, когда:
    • Возврат в пространство пользователя из системного вызова
    • Возврат в пространство пользователя из обработчика прерывания

4.3 Преимущество ядра

  • Большинство других вариантов Unix и большинство операционных систем не поддерживают вытеснение ядра, код ядра должен выполняться до завершения.
  • 2.6 Версия ядра, добавлено упреждение ядра. Пока перераспределение безопасна, вы можете проверить ядро
  • Пока блокировка не удерживается, перепланирование безопасно и может быть вытеснено ядром.
  • Удержание блокировки представлено счетчиком preempt_count в thread_info. Значение увеличивается на единицу, когда блокировка используется, и значение уменьшается на единицу, когда блокировка снимается.
  • Вытеснение ядра происходит, когда:
    • При возврате в пространство ядра из обработчика прерывания
    • Когда код ядра снова становится вытесняемым
    • Задача в ядре показывает вызов по расписанию
    • Блокировка задач в ядре

5. Системные вызовы, связанные с планированием

  • sched_setscheduler: установить политику и значения rt_priority для task_struct
  • sched_setaffinity: установить флаг битовой маски cpus_allowed для task_struct
  • sched_yield: переместите процесс из активной очереди в очередь с истекшим сроком действия, чтобы сократить время выполнения.

4. Системный вызов

1 Обзор

  • Системные вызовы обеспечивают интерфейс для взаимодействия между ядром и приложением.
  • Внутри системного вызова asmlinkage должен быть добавлен к объявлению функции, чтобы сообщить время компиляции, чтобы извлекать только параметры функции из стека.
  • Системные вызовы имеют префикс sys_ в ядре.
  • Каждый системный вызов в Linux связан с уникальным номером системного вызова.
  • Ядро записывает список всех зарегистрированных системных вызовов в таблицу системных вызовов, которая хранится в sys_call --table, связанной с архитектурой.
  • Дизайн ядра Linux оптимизирован и лаконичен, время переключения контекста чрезвычайно быстрое, а эффективность выполнения операционной системы высока.

2. Обработчик системных вызовов

  • Пользовательские программы не могут напрямую вызывать функции ядра, чтобы предотвратить выход из-под контроля безопасности пространства ядра. Вместо этого ядро ​​уведомляется прерыванием, и ядро ​​выполняется от имени программы.
  • Перед запуском мягкого прерывания загрузите номер вызова в регистр eax.
  • Передача параметров: В системах x86 ebx, ecx, edx, esi и edi сохраняют первые пять параметров по порядку. Возвращаемое значение возвращается через регистр eax
  • Функции копирования пространства ядра и пространства пользователя: copy_to_user, copy_from_user

3. Контекст системного вызова

  • Текущий указатель указывает на процесс, вызвавший текущий вызов
  • В контексте процесса при выполнении системного вызова
  • В контексте процесса ядро ​​может находиться в спящем режиме (блокировка вызовов или расписание) и может быть вытеснено

4. Реализация системных вызовов

  • Linux не поддерживает многоцелевые системные вызовы, каждый системный вызов должен иметь четкую цель.
  • Интерфейс должен быть максимально лаконичным с небольшим количеством параметров. Стремитесь к стабильности, не внося изменений
  • Старайтесь думать о будущем, старайтесь быть как можно более общим и не ограничивайте его. «Предлагайте механизмы, а не тактику»
  • После написания его нужно зарегистрировать в ядре и стать реальным доступным системным вызовом
    • Лучше всего добавить запись в системный вызов. Большинство из них находятся в файле entry.s. Все аппаратные системы, поддерживающие системные вызовы, должны быть
    • Системный номер вызова определен для включения файла /asm/unist.h
    • Функция помещается в папку под файлом ядра, поэтому она скомпилирована в образ ядра (не может быть скомпилирована как модуль)
  • Как пользовательское пространство получает доступ к зарегистрированным системным вызовам
    • Обычно пользователи могут использовать системные вызовы, включив стандартные заголовочные файлы и связав их с конкретной реализацией C базовых системных вызовов.
    • Пользовательский системный вызов не существует в файле заголовка флага, и его можно вызвать с помощью макроса, предоставленного linux: _syscalln, n представляет параметры, которые необходимо передать. Макрос имеет 2+2n параметров, первый представляет тип возвращаемого значения, второй представляет имя функции, за которым следуют n типов параметров и имена параметров.
    • Например: системный вызов функции open, номер системного вызова _NR_open, который определен в и внутренне реализован макросом _syscall3.При вызове open макрос напрямую помещается в код приложения.

V. Прерывания и обработчики прерываний

1. Прерывание

  • Прерывания используются для решения проблемы несоответствия скорости обработки процессора компьютера и аппаратного устройства.После того как аппаратное обеспечение обработало задачу, оно активно посылает сигнал процессору.
  • Прерывание — это, по сути, электрический сигнал, который генерируется аппаратным устройством и отправляется на входной контакт обработчика прерывания. Затем контроллер прерываний посылает сигнал процессору. Процессор получает сигнал и прерывает работу, чтобы обработать прерывание
  • Каждое прерывание уникально идентифицируется в цифровом виде и называется линией запроса на прерывание (IRQ). Например: IRQ0 — прерывание часов, IRQ1 — прерывание клавиатуры.

2. Обработчик прерываний

  • При ответе на определенное прерывание функция, которая выполняется, является обработчиком прерывания или подпрограммой обслуживания прерывания.
  • Желевые обработчики прерывания являются частью драйвера устройства, который является кодом ядра, используемого для управления устройством
  • Отличие от функции ядра: обработчик прерывания вызывается ядром для ответа на прерывание, работая в контексте прерывания.
  • Обработчики прерываний должны выполняться быстро, и в то же время мы полагаемся на них при выполнении большого количества другой работы. Эти две цели противоречат друг другу.
  • Для того, чтобы разрешить вышеуказанное противоречие, обработчик прерывания разделен на две половины
    • Верхняя половина: выполнить сразу после получения запроса, но выполнить небольшой объем работы. Подтверждение прерывания и аппаратный сброс
    • Нижняя половина: выполнить, как только обработчик прерывания вернется

3. Зарегистрируйте обработчик прерывания

  • IRQ: номер прерывания должен быть назначен
  • обработчик: Фактический обработчик прерывания. Принимает три параметра и возвращает параметр типа irqreturn_t
  • irqflags: может быть 0 или битовой маской следующих флагов
    • SA_INTERRUPT: Указывает, что это программа быстрого прерывания. В основном используется для процедур прерывания часов
    • SA_SAMPLE_RANDOM
    • SA_SHIRQ: общая линия прерывания
  • devname: текстовое имя устройства, связанного с прерыванием, в кодировке ASCII, например, «клавиатура» в середине клавиатуры.
  • dev_id: используется для общих линий прерывания
  • Эта функция может быть бездействующей, код не может быть вызван в контексте прерывания или не позволяет блокировать

4. Механизм обработки прерываний

  • Устройство генерирует прерывание и отправляет электрический сигнал на контроллер прерываний.
  • Контроллер прерываний посылает сигнал процессору
  • Процессор прерывает программу и переходит в предопределенное место в памяти для выполнения. является точкой входа программы прерывания
  • Ядро вызывает do_IRQ для ответа на прерывание.
  • Соответствующие функции находятся в arch/i386/kernel/entry.s, arch/i386/kernel/irq.c.

5 Управление прерываниями

  • Linux предоставляет набор интерфейсов для управления статусом прерывания на машине, предоставляя возможность отключить систему прерывания или экранировать линию прерывания.
  • Соответствующий код находится в ,
  • Корень управления прерываниями заключается в обеспечении синхронизации.Отключение прерываний гарантирует, что программа прерывания не вытесняет текущий код, а ядру также можно запретить вытеснение
  • Отключить и включить текущие прерывания процессора: local_irq_disable, local_irq_enable
  • Отключить (защитить) назначенную линию прерывания: disable_irq, disable_irq_nosync, enable_irq, synchronize_irq
  • Получает систему прерывания Статус: ASM / SYSTEM.h В IRQS_DISAL
  • Определите, находится ли он в контексте прерывания: in_interrupt в asm/hardirq.h

6. Синхронизация ядра

1. Основные понятия

  • Критическая секция: секция кода, которая обращается к общим данным и управляет ими.
  • Состояние гонки: несколько потоков выполнения в одном и том же критическом разделе.
  • Синхронизация: избегание параллелизма и предотвращение условий гонки
  • Зачем нужна синхронизация: пользовательские программы вытесняются и перепланируются планировщиком
  • Причины одновременности следующие:
    • прерывать
    • вытеснение ядра
    • Синхронизация сна и пользовательского пространства
    • мультипроцессор
  • Решение проблем с синхронизацией: блокировка
  • Какие данные нужно заблокировать
    • глобальные переменные ядра
    • общие данные
  • Тупик; все потоки ждут друг друга, чтобы снять блокировку, и ни один поток не может продолжить работу.

2. Метод синхронизации ядра

2.1 Атомарные операции

  • Атомарные операции гарантируют, что инструкции выполняются атомарно.
  • Атомарные операции обычно являются встроенными функциями, которые выполняются с помощью встроенных ассемблерных инструкций.
  • Атомарные операции дают системе меньше накладных расходов, чем другие методы синхронизации.
  • Ядро Linux обеспечивает атомарные операции над целыми числами и отдельными битами.
  • Функции, связанные с целочисленными атомарными операциями, находятся в файле asm/atomic.h.
  • Функции, связанные с битовыми атомарными операциями: asm/bitops.h

2.2 Замок самоворота

  • Spin Lock может удерживаться только одним исполняемым потоком. Если замок не занят, нить можно получить сразу. Если он занят, он всегда будет зациклен на доступном замке.
  • Спин-блокировки можно использовать для предотвращения одновременного входа нескольких потоков в критическую секцию.
  • Вращение особенно расточительно для процессора, поэтому его не следует удерживать в течение длительного времени.
  • Интерфейс определен в , а конкретная реализация, связанная с архитектурой, находится в .
  • Рекурсия недоступна для спин-блокировок в Linux.
  • Использование спин-блокировок
    spinlock_t mr_lock = SPIN_LOCK_UNLOCKED;
    //普通请求锁
    spin_lock(&mr_lock);
    //禁止中断请求锁
    spin_lock_irqsave(&mr_lock);
    //确保中断是激活的情况可用的方法
    spin_lock_irq(&mr_lock)
    /**临界区**/
    spin_unlock_irq(&mr_lock)
    spin_unlock_irqrestore(&mr_lock);
    spin_unlock(&mr_lock)
    
  • Спин-блокировки можно использовать в обработчиках прерываний (семафор не годится, он вызовет сон), перед использованием блокировок локальные прерывания должны быть отключены, иначе это вызовет взаимоблокировку

2.3 Чтение и запись спин-блокировок

  • Использование блокировки можно четко разделить на блокировку чтения и блокировку записи.
  • Одна или несколько задач чтения могут одновременно удерживать блокировки чтения.
  • Блокировка, используемая для записи, может удерживаться только одной задачей записи, и одновременное чтение в настоящее время невозможно.
  • Использование блокировки чтения-записи
    rwlock_t mr_rwlock = RW_LOCK_UNLOCKED;
    read_lock(&mr_rwlock);
    /**只读临界区**/
    read_unlock(&mr_rwlock)
    
    write_lock(&mr_rwlock)
    /**读写临界区**/
    write_unlock(&mr_rwlock)
    
  • Обновление не может читать замки для записи блокировков, приведет к тупику

2.4 Семафор

  • Семафор — это блокировка сна
  • Разрешить любое количество держателей замков одновременно
  • Когда количество семафоров равно 1, он называется бинарным семафором или семафором взаимного исключения.
  • Если задача пытается получить доступ к занятому семафору, семафор помещает его в очередь ожидания, переводя его в спящий режим. Когда процесс, удерживающий семафор, освобождается, ожидающая задача пробуждается и семафор получается.
  • Характеристики семафоров
    • Подходящий чехол блокировки будет проходить в течение длительного времени
    • Блокировка удерживается в течение короткого времени, и время сна может быть больше, чем полное время
    • будет спать и не может быть вызван в прерывании
    • Спин-блокировка не может удерживаться, когда удерживается семафор. Спинлоки не позволяют спать
  • Семафор поддерживает две атомарные операции P и V, голландский зонд и приращение.
  • Файлы, связанные с семафором:
  • использовать семафор
    //声明信号量
    static DECLARE_SEMAPHORE_GENERIC(name, count);
    //声明互斥量
    static DECLARE_MUTET(name);
    
    //以指针方式初始化信号量
    sema_init(sem, count);
    //以指针方式初始化互斥量
    init_MUTET(sem);
    
    //试图获得信号量
    down_interruptible(&name)
    //释放信号量
    up(&name)
    

2.5 Чтение и запись семафоров

  • то же, что блокировка чтения-записи
  • Связанные файлы:

2.6 Полные переменные

  • Предоставляет простой обходной путь вместо семафора
  • Связанные файлы:

2.7 SEQ LOCK

  • Он обеспечивает простой механизм для чтения и записи общих данных
  • Внутренне реализует в основном счетчик последовательности
  • Инициализация блокировки 0. При записи данных блокировка будет получена, а значение последовательности увеличится. До и после чтения данных считывается порядковый номер, если он одинаковый то не прерывается, если четный то операция записи не происходит

2.8 Барьеры

  • Барьеры обеспечивают выполнение инструкций по порядку и запрещают изменение порядка инструкций.
  • Изменение порядка происходит потому, что современные процессоры нарушают порядок, в котором инструкции отправляются и фиксируются, чтобы оптимизировать их конвейер передачи.
  • Метод rmb обеспечивает барьер «чтения» памяти, загрузки перед rmb не ставятся в очередь после rmb, и наоборот.
  • Метод wmb обеспечивает барьер «записи» в память, и операции сохранения перед wmb не ставятся в очередь после wmb.
  • Метод mb обеспечивает барьер «чтение-запись».

7. Управление памятью

1. Ядро управления памятью

1,1 страницы

  • Ядро рассматривает физические страницы как основную единицу управления памятью.
  • Блок управления памятью: MMU, аппаратное обеспечение, которое управляет памятью и преобразует виртуальные адреса в физические адреса.
  • Размер страницы зависит от архитектуры.Большинство 32-разрядных архитектур поддерживают страницы размером 4 КБ, а 64-разрядные архитектуры поддерживают страницы размером 8 КБ.
  • Структура данных физической страницы находится в struct page в . страница связана с физическими страницами, а не с виртуальными страницами
    sturct page{
       unsigned long                flags; // 页的状态,是否脏,是否被锁定。可表示32种状态。定义与<linux/page-flags.h>
       atomic_t                     count; // 页的引用计数,被使用了多少次。为0时,新的分配就可以使用它 
       struct list_head             list;
       struct address_space         *mapping; //指向与该页有关的address_space对象
       unsigned long                index; 
       struct list_head             lru;
       union{
           struct pte_chain *chain;
           pte_addr_t   direct;
       }pte;
       unsigned long                private;
       void                         *virtual; //页虚拟地址,虚拟内存地址
    }
    

1.2 Зона

  • Из-за аппаратных ограничений некоторые страницы располагаются по определенным физическим адресам в памяти и не могут использоваться для конкретных задач, поэтому они также разделены на разные зоны.
  • Страницы группы зон со схожими характеристиками. Разделение области не имеет физического смысла, оно используется только для управления логической группировкой страниц.
  • Linux использует три типа областей:
    • ZONE_DMA: зона, которая может выполнять DMA (прямой доступ к памяти).
    • Zone_Normal: зона, которая может быть отображена нормально
    • ZONE_HIGHEM: «более высокая память», которую нельзя постоянно отображать в адресное пространство ядра.
  • Структура данных зоны находится в struct zone файла .

2. Интерфейс, связанный со страницей

  • Ядро предоставляет низкоуровневый механизм запроса памяти и предоставляет интерфейсы доступа. Интерфейсы выделяют память со страницами как Праздник лодок-драконов. Определение такое же, как в
    // 分配2^order个连续的物理页,并返回指针
    struct page* alloc_pages(unsigned int gfp_mask, unsigned int order)    
    // 将页转换为逻辑地址,页是连续的,其他页紧随其后
    unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order)
    
    // 只获取一页,高端地址分配需要使用此函数
    struct page* alloc_page(unsigned int gfp_mask)    
    unsigned long get_free_page(unsigned int gfp_mask)
    
    //获取填充内容为0的页
    unsigned long get_zeroed_page(unsigned int gfp_mask)
    
    //释放页
    void __free_pages(struct page *page, unsigned int order)
    void free_pages(unsigned long addr, unsigned int order)
    void free_page(unsigned int order)
    
    // 与用户空间的malloc函数类似,最通用的接口。提供用于获得以字节为单位的一块内核内存
    // 定义与<linux/slab.h>中
    void *kmalloc(size_t siez, int flags)
    // kmalloc相反函数,释放空间
    void kfree(const void *ptr)
    
    // 确保分配的页在物理地址上是连续的
    // 定义与<linux/vmalloc.h>
    void* vmalloc(unsigned long size)
    //释放空间
    void vfree(void *addr)
    
  • Флаг gfp_mask в разделен на три категории: модификаторы поведения, модификаторы области и типы.
    • Модификаторы поведения: как ядро ​​выделяет требуемую память
    • Модификаторы области: откуда выделить память
    • Тип: комбинированный модификатор поведения и модификатор области

3. slab

  • Slab обеспечивает роль уровня кэша общей структуры данных, slab будет поддерживать объект для каждого процессора, чтобы сообщить кэшу (бесплатный список)
  • Подходит для больших структур данных, которые необходимо создавать и уничтожать
  • Слой slab делит разные объекты на так называемые группы кеша, в каждой из которых хранятся разные типы объектов (каждый тип объекта соответствует кешу)
  • Каждый блок находится в одном из трех состояний: медленный, частичный или пустой.
  • Несколько SALB составляют кэш, различные структуры данных:
    • Плита: структурная плита
    • Кэш: kmem_cache_s
    • Полный связанный список: slabs_full
    • Частично связанный список: slabs_partial
    • Пустой связанный список: slabs_empty

4. Отображение высокопроизводительной памяти

  • Страница памяти верхнего уровня не может быть постоянно отображена в адресное пространство ядра, поэтому страница, полученная с помощью некоторого флага, не является логическим адресом.
  • В системах x86 страницы в верхней памяти сопоставляются с логическими адресами 3–4 ГБ.
  • Отображение связанных интерфейсов:
    //映射一个给定的page结构到内核地址空间:
    void kmap(sturct page *page)
    
    //解除映射关系
    void kunmap(struct page* page)
    
    //临时映射
    void *kmap_atomic(sturct page *page, enum km_type type)
    

8. Виртуальная файловая система

1. Основные понятия

  • Виртуальная файловая система: VFS, которая предоставляет интерфейс файловой системы. Через VFS вы можете использовать стандартную файловую систему unix для вызова разных файлов на разных носителях для работы.
  • Linux поддерживает довольно много файловых систем (более 50):
    • Локальная файловая система: ext2, ext3
    • Сетевые файловые системы: NFS, Coda
  • В VFS есть четыре основных типа объектов.
    • сверхбыстрый объект, представляющий смонтированную файловую систему
    • Объект Inode, представляющий файл
    • Объект ввода каталога, представляющий запись каталога
    • Файловый объект, представляющий файл, открытый процессом

2. Суперблочный объект

  • Различные файловые системы должны реализовывать суперблоки, которые используются для хранения информации о конкретной файловой системе, обычно соответствующие блокам управления файловой системой, хранящимся в определенных секторах диска.
  • Структура данных суперблока определяется с помощью super_block в .
  • s_op в суперблоке указывает на таблицу функций сверхбыстрых операций, которая представлена ​​структурой super_operation. Когда файловая система работает с суперблоком, она находит соответствующий метод операции.
  • То есть информация о разных файловых системах предоставляется VFS путем регистрации собственного метода для операций с файловой системой в super_operation.
  • Связанный со сверхбыстрым кодом код находится в

3. Инод объект

  • Объект inode содержит всю информацию, необходимую ядру для работы с файлом или каталогом.
  • Структура данных объекта inode находится в struct inode в .
  • Представляет файл в файловой системе (включая обычные файлы, каналы и т. д.)
  • Элемент inode_operations в айноде также очень важен, определяя все методы работы с объектом айнода.

4. Объект элемента каталога

  • Записи каталога включают выполнение операций, связанных с каталогом, таких как поиск пути и т. д.
  • Структура данных записи каталога находится в struct dentry в .
  • Статус элемента каталога включает в себя: используется, не используется и отрицательный статус
  • Элементы каталога также включают кэши элементов каталога, в том числе:
    • Список ожерелий из каталога б/у
    • Недавно используется вдвойне связанный список
    • Hash Tables и соответствующие хеш-функции используются для быстрого разрешения заданного пути в связанные объекты ввода каталогов
  • Операции входа в каталог определены в структуре dentry_operation, расположенной в .

5. Файловый объект

  • Определение файлового объекта и структурная файловая структура в
  • Файловые операции представлены структурой file_operations.
  • Конкретные файловые системы определяют разные реализации

6. Другие структуры данных

  • Структуры данных, связанные с файловой системой: struct file_system_type, описывающая конкретный тип файловой системы, такой как ext3 или XFS.
  • Пример смонтированной файловой системы: vfsmount,
  • Данные, на которые указывают файлы дескриптора процесса, включая такую ​​информацию, как открытые файлы и дескрипторы файлов, связанные с процессом: struct files_struct,
  • Данные, на которые указывает fs дескриптора процесса, включая файловую систему и информацию о процессе: struct fs_struct,
  • Данные, на которые указывает пространство имен дескриптора процесса, включая информацию о пространстве имен: struct namespace,

9. Уровень блока ввода-вывода

1. Основные понятия

  • К основным типам устройств относятся: блочное устройство, символьное устройство. Разница в том, можно ли получить к нему доступ случайным образом
  • Наименьшая адресуемая единица в блочном устройстве — это сектор, а размер сектора обычно кратен 2. Наиболее распространенный размер — 512 байт.
  • Физические диски адресуются в секторах, доступ к файловым системам осуществляется в блоках, а блоки представляют собой более высокий уровень абстракции.
  • Блок содержит один или несколько секторов, но не больше, чем размер страницы
  • Когда блок вызывается в память, его необходимо загрузить в буфер сначала, и каждый буфер соответствует блоку
  • Каждый буфер имеет дескриптор, представленный структурой buffer_head, называемой заголовком буфера. в файле . Включая состояние буфера, количество использований, номер логического блока, физическую страницу, размер блока и т. д.

2. bio

  • В настоящее время основным контейнером блочных операций ввода-вывода в ядре является структура bio, расположенная в

3. Планировщик ввода-вывода

10. Адресное пространство процесса

1. Основные понятия

  • Каждый процесс имеет уникальное адресное пространство, взаимные помехи друг другу
  • Процесс может обращаться только к адресам памяти в допустимом диапазоне.
  • Область памяти содержит различные объекты памяти, в том числе:
    • Фрагмент кода: карта памяти исполняемого кода
    • сегмент данных: карта памяти инициализированных глобальных переменных
    • Сегмент BSS: глобальная переменная не инициализирована
    • разное

2. Дескриптор памяти

  • Ядро использует дескриптор памяти представляет собой адресное пространство процесса.
  • Структура данных дескриптора памяти находится в mm_struct в .
  • Внутренние структуры данных mmap и mm_rb представляют одно и то же содержимое, которое здесь избыточно. Первый представляет собой связанный список, по которому легко и эффективно перемещаться, а второй представляет собой красно-черное дерево, удобное для эффективного поиска.
  • Структура mm_struct, имеющая блокировку, связана в двусвязном списке через собственный список mmlist, процесс инициализации первого элемента, дескриптор init_mm. При работе со связанным списком используйте mmlist_lock для блокировки, блокировка находится в
  • Поле mm в дескрипторе процесса хранит дескриптор памяти
  • Назначить дескриптор памяти: COPY_MM, внутренний вызов allocate_mm распределения макросов из slab-кэша mm_cachep
  • Поток ядра не имеет адресного пространства процесса, а поле MM пусто.

3. Область памяти

  • Область памяти представлена ​​структурой vm_area_struct, определенной в , также называемой областью виртуальной памяти.
  • vm_area_struct описывает независимый диапазон памяти в непрерывном пространстве в указанном адресном пространстве.
  • vma включает в себя множество флагов, которые отмечают поведение и информацию содержащихся страниц.
    • VM_READ: разрешение на чтение страницы
    • VM_WRITE: разрешение на запись страницы
    • VM_EXEC: Страница исполняемых разрешений
  • vm_ops структуры vm_area_struct указывает на таблицу функций операций, относящуюся к указанной области памяти, которая представлена ​​vm_operations_struct.

11. Кэш страницы и обратная запись страницы

1. Основные понятия

  • Кэш страницы — это своего рода дисковый кеш, реализованный Linux, который в основном используется для уменьшения операций ввода-вывода на диске.
  • При кэшировании данных на диске в физической памяти доступ к диску заменяется доступом к физической памяти.
  • Значение дискового кеша:
    • Более быстрый доступ, память быстрее, чем диск
    • Временный локальный принцип: после доступа к данным, скорее всего, к ним снова будут обращаться в краткосрочной перспективе.
  • Перед выполнением операции io ядро ​​проверит, есть ли данные уже в страничном кеше, и если да, то может сразу вернуться

2. Структура данных кэша страниц

  • Кэш страниц использует структуру address_space для описания страниц в кеше страниц, как определено в .
  • Внутренний a_ops указывает на таблицу функций операций в объекте адресного пространства, который представлен структурой address_space_operations.
  • Проверка того, находится ли страница в кеше, должна быть эффективной, система счисления, предоставляемая каждой структурой address_, двоичное дерево дерева страниц, записывает смещение файла. с целью быстрого поиска. Код radix-tree находится в

3. Страница запишите обратно

  • Фоновая процедура pdflush отвечает за запись грязных страниц памяти обратно на диск.
    • Свободная память падает ниже определенного значения, чтобы освободить память. Порог настраивается
    • Время пребывания грязной страницы превышает определенное значение
    • Периодическая обратная запись для предотвращения ненормальной потери данных в системе
  • Код pdflush находится в . Код механизма обратной записи находится в , .

12. Другие

Таймеры и управление временем

  • Периодическое время управляется системным таймером, который представляет собой программируемую аппаратную микросхему, которая может генерировать прерывания с фиксированной частотой (прерывания таймера).
  • Фактическое время: определено в . struct timespec xtime, структура данных timespec определена в файле
  • Таймер: определен в структурой time_list.