Pull to refresh

Comments 48

А как работает многозадачность на современных процессорах? Как работают многоядерные процессоры?
Многоядерный процессор с точки зрения программы (в том числе с точки зрения ОС) — это просто несколько отдельных процессоров. Соответственно техника программирования та же: доступ к общим ресурсам нужно организовывать помощью средств синхронизации.
Тут надо уточнить, что контроллер прерываний один. А вот аппаратный таймер на каждый процессор свой? И как контроллер выбирает, какой процессор прерывать?
Почему это один? На каждый процессор есть свой APIC, взаимодействие и поддержка когерентности кеша поддерживается с помощью прерываний interprocessor communication.
Если APIC на каждый свой, то как один чипсет совместим с процессорами с разными количествами ядер? И как происходит выбор на каком APIC обработать прерывание?
IO APIC один. Для каждого прерывания на нём конфигурируется каким процессорам его следует доставить. Это либо LAPIC ID, либо битовая маска.
Есть local APIC, локальный для каждого ядра, а есть IO APIC, общий для всех.
Прерывания от внешних устройств попадают в IO APIC, а оттуда — в LAPIC, с некоторыми тонкостями, зависящими от режима диспетчеризации IRQ.
Друг с другом процессоры обмениваются IPI через LAPIC.
Теперь более менее понятно, спасибо.
А если рассмотреть архитектуру процессоров Itanium?
Я небольшой специалист по Itanium, но мне кажется, что с точки зрения рассматриваемого вопроса один Itanium-процессор — это просто один процессор. То что в нем несколько параллельно работающих устройств, дела не меняет. Главное, что счетчик команд — один. В конце концов, в Пентиуме тоже несколько параллельно работающих устройств, и за один такт может выполнится несколько команд.
Процессор ничего не знает ни о потоках, ни о процессах. Он просто последовательно выполняет инструкции, пока не случится прерывание.

Т.е., не смотря на наличие в архитектуре 80386 таких элементов как TR (Task Register), TSS (Task State Segment) и т.п., он определенно ничего не знал о multi-tasking и они были введены для каких-то других task'ов? ;)

Прерывания же, о которых вы говорите, симулировали многозадачность еще задолго до 80386. А для него самого это был лишь один из триггеров для переключения контекста. Популярный по одной простой причине, что в попытке раздать все задачам одинаковые кванты времени, их надо как-то измерить. А с таймером были только два способа коммуникаций — поллинг и IRQ. Ниже коротенькая вырезка из интеловского референса на 80386 от 1986:

To provide efficient, protected multitasking, the 80386 employs several special data structures. It does not, however, use special instructions to control multitasking; instead, it interprets ordinary control-transfer instructions differently when they refer to the special data structures. The registers and data structures that support multitasking are:
— Task state segment
— Task state segment descriptor
— Task register
— Task gate descriptor
With these structures the 80386 can rapidly switch execution from one task to another, saving the context of the original task so that the task can be restarted later. In addition to the simple task switch, the 80386 offers two
other task-management features:
1. Interrupts and exceptions can cause task switches (if needed in the system design). The processor not only switches automatically to the task that handles the interrupt or exception, but it automatically switches back to the interrupted task when the interrupt or exception has been serviced. Interrupt tasks may interrupt lower-priority interrupt tasks to any depth.
2. With each switch to another task, the 80386 can also switch to another LDT and to another page directory. Thus each task can have a different logical-to-linear mapping and a different linear-to-physical mapping. This is yet another protection feature, because tasks can be isolated and prevented from interfering with one another.
Если у Вас есть мечта создать самую медленную ОС в мире, можете попробовать это использовать. =)
Переключение задач через JMP/CALL гораздо быстрее, чем через IRQ.
Да всё что угодно быстрее, чем встроенные в x86 средства переключения задач.
И как это связано с обсуждаемой темой? Поскольку встроенные средства работают медленно, то мы будем считать, что их нет? ;)
Если встроенные средства такие крутые, а их не используют ленивые и косные разрабы, то обсуждать их, конечно, надо.

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

Я как-то склоняюсь ко второму варианту.
Тогда понятна причина нашего недопонимания. Просто по мне, если средства есть, то они есть. Если я закрою на их существование глаза, то могу упустить момент, когда их реализация будет оптимизирована и вполне готова к употреблению. Так что для меня они существуют, но с оговорками, что их использование должно быть обосновано и соответствовать тому, что мы знаем об их поведении в тех или иных условия. Например, Linux ничто не мешает использовать TSS per processor и не использовать их per thread.
Как-то ненаучно...«будем считать»… Если есть, значит оно есть. И не важно эффективно или нет.

Коммент Guderian-а намного более информативный в плане технических подробностей, чем невнятные топики то о том, что многозадачность есть, то ее нет.

Просто и ясно: «Она есть, но медленная и с ограничениями. По этому не используется».

И как же вы реализуете вытесняющую многозадачность без IRQ?
Странный вопрос. Во-первых, «вытесняющая многозадачность» не упоминалась вообще нигде и никем в данном контексте. Во-вторых, если вы знаете определение вытесняющей многозадачности, то прекрасно знаете ответ на свой вопрос.
Если речь не о вытесняющей многозадачности ( а есть ли таковые современные ОС? ), то она может быть реализована вообще как угодно и смысла говорить об этом нет.
В современных ОС это не используется.
Точнее, не используется для реализации многозадачности/многопроцессности/многонитевости.
Естественно. И современность тут не причем, поскольку большинство актуальных ОС ни на йоту не поменяло своей императивной концепции в разработке, которая была заложена еще задолго до появления 80386. Так что с чего им было осуществлять фундаментальные изменения?
Дело не в концепции, а в ограничениях механизма task'ов. Чтобы создать task'у, нужно создать TSS (task state segment). Для этого надо выделить сегмент памяти; для этого надо сделать соответствующую запись в GDT. В GDT же можно поместить не более 8192 записей. Итого имеем, что нельзя создать более, чем 8192 задач.

Про тормознутость уже сказали.
От наличия ограничения в 8192 задачи, код современных ОС из императивного стал декларативным? Или, может архитектура i386 потеряла знания о Task'ах. Или вы не заметили тем поста и той его части, что я комментировал?
Я заметил.

Пост: «Процессор ничего не знает ни о потоках, ни о процессах.»

Ваш комментарий: «не смотря на наличие в архитектуре 80386 таких элементов как TR (Task Register), TSS (Task State Segment) и т.п., он определенно ничего не знал о multi-tasking и они были введены для каких-то других task'ов? ;)»

Да, о многозадачности, применяемой в операционных системах, процессор не знает. Да, task'и применяются для иных целей.

>От наличия ограничения в 8192 задачи, код современных ОС из императивного стал декларативным?

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

Позвольте полюбопытствовать, для каких?

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

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

Я не специалист в этом вопросе, поэтому лучше дам ссылку на википедию. en.wikipedia.org/wiki/Task_State_Segment#Use_of_TSS_in_Linux

>Декларативный код упрощает реализацию кооперативной многозадачности.

Это все так. Но на саму реализацию многозадачности это не влияет.
Есть еще ограничение — современные ОС поддерживают 64 бита, а там TSS не поддерживает переключение. Есть несколько редких ОС, которые использовали TSS для поддержки многозадачности, но очень обломались когда захотели поддержку 64 бит.
Был в своё время замечательный сайт www.lowlevel.ru. Именно благодаря ему на втором курсе я написал свою недоось-загрузчик на ассемблере. К сожалению, по неизвестным причинам он прекратил своё существование. но его можно откопать в архиве: web.archive.org/web/20040130034935/http://www.lowlevel.ru/
Очень много полезной информации по «осестроению» для x86 очень доступным языком.
И как это влияет на последний вариант ответа? :) Он собирает в себе все правильные варианты, не вдаваясь в подробности. Любой обобщенный вариант можно назвать неправильным из-за обобщенности, но не правильным он от этого не станет. И, да, опечатка с «меняет инструкции», не принимается, т.к. я там несколько раз исправился :)
Последний ответ близок к правильному, но он не правилен по своей сути. ОС не меняет инструкции программ. ОС только перенацеливает процессор на выполнение разных программ в разные моменты времени.
>Процессор ничего не знает ни о потоках, ни о процессах.

дальше не читал…
сразу видно — специалист.
Мне почему-то на этой фразе вспомнились школьные уроки физики, где любили говорить: «Почему падает камень?», а кто-то обязательно говорил: «Из-за закона тяготения», на что получали в ответ: «Неужели камень такой умный и знает законы?».

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

процедура операционной системы, решившая сделать переключение

стек — область памяти для хранения состояния исполняемых в данный момент времени процедур


Весьма неоднозначные тезисы.
И, конечно же, ни слова не прозвучало о том, что случается с регистрами eax, ebx и прочими при переключении потоков/процессов.
Если Вы считаете процитированные места неправильными, то Вам стоило бы пояснить, почему. Или написать свой пост, где в нескольких словах был бы описан правильный вариант.

Ни слова не прозвучало о регистрах eax и прочих именно с целью экономии букв, в расчете на то, что читатель знает, что при вызове процедуры регистры упрятываются в стек, а при выходе из процедуры восстанавливаются. Переключение же потоков описано как вызов процедуры — смена указателя стека — выход.
Я не утверждаю, что эти процитированные места не правильны. Они неоднозначны и понять их можно не правильно.
При вызове процедуры регистры не обязательно упрятываются в стэк, это зависит от calling convention.
Каждый поток (thread) имеет свой стек

Может вы хотели сказать «контекст»?
Контекст понятие относящееся к ОС и текущему состоянию процессора. Каждый поток на самом деле имеет свой стек. (для винды, — 1Мб по умолчанию)
Я не сказал «контекст», чтобы не получилось слишком много букв. Стек — существенная часть контекста.
> Обработка прерывания сводится к вызову процедуры, не заданному в исполняемом коде.

Может быть, так правильно:

Обработка прерывания сводится к вызову процедуры, не заданной в исполняемом коде.
Вызов процедуры не заданной в исполняемом коде приводит к сбою защиты.
Нет, именно вызов процедуры прерывания не задан в исполняемом коде. Сама процедура задана в коде ОС или драйвера, при исполнении этого кода может случиться прерывание, следовательно процедура прерывания может быть задана в исполняемом коде
Теперь я нашёл пользу от сессии — у меня как раз был экзамен по архитектуре эвм, и там вопросы про многозадачность и т.д. :)
Sign up to leave a comment.

Articles