Реализация быстрых механизмом синхронизации в пространстве пользователя напримере системного вызова futex() в ядре Linux.

Заказать уникальную курсовую работу
Тип работы: Курсовая работа
Предмет: Программирование
  • 2222 страницы
  • 4 + 4 источника
  • Добавлена 06.12.2013
800 руб.
  • Содержание
  • Часть работы
  • Список литературы
  • Вопросы/Ответы
Оглавление
Используемые сокращения 3
Введение 3
Часть 1 Исследование механизмов синхронизации в Операционных системах 4
Часть 2 Реализация быстрых механизмов синхронизации в пространстве пользователя на примере системного вызова futex() 16
Заключение 20
Список использованных источников 21
Приложения 22
Фрагмент для ознакомления

В конечном итоге, sys_ni_syscall занимает все неиспользуемые позиции в конце таблицы; это устанавливается в строках с 572 по 574, которые повторяют элемент необходимое количество раз с целью заполнения таблицы. Поскольку sys_ni_syscall просто возвращает код ошибки ENOSYS, обращение к sys_ni_syscall эквивалентно переходу на метку badsys в рамках system_call, таким образом эффект от использования номера системного вызова, расположенного в данных позициях таблицы, такой же как и в случае применения номера, лежащего за пределами таблицы. Следовательно, системные вызовы можно добавлять в таблицу (или удалять из нее) без изменений NR_syscalls, тем не менее, эффект будет таким, как если бы вносились изменения в NR_syscalls (во всяком случае, в рамках установленных пределов). Буквосочетание «ni» в имени sys_ni_syscall означает ни что иное, как «notimplemented» (не реализовано).В этой простой функции присутствует дескриптор asmlinkage, относящийся к специфике компилятора gcc. Он уведомляет компилятор, что функция не будет искать свои аргументы в регистрах (случай общепринятой оптимизации), поскольку она ожидает их в стеке ЦП. Вспомните последнее утверждение о том, что system_call работает с собственными первыми четырьмя аргументами, номером системного вызова и допускает до четырех дополнительных аргументов, которые передаются реальному системному вызову. Такое достигается за счет оставления своих аргументов (передаваемых в регистрах) в стеке. Все системные вызовы помечаются дескриптором asmlinkage, поэтому они ищут аргументы в стеке. Разумеется, что в случае с sys_ni_syscall это ничего не меняет, поскольку sys_ni_syscall не принимает каких-либо аргументов. Теперь-то вы уже знаете, о чем идет речь, когда перед функциями присутствует asmlinkage.sys_time31394: sys_time представляет собой простой системный вызов, иллюстрирующий несколько важных концепций. Он реализует системный вызов time, который возвращает количество секунд, прошедших от полночи по универсальному времени 1 января 1970 г. Это число хранится в поле глобальной переменной xtime (см. строку 26095; она объявлена как volatile, поскольку модифицируется из прерывания, как будет показано в главе 6) и доступ к нему организуется через макрос CURRENT_TIME (см. строку 16598).31400: Функция слепо следует своему простому объявлению. Вначале текущее время сохраняется в локальной переменной i.31402: Если получаемый указатель tloc не равен NULL, значение возврата будет также копироваться в место, определяемое этим указателем. Здесь присутствует одна тонкость — взамен обращения к макросу CURRENT_TIMEпеременная i просто копируется в пользовательское пространство. На то имеются две причины:Определение макроса CURRENT_TIME в будущем может измениться, и эти новые версии могут оказаться более медленными, тогда как доступ к i был, есть и будет самым быстрым из возможных.Подобный подход гарантирует получение непротиворечивых результатов: если так случится, что между строками 31400 и 31402 время изменится, sys_time скопирует одно значение, а вернет другое.Небольшое удивление вызывает то, что эта часть кода не написана с использованием && вместо двух операторов if. Стандартная причина появления в ядре необычно выглядящего кода связана с повышением быстродействия, однако поскольку gcc генерирует одинаковый код для случаев && и двух if, в данной ситуации она не применима, если только упомянутый вид кода не связан со спецификой ранних версий gcc, в которых этот код разрабатывался.31403: Если sys_time не может получить доступ в передаваемое местоположение (чаще всего это связано с некорректным значением tloc), в i заносится -EFAULT и в строке 31405 производится возврат кода ошибки.31405: Возврат значения переменной i, которая содержит либо текущее время, либо -EFAULT.sys_reboot29298: Если и есть в ядре места, способные привести к паранойе, так вот sys_reboot — несомненный лидер в этом отношении. И причина, в общем-то, неплохая: как гласит имя функции, она должна использоваться для перезагрузки компьютера. Кроме того, в зависимости от передаваемых аргументов, эта функция может останавливать компьютер, выключать его питание и разрешать либо запрещать использование комбинации клавиш Ctrl+Alt+Del для перезагрузки. При написании кода, использующего sys_reboot следует соблюдать особую осторожность и принимать во внимание замечание, находящееся выше данной строки кода. Это замечание гласит, что перед обращением кsys_reboot следует обязательно синхронизировать жесткие диски, иначе данные, хранящиеся в дисковом кэше будут потеряны.Принимая во внимание возможные неприятные последствия для системы, sys_reboot требует указания нескольких магических аргументов, которые будут рассматриваться немного позже.29305: В случае игнорирования характеристики CAP_SYS_BOOT (строка 14096) возвращается код ошибки EPERM. Характеристики более подробно обсуждаются в главе 7, а сейчас достаточно упомянуть, что с их помощью реализуется метод проверки допустимых привилегий для конкретного пользователя.29309: А здесь — паранойя во всей своей красе! sys_reboot сравнивает аргументы magic1 и magic2 с магическими числами, определенными в строках с 16002 по 16005. Идея заключается в том, что если функция sys_rebootвызывается случайно, то весьма нежелательно так же случайно получить значения из аргументов magic1 и magic2. Следует заметить, что это не рассматривается как мера по увеличению степени безопасности, но только как защита от небрежного использования.Между прочим, упоминаемые магические числа не выбирались случайным образом. Первое число относительно очевидно — этакий каламбур из «feeldead» (чувствовать себя мертвым). На следующие три числа для максимального эффекта лучше смотреть в шестнадцатиричном виде: 0x28121969, 0x5121996 и 0x16041998. Они выглядят как день рождения супруги Линуса (или, возможно, кого-то из его родственников) и дни рождения двух его дочерей. Соответственно, это наводит на мысль, что с увеличением семьи Линуса, вероятность случайного вызова функции перезагрузки будет стремиться к уменьшению. Однако, я думаю, что жена его остановит до того, как он исчерпает возможности 32-разрядного пространства.29315: Запрос блокировки ядра, поэтому в каждый момент времени данный код будет выполнять только один процессор. Любой другой код, защищенный парой lock_kernel/unlock_kernel, для других процессоров не доступен. Для однопроцессорных компьютеров lock_kernel не делает ничего, действия же функции в случае мультипроцессорной системы описываются в главе 10.29317: В случае LINUX_REBOOT_CMD_RESTART функция sys_reboot обращается к списку функций в reboot_notifier_list, уведомляя их о том, что система перезагружается. В общем случае эти функции представляют собой часть модуля, для которого требуется выполнение определенных действий перед завершением работы системы. Кажется, что этот список не используется где-либо в ядре — по крайней мере, в рамках стандартного дистрибутива; возможно, его используют какие-то внешние модули. Во всяком случае, такой список существует и при необходимости им можно воспользоваться.LINUX_REBOOT_CMD_RESTART и другие значения cmd определяются начиная со строки 16023. Никакого скрытого смысла эти значения не несут; они установлены такими просто потому, что не должны возникать из-за всякого рода случайностей и не должны совпадать с другими значениями. (Самое интересное, что значение LINUX_REBOOT_CMD_CAD_OFF равно 0, а 0 относится как раз таким случайно возникающим значениям. Однако,посколькуLINUX_REBOOT_CMD_CAD_OFF просто запрещает использование комбинации клавиш Ctrl+Alt+Del для перезагрузки системы, случайное возникновение подобной ситуации считается «безопасным».)29321: После вывода предупредительного сообщения sys_reboot вызывает machine_restart (строка 2185) для перезапуска компьютера. Как можно заметить в строке 2298, возврат из функции machine_restart никогда не происходит, тем не менее сразу за ее вызовом находится break.Следует ли это рассматривать как классический стиль хорошего программирования? Пожалуй, да, и сейчас я кое-что добавлю. Файл kernel/sys.c относится к архитектурно-независимой части кода. Однако machine_restart, будучи явно архитектурно-зависимой, находится в архитектурно-зависимой части кода (файл arch/i386/kernel/process.c).Следовательно, в зависимости от платформы, упомянутый код будет отличаться. В настоящий момент неизвестно, будут ли будущие реализации machine_restart характеризоваться отсутствием возврата; например, может случиться так, что перезагрузка запланируется, а участвующие аппаратные средства приведут к задержке на несколько минут, в то время как возврат из функции уже произойдет. Или рассмотрим более правдоподобную ситуацию, когда существуют определенные причины невозможности совершения перезагрузки, связанные с невозможностью сброса некоторых аппаратных средств, находящихся под контролем программного обеспечения.На такого рода платформах будет иметь место возврат из machine_restart, таким образом подобная возможность должна учитываться в коде.По такому случаю в официальном дистрибутиве существует, по крайней мере, одна версия, допускающая возврат из machine_restart — версия для m68k. Код отличается для различных версий m68k-компьютеров. Поскольку книга ориентируется на х86-компьютеры, более подробный анализ всех особенностей упомянутого кода здесь не приводится.(В некоторых случаях machine_restart просто входит в бесконечный цикл, не перезагружая компьютер, но и не возвращаясь из функции.)Сейчас самое время немного прерваться. Оказывается, что чем бы ни считалось все рассмотренное — простой привычкой или паранойей — все оно необходимо для обеспечения переносимости ядра.29324: Следующие два случая разрешают или запрещают перезагрузку с использованием нечестной комбинации клавиш Ctrl+Alt+Del (известной в миру как «вулканический удар по нервам», «прах хакера», или, наиболее понравившаяся мне, «трехпальцевый привет»). Здесь просто выполняется установка состояния глобального флажка C_A_D, определенного в строке 29160 и проверяемого в строке 29378.29332: Этот случай подобен случаю LINUX_REBOOT_CMD_RESTART, но он останавливает систему, а не перезагружает ее. Отличие состоит только в обращении не к machine_restart, а к machine_halt (строка 2304), которая не предпринимает никаких действий для платформы х86, однако выполняет ощутимую работу по завершению работы системы для других платформ. Кроме того, здесь имеется план перехода на аварийный режим для компьютеров, которые не останавливаются при помощи machine_halt — выполняется обращение к функции do_exit (строка 23267), уничтожающей само ядро.29340: Здесь можно заметить знакомый шаблон. sys_reboot обесточивает компьютер, что практически то же самое, что и останов системы, за исключением вызова machine_power_off (строка 2307) для тех систем, которые обладают возможностью программного отключения электропитания.29348: Случай LINUX_REBOOT_CMD_RESTART2 — это одна из вариаций на известную тему. Здесь принимается команда, передаваемая в ASCII-строке, которая выражает способ, по которому компьютер должен завершать работу. Эта строка интерпретируется не функцией sys_reboot, a machine_restart; следовательно, строка, если она вообще присутствует, имеет отношение к платформо-зависимому коду. (Стоит, однако, заметить, что обычно имеется только один способ перезагрузки компьютера, поэтому эта дополнительная информация функцией machine_restart игнорируется.)29365: Вызывающая функция передала нераспознанную команду. sys_reboot не выполняет никаких действий и возвращает ошибку. Следовательно, даже если sys_reboot передает корректные магические числа в magic1 иmagic2, нет необходимости в выполнении каких-либо действий.29369: sys_reboot получила допустимую команду. Если поток управления добирается до этого места, возможно, это одна из команд установки C_A_D, поскольку другие команды, как правило, останавливают или перезагружают компьютер. Во всех ситуациях sys_reboot просто разблокирует ядро и вернет значение 0, указывающее на успех.sys_sysinfo24142: Системный вызов имеет возможность вернуть только одно целочисленное значение (int). В том случае, когда требуется вернуть больший объем информации, придется прибегнуть к тем же ухищрениям, что имели место при передаче более четырех аргументов в системный вызов — к возврату информации через указатель на структуру. Хороший пример — это системный вызов sysinfo, который собирает статистику по использованным системным ресурсам.24144: Распределение в памяти и обнуление structsysinfo (строка 15004), предназначенной для временного хранения возвращаемых значений. sys_sysinfo могла бы копировать каждое поле структуры по отдельности, однако это более медленный, неудобный и менее читабельный способ.24148: Запрещение прерываний. Более детальное описание можно найти в главе 6; сейчас достаточно сказать, что это необходимо для сохранения используемых sys_sysinfo значений от изменений.24149: Поле uptime в структуре sysinfo хранит количество секунд, в течение которых работает система с момента запуска. Упомянутое значение вычисляется на основе jiffies (строка 26146), которая подсчитывает тики внутреннего таймера в течение работы системы, и HZ, представляющим собой системный параметр, равный количеству тиков внутреннего таймера в секунду.24151: Массив avenrun (строка 27116) хранит среднюю длину очереди выполнения (т.е. среднее количество процессов, готовых для передачи в ЦП) за последние 1, 5 и 15 секунд. Эти значения периодически пересчитываются за счет обращения к calc_load (строка 27135). Поскольку разработчики ядра сознательно избегали операций с плавающей точкой, вычисления производятся с фиксированной точкой, поэтому в них присутствует некоторая неточность.24155: Записывается общее количество процессов, присутствующих (и присутствовавших) в системе.24158: Функция si_meminfo (строка 7635) заполняет поля структуры, относящиеся к использованию оперативной памяти, в то время как si_swapinfo (строка 38544) — поля, фиксирующие статистику по использованию виртуальной памяти.24161: Заполнение структуры завершено. sys_sysinfo пытается скопировать ее обратно в пространство пользователя, возвращая 0 в случае успешного исхода и EFAULT — в случае ошибки.

Список использованных источников

1. О.Бунин Разработка высоконагруженных систем. 2011
2. Э . Таненбаум Современные операционные системы. Питер – 2010.
Интернет ресурсы
3. http://www.kurzenkov.com
4. http://www.codenet.ru

Вопрос-ответ:

Что такое системный вызов futex() в ядре Linux?

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

Какие механизмы синхронизации используются в Операционных системах?

В Операционных системах используются различные механизмы синхронизации, такие как мьютексы, семафоры, условные переменные и атомарные операции. Мьютексы используются для обеспечения взаимного исключения – только один поток может захватить мьютекс и работать в критической секции. Семафоры позволяют ограничивать доступ к ресурсам определенному количеству потоков. Условные переменные используются для ожидания определенного события или сигнала от другого потока. Атомарные операции обеспечивают атомарность выполнения определенных операций, не допуская состояния гонки.

Какая особенность реализации быстрых механизмов синхронизации в пространстве пользователя с помощью системного вызова futex()?

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

Каким образом системный вызов futex() обеспечивает взаимное исключение?

Системный вызов futex() обеспечивает взаимное исключение, то есть защищает критическую секцию от одновременного доступа нескольких потоков, с помощью использования операции "Compare-and-Swap" (CAS). При попытке захватить блокировку, поток сравнивает текущее значение блокировки с ожидаемым значением и, если они совпадают, меняет значение блокировки на новое. Если значения не совпадают, то поток продолжает ожидание. Это позволяет обеспечить атомарность операции и предотвратить состояния гонки.

Какие механизмы синхронизации используются в операционных системах?

В операционных системах используются различные механизмы синхронизации, такие как мьютексы, семафоры, мониторы, условные переменные и т.д.

Что такое системный вызов futex() в ядре Linux?

futex() - это системный вызов ядра Linux, который предоставляет быстрый механизм синхронизации в пространстве пользователя. Он позволяет выполнить операции ожидания или установки значения переменной, используя атомарные инструкции процессора.

Как реализовано быстрое синхронизация с помощью системного вызова futex()?

Реализация быстрого механизма синхронизации с помощью futex() основана на использовании разделяемой переменной с помощью примитивов блокировки и ожидания. Это позволяет избежать связывания с ядром и снижает накладные расходы на синхронизацию.

Какие преимущества имеет системный вызов futex() по сравнению с другими механизмами синхронизации?

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

Какие источники использовались при написании статьи?

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

Что такое быстрые механизмы синхронизации?

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

Какие механизмы синхронизации используются в операционных системах?

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