Почему являются спин-блокировки хорошим выбором в Дизайне Ядра Linux вместо чего-то более общего в коде пространства пользователя, таким как семафор или взаимное исключение?

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

Когда Вы работаете ls *, сначала оболочка расширяется *, который является эффективно тем же как какой простое ls сделал, создает вектор аргумента со всеми файлами в текущем каталоге и вызовах ls. ls затем должен обработать тот вектор аргумента и для каждого аргумента и вызовов access(2)¹ файл для проверки это - существование. Затем это распечатает тот же вывод как (простое) первое ls. И обработка оболочки большого вектора аргумента и lsвероятно, включит большое выделение памяти маленьких блоков, которые могут занять время. Однако с тех пор был мало sys и user время, но много из real время, большая часть времени была бы проведена, ожидая диска, вместо того, чтобы использовать ЦП, делающий выделение памяти.

Каждый вызов к access(2) должен будет считать inode файла для получения данных полномочий. Это означает намного больше чтения с диска и ищет, чем простое чтение каталога. Я не знаю, насколько дорогой эти операции находятся на Вашем GPFS, но как сравнение, которому Вы показали ls -l то, которое имеет подобное время выполнения к подстановочному случаю, время должно было получить inode информацию, кажется, доминирует. Если бы GPFS имеет немного более высокую задержку, чем Ваша локальная файловая система на каждой операции чтения, мы ожидали бы, что это будет более явным в этих случаях.

Различие между подстановочным случаем и ls -l из 50% мог быть объяснен упорядочиванием inodes на диске. Если inodes были размечены последовательно в том же порядке как имена файлов в каталоге и ls -l статистика (2) редактор файлы в порядке каталога перед сортировкой, ls -l возможно считал бы большинство inodes в развертке. С подстановочным знаком оболочка отсортирует имена файлов прежде, чем передать их ls, так ls вероятно, считает inodes в другом порядке, добавляя больше перемещения головки диска.

Нужно отметить что Ваш time вывод не будет включать время, потраченное оболочкой для расширения подстановочного знака.

Если Вы действительно хотите видеть то, что продолжается, использовать strace(1):

strace -o /tmp/ls-star.trace ls *
strace -o /tmp/ls-l-star.trace ls -l *

и взгляните, какие системные вызовы выполняются в каждом случае.

¹ я не знаю если access(2) на самом деле используется, или что-то еще такой как stat(2). Но оба, вероятно, требуют inode поиска (я не уверен если access(file, 0) обошел бы inode поиск.)

7
23.12.2010, 18:23
4 ответа

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

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

8
27.01.2020, 20:14
  • 1
    Если блокированный вызывающий абонент не делает контекстного переключения, как для того другого потока возможно выпустить блокировку? –  David Cary 01.03.2011, 22:07
  • 2
    В ядре спин-блокировка может только быть сохранена другим ЦП, не другим потоком. Следовательно можно ожидать, пока другой ЦП не выпускает блокировку. –  Tino 25.01.2016, 15:47

Поскольку вопрос подразумевает в высказывании, что спин-блокировки являются "отходами", спин-блокировки должны быть сохранены только кратко.

Спин-блокировки не являются единственным способом синхронизировать несколько потоков. Взаимные исключения/семафоры также используются в ядре Linux, как другие примитивы синхронизации (например, waitqueues, события).

Однако ядро должно иметь дело со случаями, которые никогда не видит пространство пользователя, при этом общий является обработчиками прерываний. Обработчики прерываний не могут быть перенесены на Linux, но часто должны использовать некоторую примитивную синхронизацию (например, добавить объект работы к связанному списку, который некоторый другой поток обработает далее). Так как обработчики прерываний не могут спать, они не могут использовать взаимные исключения, waitqueues, и т.д. Это в значительной степени оставляет спин-блокировки. Если поток должен синхронизировать доступ с обработчиком прерываний, то он должен также использовать ту же спин-блокировку.

Спин-блокировки являются не обязательно отходами. Они оптимизированы для non-contention/non-waiting случая и могут быть взяты и выпущены очень быстро. В этом случае они быстрее и включают меньше служебное, чем другие примитивы синхронизации.

11
27.01.2020, 20:14

Другие ответили. Я буду суммировать случаи, где Вы использовали бы спин-блокировку и правила использовать спин-блокировку.

1. Когда спин-блокировка используется?

Ответ: В следующих ситуациях.

  1. Потоку, который содержит блокировку, не позволяют спать.
  2. Поток, который ожидает блокировки, не спит, но вращается в жестком цикле.

Когда правильно используется, спин-блокировка может дать более высокую производительность, чем семафор. Исключая: обработчик Intrrrupt.

2. Что правила состоят в том, чтобы использовать спин-блокировки?

Ответ:

Правило - 1: Любой код, который содержит спин-блокировку, не может оставить процессор ни по какой причине кроме к сервисным прерываниям (иногда даже затем). Таким образом, код, содержащий спин-блокировку, не может спать.

Причина: предположите, что Ваш драйвер, содержащий спин-блокировку, засыпает. Исключая: вызывает функцию copy_from_user() или copy_to_user(), или вытеснение ядра умирает, поэтому более высокий приоритетный процесс отодвинул Ваш код. Эффективно процесс оставляет ЦП, содержащий спин-блокировку.

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

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

Правило - 2: Отключите прерывания на локальном ЦП, в то время как спин-блокировка сохранена.

Причина: Поддержка Ваш драйвер берет спин-блокировку, которые управляют доступом к устройству и затем выпускают прерывание. Это заставляет обработчика прерываний работать. Теперь для обработчика прерываний также нужна блокировка для доступа к устройству. Если обработчик прерываний будет работать на том же процессоре, то он начнет вращаться. Код драйвера также не может работать для выпуска блокировки. ТАКИМ ОБРАЗОМ, процессор будет вращаться навсегда.

Правило - 3: Спин-блокировки должны быть сохранены в течение минимального возможного времени.

Причина: Длинная блокировка содержит времена, также мешает текущему процессору планировать, означая, что более высокому приоритетному процессу, вероятно, придется ожидать для получения ЦП.

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

Правило-4: если у Вас есть семафоры и спин-блокировки оба, чтобы быть взятыми. Затем возьмите семафор сначала и затем спин-блокировку.

2
27.01.2020, 20:14

Спин-блокировки и мьютексы используются из-за нехватки ресурсов ЦП ..Они становятся избыточным наследием конструкции фон Неймана на основе 8-битных регистров, которая является наихудшей архитектурой, совершенно нелогичной в наши дни.

К сожалению, возможности компилятора C / C ++ стали непропорциональны аппаратному обеспечению в функциях, которые просто не могут быть уловлены аппаратными средствами с архаичными внутренними ресурсами, которые все еще присутствуют у нас по сей день. Однопроцессор, таким образом, экономится время, требующееся для сохранения контекста, и продолжается загрузка повторно используемых SMP. Будущее за устройствами FPGA с оптимизированными инструментами сборки. Xilinix имеет новый 14-нм техпроцесс с 3000 межсоединениями между четырехъядерными ядрами A9 и программируемыми вентильными матрицами , которые содержат до сотен мегабит SRAM в таблицах, что позволяет использовать усовершенствованный дизайн конечного автомата, способный выполнять сложную арифметику с плавающей запятой / многомерное векторное сокращение / сокращение собственных таблиц ... намного больше, чем ваш старый привязанный компилятор для инвалидных колясок.

Мой аппаратный дизайн 25 лет назад включал расширенное оборудование в интерфейс DSP AD 21020 / CPU i960 ... стало ясно, что расширенный дизайн решил многие проблемы с программным обеспечением в этом интенсивном принтере шириной 1 метр и 160 соплами.

Специалисты в области разработки ядра, приглашенные в небольшую группу для оценки / изменения новой архитектуры, которая может заменить спин-блокировки / промахи в кэше / повторные условия SMP.

-3
27.01.2020, 20:14

Теги

Похожие вопросы