Вы думаете у человека, у которого не набита рука на верилоге - вдруг возникнет талант сделать гениальный CPU? Это не получится по очень банальной причине: когда дизайнер придумывает микроархитектуру, стадии конвейера, внутренние буфера и таблицы всякие - он должен очень хорошо чувствовать у каких операций будет какая задержка внутри такта
Скорей, не в верилоге или другом ХДЛ, а в схемотехнике: нужно же понимать, в какое "железо" превращаются те или иные конструкции языка, а не просто уверенно владеть синтаксисом ХДЛ и уметь описать на нём желаемое поведение.
Придумали это не дураки, а люди которые все внимательно по тактам меряли, и у них получилось что статистически это в среднем работает хорошо
Ну так и саму концепцию RISC придумали не дураки, и посчитали правильно -- что в CISC-процессорах активно используется от силы 10% команд, а остальные -- эпизодически, вот и решили их выкинуть. Однако на сегодняшний день от их изначальной концепции осталось только выполнение операций исключительно в регистрах, и то есть определённые подвижки для ухода от этого в некоторых специфических случаях: внезапно оказалось, что эти самые редко используемые команды многократно ускоряют выполнение соответствующих классов задач, т. е. отнюдь не бесполезны, если речь идёт о вычислительных системах достаточно высокой производительности, а не минимальной стоимости и потребляемой мощности. Вот и набиты современные типа RISC-процессоры сотнями, а то и тысячами странных и редко используемых команд :) (хотя насколько странных, как EDMK в Системе 360, сейчас, пожалуй, не встречается)
Ну и если б такое управление TLB работало бы действительно хорошо, от него бы, в конечном итоге, не отказались бы, да и использовался бы такой подход намного шире.
А вы в курсе, что даже в достаточно простых мипсовских ядрах микроконтроллерного класса аппаратные кэши трансляций состояли не из одной таблицы, а из трех? И в дополнение к нему вот тот механизм.
Нет, не в курсе; я особо в MIPS не погружался -- так, полистал немного для общего развития, и всё. На практике с ними никогда сталкиваться не приходилось, вот и не углублялся. Но это уже тонкости реализации, а не архитектурно-концептуальный уровень (очевидно, что у современных мэйнфреймов z/Architecture TLB тоже несколько отличается от, скажем, использованного в System 370/145, чья микроархитектура была нами содрана и воплощена в ЕС-1035: там весь TLB аж из восьми (восьми!) элементов состоит, а управляется микропрограммно, насколько помню; однако для программиста эти тонкости совершенно безразличны, ибо на концептуальном уровне TLB ведёт себя одинаково на любых моделях).
286 - это ядро с разными тупиковыми странностями как я помню
Угу. Не столько даже тупиковая -- сделать полноценную ОС с виртуальной памятью и прочим на этом можно, и даже некоторые дополнительные возможности были бы доступны и реализовывались бы дёшево в плане скорости, но очень уж неудобно всё это дело было, поэтому и не прижилось. (Замечу в скобках, что подход IBM -- "нормальная" виртуальная память на основе страниц с "нормальным" MMU плюс архитектурная концепция множества адресных пространств плюс архитектурный же механизм "вызова программы" оказались намного элегантнее и эффективнее, чем Интеловские описатели сегментов и шлюзов вызова, хотя, в первом приближении, позволяют решить одни и те же задачи аппаратными (с точки зрения программиста) средствами, т.е. достаточно быстро -- в отличие от чисто программной реализации путём вызова соответствующих сервисов операционной системы, что всегда очень дорого).
а PDP-11 упоминать нельзя, потому что люди влюбляются в его ассемблер и им приходится доказывать, что это плохая архитектура так как она делает конвейеризацию дорогой из-за двухоперандности и аутоинкрементов
А тем, кто влюбился, показать VAX-11, а потом попросить набросать концепцию суперскалярного процессора этой архитектуры :) Ага, с длиной кода команды от 1 до 36 байт :)))) В PDP-11, по крайней мере, выборку и декодирование команд сделать несложно -- длина хоть и переменная, но количество вариантов ограничено (1, 2 или 3 слова, т. е. 2/4/6 байтов), а однозначно определить её можно анализом первого слова (хотя в Системе 360 и её потомках анализ ещё проще: длину кода команды (тоже 2/4/6 байтов) определяют два старших бита первого байта). Собственно, поэтому мне VAX-11 и не нравится, хотя PDP-11 -- моя любимая 16-разрядная архитектура, а VAX лишь продолжил её идеи: просто DEC решила сделать мощную машину, а концептуальный подход использовала, который был успешным для маленькой и дешёвой машины; естественно, ничего из этого не вышло (VAX-11 получился слишком дорогим, чтоб вытеснить PDP-11 из её ниши, но при этом не имел шансов стать высокопроизводительным, чтоб действительно составить конкуренцию тем же мэйнфреймам IBM).
В учебных программах мало времени, учителя норовят впихнуть свою ностальгию по детству (6502 всякие), а студенты легко отвлекаются на всякое, поэтому нужно держать их строго фокусированными, чтобы они могли решать задачи на будущих интервью, а не процессорной археологией заниматься.
Честно говоря, не уверен. Что бизнесу нужны готовые специалисты -- это понятно, а Вы как раз в бизнесе и работаете, решаете реальные инженерные задачи. С другой стороны, нельзя подготовить исследователя/учёного, если у него кругозор ограничивается тем, что нужно и эффективно здесь и сейчас. Но это возвращаемся уже к общим проблемам образования -- в частности, к "целеполаганию" в образовании: а кого мы вообще готовим в том или ином учебном заведении? Думается, количество вузов, как я их понимаю, нужно сократить радикально -- раз в 10, а то и больше, -- и они должны готовить именно учёных; ну а для более приземлённых вещей типа обычных программистов или там "вериложников" -- условные техникумы и ПТУ. Ну, думаю, Вы понимаете идею.
Из сферического вакуума у нас, кстати, тоже было в 90-е, например Z-преобразование (по схемам с задержками и коэффициентами - никогда не встречал потом на практике!), но это было только на первом курсе, на абстрактном мат-анализе
Из школьного: вводят производные и интегралы в последних классах на уроках алгебры -- но чисто "сферически в вакууме", и основная масса учеников понятия не имеет, нафиг нужны эти математические извраты. А вводить можно было бы даже раньше, но в рамках физики -- механики, где прекрасно видно, как резко эти извраты упрощают решение многих задач, приближённых к реальности (преобразования между путём-скоростью-ускорением и т.п.). Как по мне, пользы от такого обучения было бы куда больше: и достаточно понятная, очевидная и практически применимая физика, и сразу математический аппарат для её обслуживания.
А мне вспомнился Терри Прачет и его "Народ", где "полуглавная героиня" -- девочка из британской королевской семьи, попавшая на почти необитаемый остров -- в один момент думает, что их (девочек знатного происхождения) учат лишь тому, что точно никогда не пригодится в реальной жизни :)
В более поздних архитектурах, например в MIPS, TLB был не в памяти, а на основе CAM (блоков context-addresable memory) и регистровых структур. При tlb miss происходило исключение и в его программном обработчике можно было подгрузить данные из памяти.
Мне это такой дикостью показалось: ведь жутко медленно и неэффективно по сравнению с аппаратной выборкой из таблиц переадресации, а последняя -- вещь весьма простая, чтоб на ней усиленно экономить.
В любом случае, сейчас академический стандарт - RISC-V
Что, уже официально на RISC-V перешли? Я-то от образования далёк, поэтому не в теме, что там и как -- только по книжкам что-то вижу.
Но говорил я больше о том, что давать глубоко надо, конечно, современное, но упомянуть неплохо бы и существовавшие некогда другие подходы -- для общего развития, так сказать, но без траты сколько-нибудь значительного времени на это дело (кто заинтересуется историей -- сам найдёт, ему достаточно ключевые слова подсказать).
А я б про кэши и таблицы страниц рассказал бы в 16-17 лет, когда познакомился с этим на реальном железе... В общем, если человеку интересна некая тема, он и сам её изучает, а если неинтересна -- никакой вуз не поможет (и вопрос только в том, а нафига такой человек в вузе?)
Строго говоря, не обязательно, хотя во всех современных архитектурах, думается, это именно так. Навскидку из отличающихся "исторических" архитектур:
80286 с его теневыми регистрами для сегментов (хотя, подобно TLB, теневые сегментные регистры хранят информацию, полученную из таблиц в памяти, но, в отличие от TLB, это не "кэш" в том смысле, что каждый теневой регистр обновляется процессором не "по собственному желанию", а в строго определённый момент -- когда выполняется загрузка соответствующего сегментного регистра, т.е. по прямому указанию программиста). В IA-32 теневые регистры сохранены, но там появился уже и нормальный TLB, поскольку появилась нормальная страничная организация памяти;
PDP-11, где преобразование адресов основано на регистрах MMU: из-за малого объёма виртуального адресного пространства (64 Кбайта) нужды в таблицах переадресации, расположенных в ОЗУ, нет, и всё необходимое лежит прямо в MMU; соответственно, нужды в TLB тоже нет.
Поскольку процессор выполняет команды, для него выглядящие как набор битов (машинный код), а для человека -- как программа на языке ассемблера, то, очевидно, перед разбором того, как процессор устроен и работает, необходимо разобраться, как писать программы на ассемблере и как команды кодируются.
Поскольку ОС управляет выполнением программ, а последние, опять-таки, являются последовательностью команд ассемблера, то опять нужно понимать, что в реальности они из себя представляют, как выполняются на концептуальном (не физическом) уровне и т.д. -- знать про регистры, про адреса памяти и т.д. и т.п. Соответственно, базовый курс по ассемблеру должен предшествовать курсу по ОС.
Что касается ввода-вывода, то прежде чем браться за ОС и её драйверы, неплохо знать, как реально ведётся работа с устройствами -- а этого проще всего достигнуть написанием (или разбором готового) небольших программ, взаимодействующих с простыми устройствами типа UART на уровне регистров. Тогда станет достаточно очевидно, что ОС, во-первых, абстрагирует прикладные задачи от подобного "общения" с устройствами, зависящего от специфики устройств и т.д. и т.п., во-вторых, организует очереди запросов ввода-вывода, а в-третьих, разруливает обращения от разных задач к одним и тем же устройствам по определённым правилам.
В общем, курс по ОС в любом случае должен быть последним, ибо ОС имеет дело с низкоуровневыми сущностями, с которыми нужно быть более-менее знакомым до того, как начать разбираться с работой ОС.
Угу, я сталкивался с таким. На нашем предприятии всё писали на Коболе, на некоторых других в нашем городе -- тоже, но, по меньшей мере, на одном крупном заводе -- как раз на PL/I, причём тоже чисто прикладное и больше "экономическое", а не "научное" (Фортран тоже попадался -- но, есно, в "научном" коде). Мне начальство предложило на нём пару вспомогательных программ написать (какие-то преобразования чего-то во что-то, что потом на вход обычного Кобола идёт, и программа выхода для штатной сортировки), но я предпочёл наваять всё это на ассемблере :) Там действительно что-то достаточно низкоуровневое было, в одной из задач я даже EDMK использовал.
Но, кстати говоря, преобразование форматов на Коболе может оказаться достаточно сложным -- всё-таки, он очень ограничен по возможностям, если смотреть с высоты даже не сегодняшнего дня, а 70-х годов, и PL/I, хотя и сложен (скорей, не сложен даже, на очень уж объёмист: документация на него занимает больше места, чем документация на Фортран, Кобол, Алгол, РПГ и Ассемблер, вместе взятые), может оказаться более разумным выбором.
Ну, может быть... В качестве гипотезы: PL/I использовался, в первую очередь, самой IBM для системных и околосистемных вещей, а вот что бизнес-приложения, что "математику" народ писал, главным образом, на Коболе или Фортране соответственно. PL/I -- язык универсальный и позволял успешно писать любые вещи, но уж слишком он сложен по сравнению с этой парочкой, поэтому его ценность как замены для них наверняка была сомнительной, ну а околосистемные вещи, для чего он подходил намного лучше, конкурируя, по большому счёту, лишь с ассемблером, мало кто разрабатывал.
Ну а у IBM огромное количество кода, насколько знаю, написано на PL/I и PL/S -- а их мэйнфреймы живее всех живых и никуда исчезать не собираются (да и наши ЕС ЭВМ ушли по политико-экономическим, а не техническим причинам, шла бы история по другому пути -- их новые модели и сейчас бы работали, занимая свою нишу подобно IBMовским машинам). Впрочем, Вы это и без меня знаете :)
тобы понимать, что io_uring - не новое явление, а догоняющий ход в долгой эволюции, полезно посмотреть на соседей. Идея completion-based async I/O старше readiness-based лет на двадцать.
Не на двадцать, а очень-очень-очень намного больше. В частности, асинхронный ввод-вывод с уведомлением приложения о завершении операции -- основа ввода-вывода в OS/360, а её разработка началась ещё в первой половине 1960-х одновременно с разработкой самих машин -- первых мэйнфреймов Системы 360; первая, жутко обрезанная версия стала доступна пользователям в 1966-м. Правда, в прикладных программах обычно пользовались синхронным вводом-выводом, поскольку это проще для программиста, но асинхронщина была всегда доступной и использовалась, когда это было нужно.
Асинхронный ввод-вывод -- основа и "матери" Винды (VAX/VMS), и её "бабки" (RSX-11M), а это -- 1970-е годы.
Если закончивший вуз программист не способен за 1-2 недели самостоятельно освоить Кобол по документации (описанию языка), то какой, нафиг, это программист? Это дебил с дипломом. Кобол -- элементарнейший язык, и писать на нём "экономические" приложения, для чего он и создавался, легко и просто.
Если он вообще не инициализирован, т.е. в него никогда не выполнялась запись -- то да (в той ячейке, где он лежит, может находиться мусор). Однако если он равен нулю или любому другому определённому числовому значению, то и поведение, с точки зрения стандарта и языка, должно быть определённым: обращение к памяти по заданному им адресу. К чему это приведёт -- не забота компилятора, за это должен отвечать программист. (И да, нужна бы стандартная прагма, включающая и отключающая контроль за нулевыми указателями).
Как по мне, основная беда от UB связана не с тем, что, дескать, аппаратура как-то не так отработает и т.д. и т.п., а то, что компилятору позволено творить любую дичь, даже когда в реальности поведение будет определённым на любой сколько-нибудь "нормальной" платформе.
Возьмём, например, целочисленный знаковый тип размером 2 байта. Как известно, все современные "нормальные" платформы (а существуют ли современные "ненормальные", я, честно говоря, не знаю) для представления целых чисел используют дополнительный код. Соответственно, имея 16 бит, мы имеем диапазон от -32768 до +32767. Прибавление единицы к максимальному положительному значению технически даёт максимальное отрицательное: +32767 + 1 = -32768. И здесь возможны ровно два технически обоснованных результата:
операция сложения молча выполняется и даёт указанный абсолютно предсказуемый и технически корректный результат;
фиксируется возникновение переполнения, что, в конечном итоге, приводит к исключению (неважно, выполняется ли это чисто аппаратными средствами -- скажем, мэйнфреймы IBM умеют ловить такое переполнение, если это разрешено соответствующим битом маски, а на IA-32 aka x86 надо явным образом анализировать флаг OF с помощью команды INTO или же условным переходом).
На мой взгляд, подобные ситуации не должны объявляться как UB на уровне языка и компилятора, т.е. стандарт языка должен указывать, а компиляторы должны реализовывать генерацию кода, выполняющего требуемую операцию, не взирая на возможное (или даже гарантированно возникающее) переполнение -- они, разве что, должны выдать предупреждение, если видят, что переполнение возникнет. А ещё лучше иметь на уровне стандарта (и, естественно, конкретных компиляторов) некую прагму, которая позволяет стандартным образом включать и отключать контроль переполнения во время выполнения программы -- даже если такой контроль, как в случае с IA-32, влечёт за собой потенциальное снижение производительности из-за необходимости выполнения лишних команд. Тогда ситуация остаётся управляемой для программиста: он знает, где переполнение допустимо, а где -- нет, и может соответствующим образом настраивать поведение программы стандартным образом.
То же самое касается и многих других случаев UB. Скажем, для невыровненных указателей тоже можно предусмотреть прагму, заставляющую включать код их проверки, причём даже на платформах, где технически невыровненные доступы разрешены и работают корректно (такая проверка упрощает отлов невыровненных указателей, которые станут проблемой на других платформах), и прагму, обязывающую компилятор сгенерировать код, корректно работающий с невыровненными указателями (для IA-32 эта прагма де-факто ничего делать не будет, а вот на ряде других платформ при её использовании будет формироваться другой, более громоздкий код -- скажем, побайтовая загрузка четырёхбайтовой величины с последующей "сборкой" в регистре процессора). Ну и т.д. и т.п. Но вместо этого, как мы знаем, UB трактуется просто как право компилятора творить любую дичь, в том числе выкидывать сомнительный для него код.
чтобы ось могла прервать одну задачу, она должна словить прерывание, если его не вызывает сама программа, то его должна вызывать другая часть - таймер. Можно конечно сделать систему, где прерывания от сторонних ресурсов говорят "эй, мне тут выполниться надо" и проц передает управление, но это чет не то, если делать вытесняющую многозадачность, то через таймер, то так да - он есть почти везде.
Вообще-то, подавляющее число устройств ввода-вывода использует механизм прерываний, чтобы информировать процессор (систему) о тех или иных событиях -- например, о завершении ранее начатой операции. И этих прерываний более чем достаточно для переключения потоков (задач), таймер необходимым ни разу не является. Собственно, все настоящие ОС и переключают потоки по целой куче разных событий, а отнюдь не только по истечению времени; приоритеты выполнения не просто так придумали.
Наличие/отсутствие таймера к процессору отношения не имеет. Конкретно в IBM PC и всех последующих более-менее совместимых машинах он был. Изначально это была микросхема 8253 или 8254, один из каналов которого в качестве таймера, кидающегося прерываниями, и использовался; позднее таймер стал частью более сложных микросхем, но для программиста это роли не играет.
Возможно, мы используем термины не совсем идентичным образом, что может создавать проблемы с пониманием. Вообще, вытесняющая многозадачность -- это когда ОС может по своему усмотрению снять с процессора один поток и поставить другой. Таймер для этого не обязателен; скажем, ОС может передать управление вышедшему из ожидания завершения операции ввода-вывода высокоприоритетному потоку, сняв с процессора низкоприоритетный поток, который работал, пока высокоприоритетный поток вынужденно простаивал, ожидая завершение ввода-вывода. В кооперативной многозадачности такое невозможно: там поток должен сам тем или иным способом отдать управление. Таймер же нужен для реализации разделения времени, т.е. когда потокам выделяется определённый отрезок (квант) времени, в течение которого они могут непрерывно занимать процессор, и если поток весь свой квант выжрал, ОС принудительно снимает его с процессора и отдаёт процессор другому потоку -- и так до тех пор, пока все готовые к выполнению потоки не отработают свои кванты, и лишь после этого происходит возврат к первому из них. Таким образом, любая система с разделением времени будет системной с вытесняющей многозадачностью, но не каждая система с вытесняющей многозадачностью обязана быть системой с разделением времени (исторический пример -- OS/360, которая, возможно, вообще первой "большой и совсем-совсем настоящей" ОС в истории была; разделение времени там было необязательной опцией, но вытесняющая многозадачность была (почти) всегда, причём и в случае отсутствия таймера).
Чёткого определения ОС действительно нет, т.е. опять возвращаемся к терминологии. Для меня более-менее полноценная ОС -- это (а) средство управления ресурсами вычислительной системы (памятью, процессорным временем, периферией в широком смысле слова), распределения их между приложениями и самой ОС, и (б) набор сервисов, предоставляемых прикладным программам и абстрагирующих их от особенностей железа, насколько это возможно. MS DOS и CP/M, например, совсем полноценными ОС для меня не являются -- они однозадачные, а соответственно, в принципе не предусматривают разделения ресурсов между приложениями, а вот Винда с Линухом или упомянутая мной выше ОС/360 -- являются.
В советской терминологии -- не упреждающий, а ускоренный перенос.
Вообще, существует несколько вариаций этой идеи; в частности, в 2-битовых секциях Intel 3002 (наша К589ИК02) вместо сигналов P и G -- сигналы X и Y, чуть-чуть отличающиеся логикой формирования.
Они или их варианты много где использовались. Тут указали на процессор ЭВМ ЕС-1033 (под который, вроде как, выпуск К155ИП3 и наладили); К131ИП3 использовался в проце ЭВМ СМ-1600; КР531ИП3 -- в качестве сумматора в MMU процессора ЭВМ СМ-1420, и т.д.
Скорей, не в верилоге или другом ХДЛ, а в схемотехнике: нужно же понимать, в какое "железо" превращаются те или иные конструкции языка, а не просто уверенно владеть синтаксисом ХДЛ и уметь описать на нём желаемое поведение.
Ну так и саму концепцию RISC придумали не дураки, и посчитали правильно -- что в CISC-процессорах активно используется от силы 10% команд, а остальные -- эпизодически, вот и решили их выкинуть. Однако на сегодняшний день от их изначальной концепции осталось только выполнение операций исключительно в регистрах, и то есть определённые подвижки для ухода от этого в некоторых специфических случаях: внезапно оказалось, что эти самые редко используемые команды многократно ускоряют выполнение соответствующих классов задач, т. е. отнюдь не бесполезны, если речь идёт о вычислительных системах достаточно высокой производительности, а не минимальной стоимости и потребляемой мощности. Вот и набиты современные типа RISC-процессоры сотнями, а то и тысячами странных и редко используемых команд :) (хотя насколько странных, как EDMK в Системе 360, сейчас, пожалуй, не встречается)
Ну и если б такое управление TLB работало бы действительно хорошо, от него бы, в конечном итоге, не отказались бы, да и использовался бы такой подход намного шире.
Нет, не в курсе; я особо в MIPS не погружался -- так, полистал немного для общего развития, и всё. На практике с ними никогда сталкиваться не приходилось, вот и не углублялся. Но это уже тонкости реализации, а не архитектурно-концептуальный уровень (очевидно, что у современных мэйнфреймов z/Architecture TLB тоже несколько отличается от, скажем, использованного в System 370/145, чья микроархитектура была нами содрана и воплощена в ЕС-1035: там весь TLB аж из восьми (восьми!) элементов состоит, а управляется микропрограммно, насколько помню; однако для программиста эти тонкости совершенно безразличны, ибо на концептуальном уровне TLB ведёт себя одинаково на любых моделях).
Угу. Не столько даже тупиковая -- сделать полноценную ОС с виртуальной памятью и прочим на этом можно, и даже некоторые дополнительные возможности были бы доступны и реализовывались бы дёшево в плане скорости, но очень уж неудобно всё это дело было, поэтому и не прижилось. (Замечу в скобках, что подход IBM -- "нормальная" виртуальная память на основе страниц с "нормальным" MMU плюс архитектурная концепция множества адресных пространств плюс архитектурный же механизм "вызова программы" оказались намного элегантнее и эффективнее, чем Интеловские описатели сегментов и шлюзов вызова, хотя, в первом приближении, позволяют решить одни и те же задачи аппаратными (с точки зрения программиста) средствами, т.е. достаточно быстро -- в отличие от чисто программной реализации путём вызова соответствующих сервисов операционной системы, что всегда очень дорого).
А тем, кто влюбился, показать VAX-11, а потом попросить набросать концепцию суперскалярного процессора этой архитектуры :) Ага, с длиной кода команды от 1 до 36 байт :)))) В PDP-11, по крайней мере, выборку и декодирование команд сделать несложно -- длина хоть и переменная, но количество вариантов ограничено (1, 2 или 3 слова, т. е. 2/4/6 байтов), а однозначно определить её можно анализом первого слова (хотя в Системе 360 и её потомках анализ ещё проще: длину кода команды (тоже 2/4/6 байтов) определяют два старших бита первого байта). Собственно, поэтому мне VAX-11 и не нравится, хотя PDP-11 -- моя любимая 16-разрядная архитектура, а VAX лишь продолжил её идеи: просто DEC решила сделать мощную машину, а концептуальный подход использовала, который был успешным для маленькой и дешёвой машины; естественно, ничего из этого не вышло (VAX-11 получился слишком дорогим, чтоб вытеснить PDP-11 из её ниши, но при этом не имел шансов стать высокопроизводительным, чтоб действительно составить конкуренцию тем же мэйнфреймам IBM).
Честно говоря, не уверен. Что бизнесу нужны готовые специалисты -- это понятно, а Вы как раз в бизнесе и работаете, решаете реальные инженерные задачи. С другой стороны, нельзя подготовить исследователя/учёного, если у него кругозор ограничивается тем, что нужно и эффективно здесь и сейчас. Но это возвращаемся уже к общим проблемам образования -- в частности, к "целеполаганию" в образовании: а кого мы вообще готовим в том или ином учебном заведении? Думается, количество вузов, как я их понимаю, нужно сократить радикально -- раз в 10, а то и больше, -- и они должны готовить именно учёных; ну а для более приземлённых вещей типа обычных программистов или там "вериложников" -- условные техникумы и ПТУ. Ну, думаю, Вы понимаете идею.
Из школьного: вводят производные и интегралы в последних классах на уроках алгебры -- но чисто "сферически в вакууме", и основная масса учеников понятия не имеет, нафиг нужны эти математические извраты. А вводить можно было бы даже раньше, но в рамках физики -- механики, где прекрасно видно, как резко эти извраты упрощают решение многих задач, приближённых к реальности (преобразования между путём-скоростью-ускорением и т.п.). Как по мне, пользы от такого обучения было бы куда больше: и достаточно понятная, очевидная и практически применимая физика, и сразу математический аппарат для её обслуживания.
А мне вспомнился Терри Прачет и его "Народ", где "полуглавная героиня" -- девочка из британской королевской семьи, попавшая на почти необитаемый остров -- в один момент думает, что их (девочек знатного происхождения) учат лишь тому, что точно никогда не пригодится в реальной жизни :)
Мне это такой дикостью показалось: ведь жутко медленно и неэффективно по сравнению с аппаратной выборкой из таблиц переадресации, а последняя -- вещь весьма простая, чтоб на ней усиленно экономить.
Что, уже официально на RISC-V перешли? Я-то от образования далёк, поэтому не в теме, что там и как -- только по книжкам что-то вижу.
Но говорил я больше о том, что давать глубоко надо, конечно, современное, но упомянуть неплохо бы и существовавшие некогда другие подходы -- для общего развития, так сказать, но без траты сколько-нибудь значительного времени на это дело (кто заинтересуется историей -- сам найдёт, ему достаточно ключевые слова подсказать).
А я б про кэши и таблицы страниц рассказал бы в 16-17 лет, когда познакомился с этим на реальном железе... В общем, если человеку интересна некая тема, он и сам её изучает, а если неинтересна -- никакой вуз не поможет (и вопрос только в том, а нафига такой человек в вузе?)
Строго говоря, не обязательно, хотя во всех современных архитектурах, думается, это именно так. Навскидку из отличающихся "исторических" архитектур:
80286 с его теневыми регистрами для сегментов (хотя, подобно TLB, теневые сегментные регистры хранят информацию, полученную из таблиц в памяти, но, в отличие от TLB, это не "кэш" в том смысле, что каждый теневой регистр обновляется процессором не "по собственному желанию", а в строго определённый момент -- когда выполняется загрузка соответствующего сегментного регистра, т.е. по прямому указанию программиста). В IA-32 теневые регистры сохранены, но там появился уже и нормальный TLB, поскольку появилась нормальная страничная организация памяти;
PDP-11, где преобразование адресов основано на регистрах MMU: из-за малого объёма виртуального адресного пространства (64 Кбайта) нужды в таблицах переадресации, расположенных в ОЗУ, нет, и всё необходимое лежит прямо в MMU; соответственно, нужды в TLB тоже нет.
Поскольку процессор выполняет команды, для него выглядящие как набор битов (машинный код), а для человека -- как программа на языке ассемблера, то, очевидно, перед разбором того, как процессор устроен и работает, необходимо разобраться, как писать программы на ассемблере и как команды кодируются.
Поскольку ОС управляет выполнением программ, а последние, опять-таки, являются последовательностью команд ассемблера, то опять нужно понимать, что в реальности они из себя представляют, как выполняются на концептуальном (не физическом) уровне и т.д. -- знать про регистры, про адреса памяти и т.д. и т.п. Соответственно, базовый курс по ассемблеру должен предшествовать курсу по ОС.
Что касается ввода-вывода, то прежде чем браться за ОС и её драйверы, неплохо знать, как реально ведётся работа с устройствами -- а этого проще всего достигнуть написанием (или разбором готового) небольших программ, взаимодействующих с простыми устройствами типа UART на уровне регистров. Тогда станет достаточно очевидно, что ОС, во-первых, абстрагирует прикладные задачи от подобного "общения" с устройствами, зависящего от специфики устройств и т.д. и т.п., во-вторых, организует очереди запросов ввода-вывода, а в-третьих, разруливает обращения от разных задач к одним и тем же устройствам по определённым правилам.
В общем, курс по ОС в любом случае должен быть последним, ибо ОС имеет дело с низкоуровневыми сущностями, с которыми нужно быть более-менее знакомым до того, как начать разбираться с работой ОС.
Угу, я сталкивался с таким. На нашем предприятии всё писали на Коболе, на некоторых других в нашем городе -- тоже, но, по меньшей мере, на одном крупном заводе -- как раз на PL/I, причём тоже чисто прикладное и больше "экономическое", а не "научное" (Фортран тоже попадался -- но, есно, в "научном" коде). Мне начальство предложило на нём пару вспомогательных программ написать (какие-то преобразования чего-то во что-то, что потом на вход обычного Кобола идёт, и программа выхода для штатной сортировки), но я предпочёл наваять всё это на ассемблере :) Там действительно что-то достаточно низкоуровневое было, в одной из задач я даже EDMK использовал.
Но, кстати говоря, преобразование форматов на Коболе может оказаться достаточно сложным -- всё-таки, он очень ограничен по возможностям, если смотреть с высоты даже не сегодняшнего дня, а 70-х годов, и PL/I, хотя и сложен (скорей, не сложен даже, на очень уж объёмист: документация на него занимает больше места, чем документация на Фортран, Кобол, Алгол, РПГ и Ассемблер, вместе взятые), может оказаться более разумным выбором.
Ну, может быть... В качестве гипотезы: PL/I использовался, в первую очередь, самой IBM для системных и околосистемных вещей, а вот что бизнес-приложения, что "математику" народ писал, главным образом, на Коболе или Фортране соответственно. PL/I -- язык универсальный и позволял успешно писать любые вещи, но уж слишком он сложен по сравнению с этой парочкой, поэтому его ценность как замены для них наверняка была сомнительной, ну а околосистемные вещи, для чего он подходил намного лучше, конкурируя, по большому счёту, лишь с ассемблером, мало кто разрабатывал.
Ну а у IBM огромное количество кода, насколько знаю, написано на PL/I и PL/S -- а их мэйнфреймы живее всех живых и никуда исчезать не собираются (да и наши ЕС ЭВМ ушли по политико-экономическим, а не техническим причинам, шла бы история по другому пути -- их новые модели и сейчас бы работали, занимая свою нишу подобно IBMовским машинам). Впрочем, Вы это и без меня знаете :)
Не на двадцать, а очень-очень-очень намного больше. В частности, асинхронный ввод-вывод с уведомлением приложения о завершении операции -- основа ввода-вывода в OS/360, а её разработка началась ещё в первой половине 1960-х одновременно с разработкой самих машин -- первых мэйнфреймов Системы 360; первая, жутко обрезанная версия стала доступна пользователям в 1966-м. Правда, в прикладных программах обычно пользовались синхронным вводом-выводом, поскольку это проще для программиста, но асинхронщина была всегда доступной и использовалась, когда это было нужно.
Асинхронный ввод-вывод -- основа и "матери" Винды (VAX/VMS), и её "бабки" (RSX-11M), а это -- 1970-е годы.
Если закончивший вуз программист не способен за 1-2 недели самостоятельно освоить Кобол по документации (описанию языка), то какой, нафиг, это программист? Это дебил с дипломом. Кобол -- элементарнейший язык, и писать на нём "экономические" приложения, для чего он и создавался, легко и просто.
Бесконечности и НаНы не везде существуют, если рассматривать всю совокупность имеющихся платформ.
Если он вообще не инициализирован, т.е. в него никогда не выполнялась запись -- то да (в той ячейке, где он лежит, может находиться мусор). Однако если он равен нулю или любому другому определённому числовому значению, то и поведение, с точки зрения стандарта и языка, должно быть определённым: обращение к памяти по заданному им адресу. К чему это приведёт -- не забота компилятора, за это должен отвечать программист. (И да, нужна бы стандартная прагма, включающая и отключающая контроль за нулевыми указателями).
Как по мне, основная беда от UB связана не с тем, что, дескать, аппаратура как-то не так отработает и т.д. и т.п., а то, что компилятору позволено творить любую дичь, даже когда в реальности поведение будет определённым на любой сколько-нибудь "нормальной" платформе.
Возьмём, например, целочисленный знаковый тип размером 2 байта. Как известно, все современные "нормальные" платформы (а существуют ли современные "ненормальные", я, честно говоря, не знаю) для представления целых чисел используют дополнительный код. Соответственно, имея 16 бит, мы имеем диапазон от -32768 до +32767. Прибавление единицы к максимальному положительному значению технически даёт максимальное отрицательное: +32767 + 1 = -32768. И здесь возможны ровно два технически обоснованных результата:
операция сложения молча выполняется и даёт указанный абсолютно предсказуемый и технически корректный результат;
фиксируется возникновение переполнения, что, в конечном итоге, приводит к исключению (неважно, выполняется ли это чисто аппаратными средствами -- скажем, мэйнфреймы IBM умеют ловить такое переполнение, если это разрешено соответствующим битом маски, а на IA-32 aka x86 надо явным образом анализировать флаг OF с помощью команды INTO или же условным переходом).
На мой взгляд, подобные ситуации не должны объявляться как UB на уровне языка и компилятора, т.е. стандарт языка должен указывать, а компиляторы должны реализовывать генерацию кода, выполняющего требуемую операцию, не взирая на возможное (или даже гарантированно возникающее) переполнение -- они, разве что, должны выдать предупреждение, если видят, что переполнение возникнет. А ещё лучше иметь на уровне стандарта (и, естественно, конкретных компиляторов) некую прагму, которая позволяет стандартным образом включать и отключать контроль переполнения во время выполнения программы -- даже если такой контроль, как в случае с IA-32, влечёт за собой потенциальное снижение производительности из-за необходимости выполнения лишних команд. Тогда ситуация остаётся управляемой для программиста: он знает, где переполнение допустимо, а где -- нет, и может соответствующим образом настраивать поведение программы стандартным образом.
То же самое касается и многих других случаев UB. Скажем, для невыровненных указателей тоже можно предусмотреть прагму, заставляющую включать код их проверки, причём даже на платформах, где технически невыровненные доступы разрешены и работают корректно (такая проверка упрощает отлов невыровненных указателей, которые станут проблемой на других платформах), и прагму, обязывающую компилятор сгенерировать код, корректно работающий с невыровненными указателями (для IA-32 эта прагма де-факто ничего делать не будет, а вот на ряде других платформ при её использовании будет формироваться другой, более громоздкий код -- скажем, побайтовая загрузка четырёхбайтовой величины с последующей "сборкой" в регистре процессора). Ну и т.д. и т.п. Но вместо этого, как мы знаем, UB трактуется просто как право компилятора творить любую дичь, в том числе выкидывать сомнительный для него код.
Вообще-то, подавляющее число устройств ввода-вывода использует механизм прерываний, чтобы информировать процессор (систему) о тех или иных событиях -- например, о завершении ранее начатой операции. И этих прерываний более чем достаточно для переключения потоков (задач), таймер необходимым ни разу не является. Собственно, все настоящие ОС и переключают потоки по целой куче разных событий, а отнюдь не только по истечению времени; приоритеты выполнения не просто так придумали.
Наличие/отсутствие таймера к процессору отношения не имеет. Конкретно в IBM PC и всех последующих более-менее совместимых машинах он был. Изначально это была микросхема 8253 или 8254, один из каналов которого в качестве таймера, кидающегося прерываниями, и использовался; позднее таймер стал частью более сложных микросхем, но для программиста это роли не играет.
Возможно, мы используем термины не совсем идентичным образом, что может создавать проблемы с пониманием. Вообще, вытесняющая многозадачность -- это когда ОС может по своему усмотрению снять с процессора один поток и поставить другой. Таймер для этого не обязателен; скажем, ОС может передать управление вышедшему из ожидания завершения операции ввода-вывода высокоприоритетному потоку, сняв с процессора низкоприоритетный поток, который работал, пока высокоприоритетный поток вынужденно простаивал, ожидая завершение ввода-вывода. В кооперативной многозадачности такое невозможно: там поток должен сам тем или иным способом отдать управление. Таймер же нужен для реализации разделения времени, т.е. когда потокам выделяется определённый отрезок (квант) времени, в течение которого они могут непрерывно занимать процессор, и если поток весь свой квант выжрал, ОС принудительно снимает его с процессора и отдаёт процессор другому потоку -- и так до тех пор, пока все готовые к выполнению потоки не отработают свои кванты, и лишь после этого происходит возврат к первому из них. Таким образом, любая система с разделением времени будет системной с вытесняющей многозадачностью, но не каждая система с вытесняющей многозадачностью обязана быть системой с разделением времени (исторический пример -- OS/360, которая, возможно, вообще первой "большой и совсем-совсем настоящей" ОС в истории была; разделение времени там было необязательной опцией, но вытесняющая многозадачность была (почти) всегда, причём и в случае отсутствия таймера).
Чёткого определения ОС действительно нет, т.е. опять возвращаемся к терминологии. Для меня более-менее полноценная ОС -- это (а) средство управления ресурсами вычислительной системы (памятью, процессорным временем, периферией в широком смысле слова), распределения их между приложениями и самой ОС, и (б) набор сервисов, предоставляемых прикладным программам и абстрагирующих их от особенностей железа, насколько это возможно. MS DOS и CP/M, например, совсем полноценными ОС для меня не являются -- они однозадачные, а соответственно, в принципе не предусматривают разделения ресурсов между приложениями, а вот Винда с Линухом или упомянутая мной выше ОС/360 -- являются.
В советской терминологии -- не упреждающий, а ускоренный перенос.
Вообще, существует несколько вариаций этой идеи; в частности, в 2-битовых секциях Intel 3002 (наша К589ИК02) вместо сигналов P и G -- сигналы X и Y, чуть-чуть отличающиеся логикой формирования.
Они или их варианты много где использовались. Тут указали на процессор ЭВМ ЕС-1033 (под который, вроде как, выпуск К155ИП3 и наладили); К131ИП3 использовался в проце ЭВМ СМ-1600; КР531ИП3 -- в качестве сумматора в MMU процессора ЭВМ СМ-1420, и т.д.