Потоки (threads) и многопоточное выполнение программ (multi-threading). Пользовательские потоки и потоки ядра

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

Вступление

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

Вы можете захотеть загрузить файлы из необычного места, такого как сжатый/зашифрованный архив, или, например, из удаленной сетевой папки. Для этих особых ситуаций, SFML предоставляет третью функцию: loadFromStream . Эта функция считывает данные, используя абстрактный интерфейс sf::InputStream , который позволяет вам иметь собственную реализацию класса потока, который будет работать с SFML.

В этой статье будет рассказано, как писать и использовать ваши собственные классы потоков.

Стандартные потоки C++?

Как и многие другие языки, C++ уже содержит класс потока данных: std::istream . По факту, таких классов два: std::istream является только front-end решением, абстрактным интерфейсом к данным, получаемым из std::streambuf .

К сожалению, эти классы не дружелюбны к пользователю - решение нетривиальной задачи с использованием данных классов может стать очень сложным. Библиотека Boost.Iostreams стремится обеспечить простой интерфейс для стандартных потоков, но Boost - это большая зависимость.

По этой причине SFML предоставляет собственный потоковый класс, который, как мы надеемся, более простой и быстрый, нежели перечисленные выше.

Хотя добросовестное и регулярное проведение сплит-тестов может дать до 10% увеличения конверсии, существуют другие стратегии, способные приносить более ощутимые результаты. В этой статье мы рассмотрим одну из них, основанную на «капитальном ремонте» офферов и структуры маркетинговых воронок с учетом (user flow), проходящего через сайт.

Вашему вниманию — кейс от Бреда Смита (Brad Smith), являющегося одним из партнеров-основателей агентства Codeless Interactive и завсегдатаем таких проектов, как Kissmetrics, WordStream, AdEspresso и др. Он описал реальные примеры и пошаговый процесс оптимизации пользовательского потока . По результатам внедренных им мероприятий был достигнут 166% прирост новых лидов в течение 3 месяцев (см. иллюстрацию и комментарий ниже):

Результаты оптимизации пользовательского потока за 3 месяца по сравнению с предыдущим периодом (на средней части картинки показано, что количество привлеченных новых лидов (Contacts) увеличилось с 574 до 1 528, что составляет 166.2% рост)

Почему сплит-тестирование не всегда приносит ощутимый результат?

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

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

1. Во-первых, «крошечные изменения» в подавляющем большинстве приводят к «крошечным результатам» (если таковые вообще имеются). Более того, полученные в ходе сплит-тестирования результаты показывают одну стойкую, но неутешительную тенденцию: со временем показатели конверсии «откатываются» к средним значениям (см. график и комментарий ниже). Такой вывод был сделан сервисом PPC-аналитики WordStream на основании анализа деятельности тысяч аккаунтов контекстной рекламы AdWords, годовой рекламный бюджет которых составил свыше $3 000 000 000.

Пример результатов А/Б-теста: на графике синим цветом показан всплеск роста конверсии в начале тестирования и постепенное снижение показателей до среднего уровня, которое произошло в течение определенного временного промежутка

2. Во-вторых, практика тестирования требует наличия определенного объема данных для анализа. Это нужно, чтобы выборка считалась репрезентативной (достоверной). Например, если ваша посадочная страница не генерирует за месяц хотя бы 1 000 подписчиков, то вы не можете тестировать ее элементы. Точнее говоря, конечно же, это возможно, но полученные результаты нельзя будет считать достоверными из-за недостаточного объема данных. Другой пример: вы проводите А/Б-тест, имея 500 конверсий в месяц; результаты теста дают показатель 250 на 250 по испытываемым вариантам. Очевидно, что такой исход событий не позволяет выявить победителя. Нужен больший объем выборки.

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

Но и это еще не все…

Сплит-тесты почти никогда не могут обеспечить значительных результатов, так как в чистом виде приоритетная сфера их применения лежит в плоскости поверхностных изменений. Само по себе сплит-тестирование не затрагивает предварительного исследования элементов лендинга и не может дать ответ на вопрос о том, какой раздел landing page следует тестировать в первую очередь. На практике это означает, что маркетолог тратит уйму времени и сил на то, что является лишь крохотной частью всего процесса конверсии, пренебрегая более широким анализом того, что именно происходило до и после нажатия СТА-кнопки в лид-форме.

Как уже отмечалось выше, в качестве альтернативы можно использовать CRO стратегию, позволяющую получить более чем 10%-ный прирост коэффициента конверсии, фокусируясь при этом не на мелочах, а на усовершенствовании всего пользовательского потока, или так называемой « ».

Как работает оптимизация пользовательского потока?

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

— слева (для сайта электронной коммерции): контекстная реклама → товарный лендинг или карточка товара в интернет-магазине → покупка товара;
— справа (для сайта с платной подпиской или посадочной страницы): входящий трафик из социальных сетей → посадочная страница → подписка на email-рассылку

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

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

Squarespace предлагает красивые шаблоны, которые могут использоваться в различных рыночных нишах. Однако общий минус всех подобных конструкторов состоит в недостатке опций, позволяющих настроить работу сайта или landing page с учетом индивидуальных особенностей конкретного проекта

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

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

При идеальном стечении обстоятельств такой пользовательский опыт может позволить отдельным посетителям найти то, за чем они пришли, и совершить покупку здесь и сейчас. Однако не стоит забывать, что по данным авторитетного маркетингового агентства Moz наиболее лояльными клиентами становятся те, кто посетил сайт порядка 10 раз, а не совершил конверсионное действие в первые 1-3 визита.

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

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

Но если вы начнете анализировать пользовательские потоки, то сможете неоднократно убедиться, что многие люди даже не заходят на главную страницу. Они либо переходят с объявления контекстной рекламы прямо на landing page, либо вводят в поисковую систему коммерческий запрос и направляются сразу на товарный лендинг или страницу с описанием запрашиваемой услуги.

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

Три примера пользовательских потоков, где в качестве отправных точек выступают разные источники:
— слева: ссылка с результатов выдачи поисковых систем → landing page → подписка на рассылку;
— в центре: прямая ссылка на сайт из закладок или введенная прямо в адресную строку браузера → главная страница → страница с описанием товара или услуги → добавление в корзину → оплата;
— справа: объявление контекстной рекламы → лендинг → покупка

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

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

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

Оптимизация пользовательского потока происходит приблизительно по такой же схеме за исключением того, что вы расширяете этот процесс, перенося его на весь путь потенциального клиента: начиная от источника трафика и заканчивая путешествием по сайту в «точку назначения». При этом нужно связывать каждую веб-страницу — или отдельное письмо серийной (follow-up) рассылки — с предыдущей.

Вот примерный алгоритм того, как это может выглядеть на практике.

Шаг #1. Определите, откуда приходят пользователи (чтобы понять, что они ищут)

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

Чтобы смоделировать путешествие потребителя применительно к определенному онлайн-бизнесу, можно использовать сервис Customer Journey to Online Purchase от компании Google, помогающий выяснить, какие маркетинговые каналы чаще всего используют пользователи в той или иной маркетинговой нише (см. иллюстрацию и комментарий ниже):

Пример интерфейса Customer Journey to Online Purchase, иллюстрирующего, какие каналы используют потребители небольших (опция «Small») сайтов электронной коммерции (опция «Shopping»), действующих с таргетингом на США (опция «The USA»)

Комментарий к иллюстрации . Перечисленные выше опции можно задавать применительно к разным сферам и географическим локациям веб-сайтов. Чем левее на графике канал, тем менее готовым к покупке будет приходящий из него посетитель. На приведенном примере таковыми являются пользователи, привлеченные из органической выдачи поисковиков (Organic Research). Наиболее горячая целевая аудитория в этой нише — те, кто переходят на сайт по прямой ссылке (Direct), вводя ее в адресную строку браузера или активируя ее из закладок. Поэтому канал Direct расположен крайним справа. Подобным же образом анализируются , показанные ближе к центру графика.

По словам разработчиков Customer Journey to Online Purchase, исходными данными для этого сервиса являются результаты анализа миллионов пользовательских взаимодействий, собираемых Google Analytics.

Поэтому логичным продолжением этого шага оптимизации пользовательских потоков на лендинге или сайте должно быть рассмотрение собранных в системе Google Analytics данных вашего проекта (см. колонку «Источники/Каналы» (Sources/Mediums)). Вот как это может выглядеть на реальном примере:

Несложно заметить, что большинство пользователей приходят на сайт из первых 3 источников: органическая выдача поисковой системы (в таблице — «google/organic»), переходы по прямым ссылкам (в таблице — «direct») и платный поисковый трафик (в таблице — «google/cpc»).

Если наложить информацию об источниках трафика на данные о популярных страницах — для этого в системе Google Analytics есть специальный отчет «Top Content»,— то можно визуализировать и проследить, как перемещаются по сайту посетители, впервые привлеченные на веб-ресурс:

Пример того, как может выглядеть схема перемещения пользователей в разрезе источников трафика и посещаемых ими страниц сайта (примечание: часть конфиденциальных данных на иллюстрации скрыта)

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

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

2. Второй сегмент — это люди, привлекаемые с помощью платного поискового трафика. Они сразу направляются на landing page. С этой группой все ясно и понятно.

Шаг #2. Проанализируйте, какие элементы посещаемых страниц работают, а какие — нет

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

Эта работа предполагает построение так называемой системы микроконверсий — небольших взаимодействий и серий писем, которые получает человек, последовательно переходя от одной страницы или подписной формы (opt-in) к следующей (см. схему и комментарий ниже):

Схема, иллюстрирующая систему микроконверсий, которую должен пройти посетитель, прежде чем перейти на более высокий уровень лояльности: (1) главная страница → (2) переход на вложенную страницу через меню сайта → (3) реакция на полезный контент → (4) подписка на лендинге, «заточенном» под посетителей верхнего уровня воронки (TOFU) → (5) благодарственная страница с новым оффером (для перевода на средний уровень воронки (MOFU)) и email с полезным контентом → (6) переход и подписка на лендинге, «заточенном» под посетителей среднего уровня воронки (MOFU) → (7) благодарственная страница с новым оффером (для перевода на нижний уровень воронки (BOFU)) и email с полезным контентом → (8) лояльный подписчик и вход в продажу

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

Представленная выше схема может показаться слишком усложненной, однако практика показывает, что в подавляющем большинстве случаев необходимо 6-8 «касаний» с посетителем, чтобы добиться окончательной конверсии в покупку. Игнорирование этого принципа часто можно наблюдать, когда через настроенные в Facebook или ВКонтакте рекламные объявления холодный трафик направляется сразу на landing page с коммерческим оффером. Оптимизация пользовательского потока в таком случае предполагает внедрение так называемой системы взращивания клиентов (lead nurturing) — специально разработанной кампании (drip campaign) — включая последовательную серию писем,— направленной на повышение лояльности новых посетителей сайта.

Когда проблема выявлена, остальное — дело техники. Например, можно использовать доступный функционал в соцсетях, чтобы автоматически добавлять новые контакты для дальнейшего взаимодействия с ними через сервисы почтовой рассылки или Saas-платформы автоматизации маркетинга (MailChimp, Infusionsoft, HubSpot и др.):

На иллюстрации показано, как с помощью полезной CRM AdEspresso настраивается автоматическое добавление новых контактов из Facebook в HubSpot для последующей работы с лидами

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

Для такого анализа лучше всего использовать специализированные сервисы, которые позволяют генерировать наглядные визуальные изображения (тепловые карты), характеризующие поведение онлайн-пользователей на исследуемом объекте. Зачастую такие кейсы являются более информативными, с ними легче работать и проще доносить полученные результаты до клиентов и начальства. Далее в статье будут рассмотрены примеры такого анализа, полученные с использованием соответствующего функционала SaaS-платформы CrazyEgg.

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

Карта прокрутки позволяет оценить, насколько далеко посетитель опускается вниз страницы в ходе изучения контента, задействуя скроллинг. Проиллюстрированные выше результаты показывают, что никто не переходит так называемую «линию сгиба» (below the fold), а читает лишь то, что представлено на первом экране

Чтобы интерпретировать представленную на картинке информацию, нужно обратить внимание на цветовую шкалу, расположенную в правом нижнем углу: чем «горячее» цвет, тем больше внимания пользователей привлекает окрашенная в него часть страницы, а чем «холоднее» — тем меньше посетителей добрались до соответствующей части веб-страницы или лендинга (как до дна голубого океана, куда почти никто не погружается).

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

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

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

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

Шаг #3. Оптимизируйте дизайн и контент страниц с учетом особенностей пользовательского потока

Что возникает в вашем воображении, когда вы слышите слово «дизайнер» (designer)? Большинство скажут, что это человек, создающий внешний вид лендинга. Однако у английского слова «designer» есть еще несколько значений, два из которых — конструктор, проектировщик. Поэтому (в глубинном смысле) дизайн посадочной страницы — это не то, как она выглядит, а то, как она работает .

Такое понимание предполагает, что дизайн landing page должен разрабатываться с мыслью о том, какие конверсионные цели должны быть достигнуты с ее помощью. В качестве последних может выступать добавление в корзину (заказ или покупка), но чаще — заполнение лид-формы.

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

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

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

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

На иллюстрации изображена таблица распределения кликов среди всех кликабельных элементов страницы (СТА-кнопки, текстовые ссылки, картинки и др.). В подавляющем большинстве случаев (45%) посетители кликают именно на СТА-кнопку (Download Now) в лид-форме. Это является показательным признаком конверсионной страницы

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

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

Например, чтобы решить, какую лид-форму — длинную или короткую — размещать на посадочной странице, нужно понимать особенности конкретного пользовательского потока:

  • если посетители относятся к категории TOFU (находятся в верхней части воронки и мало знакомы с брендом), то нужна форма с минимальным количеством полей для заполнения;
  • если же большая часть трафика представляют группу BOFU (находятся в нижней части воронки, уже получали полезный контент и лояльно относятся к бренду), то при необходимости можно использовать более подробную лид-форму.

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

Однопоточные и многопоточные процессы

К сожалению, до сих пор мышление многих программистов при разработке программ остается чисто последовательным. Не учитываются широкие возможности параллелизма , в частности, многопоточности. Последовательный (однопоточный) процесс – это процесс, который имеет только один поток управления (control flow ), характеризующийся изменением его счетчика команд . Поток (thread) – это запускаемый из некоторого процесса особого рода параллельный процесс, выполняемый в том же адресном пространстве, что и процесс-родитель.

Рис. 10.1. Однопоточный и многопоточный процессы.

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

Многопоточность имеет большие преимущества:

· Увеличение скорости (по сравнению с использованием обычных процессов). Многопоточность основана на использовании облегченных процессов (lightweight processes) ,работающих в общем пространстве виртуальной памяти. Благодаря многопоточности, не возникает больше неэффективных ситуаций, типичных для классической системы UNIX, в которой каждая команда shell (даже команда вывода содержимого текущей директории ls исполнялась как отдельный процесс , причем в своем собственном адресном пространстве. В противоположность облегченным процессам, обычные процессы (имеющие собственное адресное пространство) часто называют тяжеловесными (heavyweight) .

· Использование общих ресурсов . Потоки одного процесса используют общую память и файлы.

· Экономия . Благодаря многопоточности, достигается значительная экономия памяти, по причинам, объясненным выше. Также достигается и экономия времени, так как переключение контекста на облегченный процесс, для которого требуется только сменить стек и восстановить значения регистров, значительно быстрее, чем на обычный процесс.

Использование мультипроцессорных архитектур . Это особенно важно в настоящее время, в период широкого использования многоядерных гибридных и многопроцессорных систем. Именно многопоточность программ, основанная на многоядерности процессора, дает возможность, наконец, почувствовать реальные преимущества параллельного выполнения.

История многопоточности

Как небезынтересно отметить, один из первых шагов на пути к широкому использованию многопоточности, по-видимому, был сделан в 1970-е годы советскими разработчиками компьютерной аппаратуры и программистами. МВК "Эльбрус-1", разработанный в 1979 году, поддерживал в аппаратуре и операционной системе эффективную концепцию процесса, которая была близка к современному понятию облегченного процесса. В частности, процесс в "Эльбрусе" однозначно характеризовался своим стеком. Иначе говоря, все процессы были облегченными и исполнялись в общем пространстве виртуальной памяти – других процессов в "Эльбрусе" просто не было!

Концепция многопоточности начала складываться, по-видимому, с 1980-х гг. в системе UNIX и ее диалектах. Наиболее развита многопоточность была в диалекте UNIX фирмы AT&T, на основе которого, как уже отмечалось в общем историческом обзоре, была разработана система Solaris. Все это отразилось и в стандарте POSIX , в который вошла и многопоточность, наряду с другими базовыми возможностями UNIX .

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

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

Важный шаг вперед сделали авторы языка Java и Java -технологии, первая версия реализации которых была выпущена в 1995 г. Именно в Java впервые многопоточность была реализована на уровне конструкций языка и базовых библиотек. В частности, в Java введен класс Thread ,представляющий поток , и операции над ним в виде специальных методов и конструкций языка.

Платформа.NET , появившаяся в 2000 г., предложила свой механизм многопоточности, который фактически является развитием идей Java .

Различие подходов к многопоточности в разных ОС и на разных платформах разработки программ сохраняется и до настоящего времени, что приходится постоянно учитывать разработчикам. Для прикладных программ мы рекомендуем реализовывать многопоточность на платформе Java или.NET , что наиболее удобно и позволяет использовать высокоуровневые понятия и конструкции. Однако в нашем курсе, посвященном операционным системам, мы, естественно, больше внимания уделяем системным вопросам многопоточности и ее реализации в операционных системах.

Пользовательские потоки и потоки ядра

Модели многопоточности .Реализация многопоточности в ОС, как и многих других возможностей, имеет несколько уровней абстракции. Самый высокий из них – пользовательский уровень. С точки зрения пользователя и его программ, управление потоками реализовано через библиотеку потоков пользовательского уровня (user threads) Подробнее конкретные операции над пользовательскими потоками будут рассмотрены немного позже. Пока отметим лишь, что существует несколько моделей потоков пользовательского уровня, среди которых:

· POSIX Pthreads – потоки, специфицированные стандартом POSIX и используемые в POSIX -приложениях (рассмотрены позже в данной лекции);

· Mac C-threads – пользовательские потоки в системе MacOS;

· Solaris threads – пользовательские потоки в ОС Solaris (рассмотрены позже в данной лекции).

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

· Windows 95 /98/NT/2000/XP/2003/2008/7;

· BeOS ;

Существуют различные модели многопоточности – способы отображения пользовательских потоков в потоки ядра. Теоретически возможны (и на практике реализованы) следующие модели многопоточности:

Модель много / один (many-to-one) отображение нескольких пользовательских потоков в один и тот же поток ядра. Используется в операционных системах, не поддерживающих множественные системные потоки (например, с целью экономии памяти).

Рис. 10.2. Схема модели многопоточности "много / один".

Модель один / один (one-to-one) – взаимно-однозначное отображение каждого пользовательского потока в определенный поток ядра. Примеры ОС, использующих данную модель, - Windows 95 /98/NT/2000/XP/2003/2008/7; OS/2 .

Рис. 10.3. Схема модели многопоточности "один / один".

Модель много / много (many-to-many) – модель, допускающая отображение нескольких пользовательских потоков в несколько системных потоков. Такая модель позволяет ОС создавать большое число системных потоков. Характерным примером ОС, использующей подобную модель, является ОС Solaris, а также Windows NT / 2000 / XP / 2003 / 2008 / 7 с пакетом ThreadFiber .

Рис. 10.4. Схема модели многопоточности "много / много".

Проблемы многопоточности

Многопоточность – весьма сложная, еще не полностью изученная и, тем более, не полностью формализованная область, в которой имеется много интересных проблем. Рассмотрим некоторые из них.

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

Прекращение потоков . Важной проблемой является проблема прекращения потоков: например, если родительский поток прекращается, то должен ли при этом прекращаться дочерний поток ? Если прекращается стандартный процесс, создавший несколько потоков, то должны ли прекращаться все его потоки? Ответы на эти вопросы в разных ОС неоднозначны.

Обработка сигналов . Сигналы в UNIX – низкоуровневый механизм обработки ошибочных ситуаций. Примеры сигналов: SIGSEGV - нарушение сегментации (обращение по неверному адресу, чаще всего по нулевому); SIGKILL – сигнал процессу о выполнении команды kill его уничтожения. Пользователь может определить свою процедуру-обработчик сигнала системным вызовом signal . Проблема в следующем: как распространяются сигналы в многопоточных программах и каким потоком они должны обрабатываться? В большинстве случаев этот вопрос решается следующим образом: сигнал обрабатывается потоком, в котором он сгенерирован, и влияет на исполнение только этого потока. В более современных ОС (например, Windows 2000 и более поздних версиях Windows ), основанных на объектно-ориентированной методологии, концепция сигнала заменена более высокоуровневой концепцией исключения (exception) .Исключение распространяется по стеку потока в порядке, обратном порядку вызовов методов, и обрабатывается первым из них, в котором система находит подходящий обработчик. Аналогичная схема обработки исключений реализована в Java и в.NET .

Группы потоков . В сложных задачах, например, задачах моделирования, при большом числе разнородных потоков, возникает потребность в их структурировании с помощью концепции группы потоков – совокупности потоков, имеющей свое собственное имя, над потоками которой определены групповые операции . Наиболее удачно, с нашей точки зрения, группы потоков реализованы в Java (с помощью классаThreadGroup ). Следует отметить также эффективную реализацию пулов потоков (ThreadPool) в.NET .

Локальные данные потока (thread-local storage - TLS) – данные, принадлежащие только определенному потоку и используемые только этим потоком. Необходимость в таких данных очевидна, так как многопоточность – весьма важный метод распараллеливания решения большой задачи, при котором каждый поток работает над решением порученной ему части. Все современные операционные системы и платформы разработки программ поддерживают концепцию локальных данных потока.

Синхронизация потоков . Поскольку потоки, как и процессы могут использовать общие ресурсы и реагировать на общие события, необходимы средства их синхронизации. Эти средства подробно рассмотрены позже в данном курсе.

Тупики (deadlocks) и их предотвращение . Как и процессы, потоки могут взаимно блокировать друг друга (т.е. может создаться ситуация deadlock ), при их неаккуратном программировании. Меры по борьбе с тупиками подробно рассмотрены позже в данном курсе.

Потоки POSIX (Pthreads)

В качестве конкретной модели многопоточности рассмотрим потоки POSIX (напомним, что данная аббревиатура расшифровывается как Portable Operating Systems Interface of uniX kind – стандарты дляпереносимых ОС типа UNIX ). Многопоточность в POSIX специфицирована стандартом IEEE 1003.1c, который описывает API для создания и синхронизации потоков . Отметим, что POSIX -стандарт API определяет лишь требуемое поведение библиотеки потоков. Реализация потоков оставляется на усмотрение авторов конкретной POSIX -совместимой библиотеки. POSIX -потоки распространены в ОС типа UNIX , а также поддержаны, с целью совместимости программ, во многих других ОС, например, Solaris и Windows NT.

Стандарт POSIX определяет два основных типа данных для потоков: pthread_t – дескриптор потока ; pthread_attr_t – набор атрибутов потока .

Стандарт POSIX специфицирует следующий набор функций для управления потоками :

· pthread_create(): создание потока

· pthread_exit():завершение потока (должна вызываться функцией потока при завершении)

· pthread_cancel():отмена потока

· pthread_join():заблокировать выполнение потока до прекращения другого потока, указанного в вызове функции

· pthread_detach():освободить ресурсы занимаемые потоком (если поток выполняется, то освобождение ресурсов произойдёт после его завершения)

Модели многопоточности. Реализация многопоточности в ОС, как и многих других возможностей, имеет несколько уровней абстракции. Самый высокий из них – пользовательский уровень. С точки зрения пользователя и его программ, управление потоками реализовано через библиотеку потоков пользовательского уровня (user threads). Подробнее конкретные операции над пользовательскими потоками будут рассмотрены немного позже. Пока отметим лишь, что существует несколько моделей потоков пользовательского уровня, среди которых:

  • POSIX Pthreads – потоки, специфицированные стандартом POSIX и используемые в POSIX-приложениях (рассмотрены позже в данной лекции);
  • Mac C-threads – пользовательские потоки в системе MacOS;
  • Solaris threads – пользовательские потоки в ОС Solaris (рассмотрены позже в данной лекции).

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

  • Windows 95/98/NT/2000/XP/2003/2008/7;
  • Solaris;
  • Tru64 UNIX;
  • BeOS;
  • Linux.

Существуют различные модели многопоточности – способы отображения пользовательских потоков в потоки ядра. Теоретически возможны (и на практике реализованы) следующие модели многопоточности:

Модель много / один (many-to-one) – отображение нескольких пользовательских потоков в один и тот же поток ядра. Используется в операционных системах, не поддерживающих множественные системные потоки (например, с целью экономии памяти). Данная модель изображена на рис. 10.2 .

Рис. 10.2. Схема модели многопоточности "много / один".

Модель один / один (one-to-one) – взаимно-однозначное отображение каждого пользовательского потока в определенный поток ядра. Примеры ОС, использующих данную модель, - Windows 95/98/NT/2000/XP/2003/2008/7; OS/2. Данная модель изображена на рис. 10.3 .

Рис. 10.3. Схема модели многопоточности "один / один".

Модель много / много (many-to-many) – модель, допускающая отображение нескольких пользовательских потоков в несколько системных потоков. Такая модель позволяет ОС создавать большое число системных потоков. Характерным примером ОС, использующей подобную модель, является ОС Solaris, а также Windows NT / 2000 / XP / 2003 / 2008 / 7 с пакетом ThreadFiber . Данная модель изображена на рис. 10.4 .

Рис. 10.4. Схема модели многопоточности "много / много".

Конец работы -

Эта тема принадлежит разделу:

В лекции рассматриваются понятие потока thread и многопоточное выполнение multi-threading

В лекции рассматриваются понятие потока thread и многопоточное выполнение multi threading модели многопоточности пользовательские потоки и.. содержание введение однопоточные и многопоточные процессы история многопоточности пользовательские..

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

Что будем делать с полученным материалом:

Если этот материал оказался полезным ля Вас, Вы можете сохранить его на свою страничку в социальных сетях:

Все темы данного раздела:

Однопоточные и многопоточные процессы
К сожалению, до сих пор мышление многих программистов при разработке программ остается чисто последовательным. Не учитываются широкие возможности параллелизма, в частности, многопоточности. Последо

История многопоточности
Как небезынтересно отметить, один из первых шагов на пути к широкому использованию многопоточности, по-видимому, был сделан в 1970-е годы советскими разработчиками компьютерной аппаратуры и програм

Проблемы многопоточности
Многопоточность – весьма сложная, еще не полностью изученная и, тем более, не полностью формализованная область, в которой имеется много интересных проблем. Рассмотрим некоторые из них.

Потоки и процессы в Solaris
В ОС Solaris, как уже было отмечено, используется модель потоков много / много. Кроме того, в системе используется также уже известное нам понятие облегченный процесс (ligh

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

Ключевые термины
Mac C-threads – пользовательские потоки в системе MacOS. POSIX Pthreads – потоки, специфицированные стандартом POSIX и используемые в POSIX-приложениях. Solaris threads – пользова

Модель много / много- модель многопоточности,при которой различные пользовательские потокимогут быть отображены в различные потоки ядра
Модель много / один- модель многопоточности, при которой несколько пользовательских потоковмогут быть отображены в один поток ядра

Краткие итоги
Многопоточность (multi-threading) – современное направление программирования, особенно актуальное в связи с широким распространением параллельных компьютерных архитектур. Поток – особый вид процесс

Вопросы
Что такое поток? Чем отличаются однопоточные и многопоточные процессы? В чем преимущества многопоточности? В какой системе впервые было реализовано понятие процесса

Упражнения
Проанализируйте и опишите преимущества, недостатки и проблемы многопоточности. Реализуйте модель многопоточности один/один. Реализуйте модель многопоточности много/один.

Темы для курсовых работ, рефератов, эссе
История концепции потока и многопоточности в операционных системах и языках программирования (реферат). Обзор многопоточности в UNIX, Linux, Solaris (реферат). Обзор многопо

Потоки (threads) и многопоточное выполнение программ (multi-threading)

Однопоточные и многопоточные процессы

Последовательный (однопоточный) процесс – это процесс, который имеет только один поток управления (control flow), характеризующийся изменением его счетчика команд. Поток (thread) – это запускаемый из некоторого процесса особого рода параллельный процесс, выполняемый в том же адресном пространстве, что и процесс-родитель. Схема организации однопоточного и многопоточного процессов изображена на рис. 1.

Рис. 11. Однопоточный и многопоточный процессы.

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

Многопоточность имеет большие преимущества:

  • Увеличение скорости (по сравнению с использованием обычных процессов). Многопоточность основана на использовании облегченных процессов (lightweight processes) ,работающих в общем пространстве виртуальной памяти. Благодаря многопоточности, не возникает больше неэффективных ситуаций, типичных для классической системы UNIX.
  • Использование общих ресурсов . Потоки одного процесса используют общую память и файлы.
  • Экономия . Благодаря многопоточности, достигается значительная экономия памяти, по причинам, объясненным выше. Также достигается и экономия времени, так как переключение контекста на облегченный процесс, для которого требуется только сменить стек и восстановить значения регистров, значительно быстрее, чем на обычный процесс.

Использование мультипроцессорных архитектур . Это особенно важно в настоящее время, в период широкого использования многоядерных гибридных и многопроцессорных систем. Именно многопоточность программ, основанная на многоядерности процессора, дает возможность, наконец, почувствовать реальные преимущества параллельного выполнения.



Пользовательские потоки и потоки ядра

Модели многопоточности . Реализация многопоточности в ОС, как и многих других возможностей, имеет несколько уровней абстракции. Самый высокий из них – пользовательский уровень. С точки зрения пользователя и его программ, управление потоками реализовано через библиотеку потоков пользовательского уровня (user threads) Отметим, что существует несколько моделей потоков пользовательского уровня.

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

  • Windows 95/98/NT/2000/XP/2003/2008/7;
  • Solaris;
  • Tru64 UNIX;
  • BeOS;
  • Linux.

Существуют различные модели многопоточности – способы отображения пользовательских потоков в потоки ядра. Теоретически возможны (и на практике реализованы) следующие модели многопоточности:

Модель много / один (many-to-one) – отображение нескольких пользовательских потоков в один и тот же поток ядра. Используется в операционных системах, не поддерживающих множественные системные потоки (например, с целью экономии памяти). Данная модель изображена на рис. 2.

Рис. 10.2. Схема модели многопоточности "много / один".

Модель один / один (one-to-one) – взаимно-однозначное отображение каждого пользовательского потока в определенный поток ядра. Примеры ОС, использующих данную модель, - Windows 95/98/NT/2000/XP/2003/2008/7; OS/2. Данная модель изображена на рис. 3.

Рис. 10.3. Схема модели многопоточности "один / один".

Модель много / много (many-to-many) – модель, допускающая отображение нескольких пользовательских потоков в несколько системных потоков. Такая модель позволяет ОС создавать большое число системных потоков. Характерным примером ОС, использующей подобную модель, является ОС Solaris, а также Windows NT / 2000 / XP / 2003 / 2008 / 7 с пакетом ThreadFiber . Данная модель изображена на рис. 4.

Рис. 4. Схема модели многопоточности "много / много".

Потоки в Windows 2000

Как уже отмечалось, в системе Windows реализована модель многопоточности "один / один". Каждый поток содержит:

  • идентификатор потока (thread id);
  • набор регистров
  • отдельные стеки для пользовательских и системных процедур;
  • область памяти для локальных данных потока (thread-local storage – TLS).

Проблемы многопоточности

Многопоточность – весьма сложная, еще не полностью изученная и, тем более, не полностью формализованная область, в которой имеется много интересных проблем. Рассмотрим некоторые из них.

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

Прекращение потоков . Важной проблемой является проблема прекращения потоков: например, если родительский поток прекращается, то должен ли при этом прекращаться дочерний поток? Если прекращается стандартный процесс, создавший несколько потоков, то должны ли прекращаться все его потоки? Ответы на эти вопросы в разных ОС неоднозначны.

Обработка сигналов . Сигналы в UNIX – низкоуровневый механизм обработки ошибочных ситуаций. Примеры сигналов: SIGSEGV - нарушение сегментации (обращение по неверному адресу, чаще всего по нулевому); SIGKILL – сигнал процессу о выполнении команды kill его уничтожения. Пользователь может определить свою процедуру-обработчик сигнала системным вызовом signal . Проблема в следующем: как распространяются сигналы в многопоточных программах и каким потоком они должны обрабатываться? В большинстве случаев этот вопрос решается следующим образом: сигнал обрабатывается потоком, в котором он сгенерирован, и влияет на исполнение только этого потока. В более современных ОС (например, Windows 2000 и более поздних версиях Windows), основанных на объектно-ориентированной методологии, концепция сигнала заменена более высокоуровневой концепцией исключения (exception) .Исключение распространяется по стеку потока в порядке, обратном порядку вызовов методов, и обрабатывается первым из них, в котором система находит подходящий обработчик. Аналогичная схема обработки исключений реализована в Java и в.NET.

Группы потоков . В сложных задачах, например, задачах моделирования, при большом числе разнородных потоков, возникает потребность в их структурировании и помощью концепции группы потоков – совокупности потоков, имеющей свое собственное имя, над потоками которой определены групповые операции. Наиболее удачно, с нашей точки зрения, группы потоков реализованы в Java (с помощью класса ThreadGroup ). Следует отметить также эффективную реализацию пулов потоков (ThreadPool) в.NET.

Локальные данные потока (thread-local storage - TLS) – данные, принадлежащие только определенному потоку и используемые только этим потоком. Необходимость в таких данных очевидна, так как многопоточность – весьма важный метод распараллеливания решения большой задачи, при котором каждый поток работает над решением порученной ему части. Все современные операционные системы и платформы разработки программ поддерживают концепцию локальных данных потока.

Синхронизация потоков . Поскольку потоки, как и процессы могут использовать общие ресурсы и реагировать на общие события, необходимы средства их синхронизации.

Тупики (deadlocks) и их предотвращение . Как и процессы, потоки могут взаимно блокировать друг друга (т.е. может создаться ситуация deadlock ), при их неаккуратном программировании.

42. Файловые системы. Обзор.

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

Файловая система – это набор спецификаций и соответствующее им программное обеспечение, которые отвечают за создание, уничтожение, организацию, чтение, запись, модификацию и перемещение файловой информации, а также за управление доступом к файлам и за управление ресурсами, которые используются файлами. Именно файловая система определяет способ организации данных на диске или на каком-нибудь ином носителе данных. В качестве примера можно привести файловую систему FAT, реализация для которой имеется в абсолютном большинстве ОС, работающих в современных ПК1.

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

  • ♦ создание, удаление, переименование (и другие операции) именованных наборов данных (именованных файлов) из своих программ или посредством специальных управляющих программ, реализующих функции интерфейса пользователя с его данными и активно использующих систему управления файлами;
  • ♦ работа с не дисковыми периферийными устройствами как с файлами;
  • ♦ обмен данными между файлами, между устройствами, между файлом и уст-

ройством (и наоборот);

  • ♦ работа с файлами с помощью обращений к программным модулям системы

управления файлами (часть API ориентирована именно на работу с файлами);

  • ♦ защита файлов от несанкционированного доступа.

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

Другими словами, термин «файловая система» определяет, прежде всего,

принципы доступа к данным, организованным в файлы. Этот же термин часто ис-

пользуют и по отношению к конкретным файлам, расположенным на том или ином

носителе данных. А термин «система управления файлами» следует употреблять

по отношению к конкретной реализации файловой системы, то есть это – комплекс

программных модулей, обеспечивающих работу с файлами в конкретной операци-

онной системе.

Следует ещё раз заметить, что любая система управления файлами не сущест-

вует сама по себе – она разработана для работы в конкретной ОС. В качестве при-

мера можно сказать, что всем известная файловая система FAT (file allocation table)

имеет множество реализации как система управления файлами. Так, система, полу-

чившая это название и разработанная для первых персональных компьютеров, на-

зывалась просто FAT (сейчас её называют FAT-12). Её разрабатывали для работы с

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

Потом её усовершенствовали для работы с жесткими дисками большего объёма, и

эта новая реализация получила название FAT-16. Это название файловой системы

мы используем и по отношению к системе управления файлами самой MS-DOS.

Реализацию же системы управления файлами для OS/2, которая использует основ-

ные принципы системы FAT, называют super-FAT; основное отличие – возмож-

ность поддерживать для каждого файла расширенные атрибуты. Есть версия системы управления файлами с принципами FAT и для Windows 95/98, для Windows

NT и т. д. Другими словами, для работы с файлами, организованными в соответствии с некоторой файловой системой, для каждой ОС должна быть разработана соответствующая система управления файлами. Эта система управления файлами будет работать только в той ОС, для которой она и создана; но при этом она позволит работать с файлами, созданными с помощью системы управления файлами другой ОС, работающей по тем же основным принципам файловой системы.

Файловая система FAT

Как мы уже отмечали, аббревиатура FAT (file allocation table) расшифровывается как «таблица размещения файлов». Этот термин относится к линейной табличной структуре со сведениями о файлах – именами файлов, их атрибутами и другими данными,

определяющими местонахождение файлов (или их фрагментов) в среде FAT. Элемент FAT определяет фактическую область диска, в которой хранится начало физического файла. В файловой системе FAT логическое дисковое пространство любого логиче-

ского диска делится на две области (рис. 4.6): системную область и область дан-

Рис.4.6. Структура логического диска

R | Sec | Fat1 | Fat2 | Dir | Каталоги и файлы

________________________________________________________

Системная область | Область данных

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

Загрузочной записи (boot record, BR);

Зарезервированных секторов (reserved sector, ResSecs);

Таблицы размещения файлов (file allocation table, FAT);

Корневого каталога (root directory, RDir).

Таблица размещения файлов

Таблица размещения файлов является очень важной информационной структурой. Можно сказать, что она представляет собой карту (образ) области данных, в которой описывается состояние каждого участка области данных. Область данных разбивают на так называемые кластеры. Кластер представляет собой один или несколько смежных секторов в логическом дисковом адресном пространстве (точнее – только в области данных). В таблице FAT кластеры, принадлежащие одному файлу (некорневому каталогу), связываются в цепочки. Для указания номера кластера и системе управления файлами FAT-16 используется 16-битовое слово, следовательно, можно иметь до 216 = 65536 кластеров (с номерами от 0 до 65535). Кластер – это минимальная адресуемая единица дисковой памяти, выделяемая файлу (или некорневому каталогу). Файл или каталог занимает целое число кластеров. Последний кластер при этом может быть задействован не полностью, что приведет к заметной потере дискового пространства при большом размере кластера. На дискетах кластер занимает один или два сектора, а на жёстких дисках – в зависимости от объёма раздела.

FAT32 - последняя версия файловой системы FAT и улучшение предыдущей версии, известной как FAT16. Она была создана, чтобы преодолеть ограничения на размер тома в FAT16, позволяя при этом использовать старый код программ MS-DOS и сохранив формат. FAT32 использует 32-разрядную адресацию кластеров. FAT32 появилась вместе с Windows 95 OSR2.

NTFS (от англ. New Technology File System - «файловая система новой технологии») - стандартная файловая система для семейства операционных систем Microsoft Windows NT.

NTFS заменила использовавшуюся в MS-DOS и Microsoft Windows файловую систему FAT. NTFS поддерживает системуметаданных

И использует специализированные структуры данных для хранения информации о файлах для улучшения производительности, надёжности и эффективности использования дискового пространства. NTFS хранит информацию о файлах в главной файловой таблице - Master File Table (MFT). NTFS имеет встроенные возможности разграничивать доступ к данным для различных пользователей и групп пользователей (списки контроля доступа - Access Control Lists (ACL)), а также назначать квоты (ограничения на максимальный объём дискового пространства, занимаемый теми или иными пользователями). NTFS использует систему журналирования USN для повышения надёжности файловой системы.

43. Управление памятью в операционной системе. Типы адресов.

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

Следует иметь в виду важную особенность основной памяти. В компьютерных архитектурах имеется два различных способа нумерации байтов в слове. По традиции будем представлять себе память как линейный массив, расположенный "слева направо", такой, что адреса слов, находящихся левее, меньше, чем адреса слов, находящихся правее. Каждое слово делится на байты, имеющие в слове свои номера – 0, 1 и т.д.. Например, в 64-разрядных системах в слове 8 байтов, с номерами от 0 до 7, в более старых 16-разрядных (x86) – два байта, с номерами 0 и 1. Если нумерация байтов в слове начинается слева, т.е. начиная со старших битов, то такую архитектуру принято называть big endian , если же справа, т.е. начиная с младших битов, то little endian. Например, при big endian – архитектуре 32-разрядного процессора байты двух соседних слов памяти нумеруются так: 0, 1, 2, 3, 0, 1, 2, 3. При little endian же архитектуре нумерация будет иной: 3, 2, 1, 0, 3, 2, 1, 0. Представим теперь, что мы хотим рассматривать эти же два слова как массив байтов длиной 8 и записать туда байт за байтом символы строки: "ЭТОТЕКСТ" (всего – 8 символов). Такая операция при обеих архитектурах будет выполнена одинаково, т.е. последовательные байты получат именно эти значения. Затем рассмотрим результат снова, но уже как последовательность их двух слов. Каково будет содержимое этих слов? При big endian – архитектуре сюрпризов не будет: первое слово – "ЭТОТ", второе "ЕКСТ". Однако при little endian – архитектуре результат будет совсем иным: первое слово – "ТОТЭ", второе – "ТСКЕ" ! Не забудем, что при обработке целого слова в little endian – архитектуре байты как бы "переставляются" в обратном порядке. Разумеется, это неудобно. С подобной проблемой автор столкнулся при переносе написанного им компилятора с архитектуры SPARC (big endian) на архитектуру Intel x86 (little endian), используя типы byte и word на Турбо-Паскале. Подобная операция типична для системных программ, например, таблица идентификаторов в компиляторе должна содержать как символы идентификатора (последовательность байтов), так и другую информацию о нем (длину, ссылки в различные таблицы и т.д.). Поэтому при little endian – архитектуре приходится хранить и обрабатывать байтовые массивы и массивы слов отдельно, и нельзя изменять точку зрения на одну и ту же область памяти и рассматривать ее то как массив байтов, то как массив слов.

Пример little endian – архитектуры – x86. Пример big endian – архитектуры – SPARC. При программировании на языках высокого уровня разработчику, как правило, не приходится учитывать это различие. Однако если при реализации распределения памяти требуется одну и ту же область памяти рассматривать то как массив слов, то как массив байтов, то для little endian – архитектур могут быть "сюрпризы", связанные с тем, что при записи в память как в массив слов байты как бы переставляются.

Основная память – это неустойчивое (volatile ) устройство памяти. Ее содержимое теряется при сбое системы или при выключении питания. Для организации устойчивой памяти используются другие, более медленные технологии.

ОС отвечает за следующие действия, связанные с управлением памятью:

  • Отслеживание того, какие части памяти в данный момент используются и какими процессами . Как правило, ОС организует для каждого процесса свою виртуальную память – расширение основной памяти путем хранения ее образа на диске и организации подкачки в основную память фрагментов (страниц или сегментов) виртуальной памяти процесса и ее откачки по мере необходимости.
  • Стратегия загрузки процессов в основную память, по мере ее освобождения . При активизации процесса и его запуске или продолжении его выполнения процесс должен быть загружен в основную память, что и осуществляется операционной системой. При этом, возможно, какие-либо не активные в данный момент процессы приходится откачивать на диск.
  • Выделение и освобождение памяти по мере необходимости . ОС обслуживает запросы вида "выделить область основной памяти длиной n байтов" и "освободить область памяти, начинающуюся с заданного адреса, длиной m байтов". Длина участков выделяемой и освобождаемой памяти может быть различной. ОС хранит список занятой и свободной памяти. При интенсивном использовании памяти может возникнуть ее фрагментация – дробление на мелкие свободные части, вследствие того, что при запросах на выделение памяти длина найденного сегмента оказывается немного больше, чем требуется, и остаток сохраняется в списке свободной памяти как область небольшого размера (подчас всего 1 – 2 слова). В курсе рассмотрены различные стратегии управления памятью и борьбы с фрагментацией. При исчерпании основной памяти ОС выполняет сборку мусора – поиск не используемых фрагментов, на которые потеряны ссылки, и уплотнение (компактировку) памяти – сдвиг всех используемых фрагментов по меньшим адресам, с корректировкой всех адресов.

Типы адресов

Для идентификации переменных и команд используются символьные имена (метки), виртуальные адреса и физические адреса (рисунок 2.7).
Символьные имена присваивает пользователь при написании программы на алгоритмическом языке или ассемблере.
Виртуальные адреса вырабатывает транслятор, переводящий программу на машинный язык. Так как во время трансляции в общем случае не известно, в какое место оперативной памяти будет загружена программа, то транслятор присваивает переменным и командам виртуальные (условные) адреса, обычно считая по умолчанию, что программа будет размещена, начиная с нулевого адреса. Совокупность виртуальных адресов процесса называется виртуальным адресным пространством. Каждый процесс имеет собственное виртуальное адресное пространство. Максимальный размер виртуального адресного пространства ограничивается разрядностью адреса, присущей данной архитектуре компьютера, и, как правило, не совпадает с объемом физической памяти, имеющимся в компьютере.

Рис. 2.7. Типы адресов

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

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

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

44. Методы распределения памяти без использования дискового пространства.

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

Рис. 2.8. Классификация методов распределения памяти