IBM®
Перейти к тексту
    в России и странах СНГ [изменить]    Условия использования
 
 
   
    Главная страница    Продукты    Услуги и решения    Поддержка и загрузка    Мой профиль    
Перейти к тексту

developerWorks Россия  >  Linux | Open source  >

Контейнерная виртуализация Cell/B.E. : Часть 2. Вопросы реализации

Представляем принципы программной контейнерной виртуализации на платформе Cell/B.E. с использованием проекта с открытым исходным кодом OpenVZ

developerWorks
Опции документа

Опции документа, требующие включения JavaScript, не отображаются

Обсудить


Выскажите мнение об этой странице

Помогите нам улучшить содержание


Уровень сложности: средний

Кристиан Кайзер, Стажёр, IBM
Кристиан Рунд, исследователь-разработчик, IBM

12.02.2008

В этой серии из трёх частей представлена форма программной виртуализации, ориентированная на аппаратные ресурсы, известная как контейнерная виртуализация (или виртуализация операционной системы), для демонстрации которой используется проект с открытым исходным кодом OpenVZ. В серии представлен исчерпывающий обзор всех компонентов и методик, необходимых для виртуализации процессора Cell/B.E. программными методами. Эта статья, вторая в серии, подробно описывает реализацию выделенной виртуализации и разбиения на разделы, описанных в первой части серии..

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

Чтобы продемонстрировать реализацию системы, в этой статье будут освещены следующие вопросы:

  • Виртуализация spufs: предотвращение использования одного root-inode для всех точек монтирования
  • Корректировки sysfs: записи необходимо корректировать в реальном времени
  • Модификация планировщика SPU: добавление шага реализации виртуализации
  • Модификация инструментов OpenVZ: использование новых функций

Виртуализация spufs

По умолчанию spufs использует один и тот же root-inode при каждом монтировании. Например, у вас может быть две среды chroot (A и B), и spufs обоих будет смонтирована по пути /spu. Если вы создадите потоки SPE в среде A, после чего выведете содержимое /spu, вы увидите только что созданные потоки SPE. Однако в среде B вы увидите тот же листинг /spu, поскольку вы обращаетесь к тому же root-inode, что и в среде A.

Чтобы изменить такое поведение, т.е. чтобы в обеих средах можно было увидеть только созданные в них потоки SPE, необходимо изменить тот факт, что spufs всегда использует один и тот же root-inode для всех точек монтирования. При монтировании spufs она вызывает функцию ядра, которая возвращает системный блок. Обычно используется функция get_sb_single(), которая всегда возвращает один и тот же системный блок. Функция get_sb_nodev() всегда возвращает различные системные блоки, что приводит к нужному нам результату. (На рисунке 1 показана spufs до и после выполнения виртуализации.)


Рисунок 1. Spufs до и после выполнения виртуализации
Spufs до и после выполнения виртуализации

OpenVZ позволяет смонтировать внутри контейнера только несколько файловых систем. Каждая система реализует экземпляр struct file_system_type , который определяет аспекты, связанные с файлами. OpenVZ расширяет эту структуру (наряду с другими), дополняя ее компонентом, определяющим, может ли быть смонтирована файловая система. Таким образом, компоненту .fs_flags должно быть установлено значение FS_VIRTUALIZED.

У процесса, созданного внутри контейнера, есть два PID. (Вспомните часть 1 , в которой говорилось, что у каждого контейнера есть собственное множество ресурсов, предоставляемых ядром. У дерева процессов было одно множество ресурсов, а контейнер мог видеть только собственное множество процессов с виртуализованными PID.) Внутри контейнера есть виртуализованный PID, а в базовой системе тот же процесс идентифицируется другим PID, который называется глобальным PID. Как уже упоминалось, название директорий spufs задаётся в виде spethread-<PID>-<thread-ID>, где <PID> - идентификатор процесса потока SPE, а <thread-ID>> соответствующий идентификатор потока. Поскольку в среде контейнера используются виртуализованные PID, листинг spufs внутри контейнера должен показывать виртуализованные, а не глобальные PID. К счастью, такой алгоритм уже реализован в OpenVZ.

Измените файл arch/powerpc/platforms/cell/spufs/inode.c в ядре Linux®.



В начало


Корректировка sysfs

sysfs уже виртуализована, поэтому ее можно использовать внутри контейнеров. Она является не копией sysfs, видимой в базовой системе, а её частью. Цель состоит в том, чтобы выделять SPU контейнерам и освобождать их в реальном времени. Это означает, что записи sysfs также необходимо адаптировать в реальном времени. Перед этим создайте директорию, в которой перечислены SPU.

Это директория /sys/devices/system/spu. По умолчанию в sysfs в среде контейнера нет директорий /sys/devices/system/spu, /sys/devices/system и /sys/devices. Эти три записи необходимо создать во время инициализации (запуска) контейнера. Поддиректории /sys/devices/system/spu могут иметь вид от spu0 до spu<N>, где <N> - количество доступных SPU в системе минус 1. Директории необходимо создавать, когда SPU назначается контейнеру, и удалять, когда они открепляются от контейнера.

Каждой директории в листинге sysfs должен соответствовать экземпляр kobject в пространстве ядра. kobject - это структура, которая определяет название директории и её родительский kobject (другими словами, соответствующую родительскую директорию). Например, у kobject, который отображается как директория /sys/devices/system/spu/spu3, есть два параметра, которые нужно изменить:

  • Название spu3.
  • Родитель (указатель на kobject, представляющий /sys/devices/system/spu).

После регистрации kobject в sysfs посредством вызова subsystem_register(), он становится видимым из пространства пользователя. Обратное действие состоит в удалении директории из sysfs. Для этого можно вызвать функцию subsystem_unregister(), указав kobject, который необходимо удалить. На рисунке 2 показан пример.


Рисунок 2. Sysfs и kobjects
Sysfs и kobjects

У kobject с названием spu3 есть указатель на родительский kobject с названием spu.

Основные изменения необходимо сделать в файле ядра kernel/ve/vecalls.c. Это файл OpenVZ, в котором реализовано большинство функций, которые вызываются во время инициализации и настройки параметров контейнеров.



В начало


Модификация планировщика SPU

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

  • Идентификатор (номер) SPU
  • К какому узлу Cell/B.E. он принадлежит
  • Указатель на LS SPU

Новая переменная хранит владельца SPU в виде идентификатора контейнера. Планировщик SPU реализует функцию spu_alloc(), которая ищет свободный SPU, на котором будет выполняться поток SPE. Таким образом, он ищет список доступных в системе SPU (на которых в данный момент не выполняется потоков SPE).

Обычно берется первый SPU в списке и на нём запускается поток SPE. Чтобы реализовать виртуализацию, функция должна проверить, совпадает ли идентификатор контейнера свободного SPU с идентификатором контейнера потока SPE, который предполагается на нем выполнить. На рисунке 3 показано, как работает spu_alloc() до и после модификации.


Рисунок 3. Spu_alloc() до и после модификации
Spu_alloc() до и после модификации

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

Функция spu_alloc() реализована в исходном файле ядра Linux arch/powerpc/platforms/cell/spu_base.c.



В начало


Модификация инструментов OpenVZ

Большая часть нужной функциональности уже реализована, но для того, чтобы использовать новые функции, необходимо модифицировать инструменты OpenVZ. Инструмент vzctl управляет выделением SPU в реальном времени. Это основной инструмент для настройки параметров в OpenVZ. Новый параметр для установки количества SPU, выделенных контейнеру, - --spus <nr_spus>.

Значение <nr_spus> представляет количество SPU, выделенных контейнеру. Это абсолютное значение, поэтому если контейнеру с восемью SPU присваивается значение 6, то от процессора открепляются 2 SPU, а не добавляются 6 SPU (8 - 6 = 2).

Например, вот результат работы команды, когда контейнер с ID, равным 101, получает восемь SPU:

[root@c02b12-0 ~]# vzctl set 101 --spus 8
Setting SPUs: 8
Configure meminfo: 1024000
WARNING: Settings were not saved and will be reset to original
 values on next start (use --save flag)
[root@c02b12-0 ~]#

Для реализации такого алгоритма инструмент vzctl должен перейти барьер пространства пользователя и выполнить ряд операций управления в пространстве ядра. Инструмент должен найти SPU, которые не используются другими контейнерами. Инструмент vzctl выполняет поиск по списку доступных SPU и проверяет идентификатор контейнера в структуре нового spu (описана в разделе модификации планировщика SPU). Если это значение равно 0, SPU может быть назначен рассматриваемому контейнеру. Значение 0 используется потому, что значение идентификатора контейнера должно быть больше 0, т.е. значение 0 указывает на то, что SPU не назначен ни одному из контейнеров. Если функция не может найти нужного для выполнения запроса количества свободных SPU, процедура завершается и не назначает контейнеру ни одного SPU. Если количество SPU, уже назначенных контейнеру, больше запрошенного количества SPU, разница открепляется.

Чтобы преодолеть барьер между пространством пользователя и пространством ядра, можно использовать различные модели реализации. (Дополнительную информацию о моделях реализации можно найти в статье Арнда Бергмана "Как не изобрести интерфейсы ядра", ссылка на которую приведена в разделе Ресурсы.) Наиболее простой способ состоит в реализации нового системного вызова, который накладывает параметры <containerID> и <nr_spus> на параметры системного вызова.

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

Модуль не является частью этой статической функции, и поэтому статическая встроенная функция обработки системного вызова не может вызвать функцию, являющуюся частью модуля. Решение состоит в реализации оболочки функции, которая копирует указатель на функции модуля в переменную встроенной статической функции обработки системного вызова таким образом, чтобы встроенный статический обработчик системного вызова мог вызвать функцию модуля. Эта оболочка функции вызывается во время инициализации и очистки модуля. Чёрная стрелка на рисунке 4 показывает наш метод оболочки функции.


Рисунок 4. Функции модуля и системный вызов
Функции модуля и системный вызов

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

Необходимо изменить исходный код ядра в следующих файлах:

  • include/asm-powerpc/systbl.h
  • include/asm-powerpc/unistd.h
  • include/linux/syscalls.h
  • kernel/sys.c
  • kernel/sys_ni.c
  • kernel/ve/vecalls.c

Кроме того, обновляются файлы исходного кода vzctl OpenVZ:

  • include/res.h
  • include/vzctl_param.h
  • include/vzsyscalls.h
  • src/lib/config.c
  • src/lib/res.c
  • src/vzctl.c

В систему сборки OpenVZ добавляется два новых файла:

  • include/spu.h
  • src/lib/spu.c


В начало


Подготовка к третьей части

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

Поделиться этой статьей

digg digg.com
del.icio.us del.icio.us
Slashdot slashdot.org



Ресурсы

Научиться

Получить продукты и технологии

Обсудить


Об авторах

Кристиан Кайзер (Christian Kaiser) изучает вычислительную технику в университете RWTH в Ахене в Германии. В 2007 году он проходил стажировку в исследовательской лаборатории IBM в Германии, в городе Бёблинген. Во время стажировки в IBM он исследовал методы виртуализации для процессора Cell Broadband Engine. После завершения стажировки Кристиан Кайзер начал работу над диссертацией на кафедре операционных систем в университете RWTH в Ахене. Тема его диссертации - "Анализ коллективной асинхронной связи в высокоскоростных сетях, организованных в памяти"


Кристиан Рунд (Christian Rund) - сотрудник исследовательской лаборатории IBM в Бёблингене, в Германии. Он изучал теорию вычислительных систем в университете Штутгарта и в Упсальском университете в Швеции, закончив обучение в 1997 году. Во время учебы он проходил стажировку в IBM в Херренберге и Штутгарте в Германии. В 1998 году он поступил на работу в департамент разработки систем банка Landeszentralbank в Штутгарте (Deutsche Bundesbank). В 2001 году Кристиан перешел в команду разработчиков канала FCP zSeries корпорации IBM в качестве исследователя-разработчика. С середины 2006 года он занимается исследованием и разработкой микропрограммного обеспечения хост-контроллера Cell/B.E.




Выскажите мнение об этой странице


Пожалуйста, найдите минутку и заполните форму, чтобы повысить уровень сервиса.



ДаНетНе знаю
 


 


12345
 


В начало


IBM является товарным знаком IBM Corporation в США и (или) других странах. UNIX является зарегистрированным товарным знаком The Open Group в США и других странах. Linux является зарегистрированным товарным знаком, принадлежащим Линусу Торвальдсу в США и (или) других странах. Другие названия компаний, продукции и услуг могут являться товарными знаками или знаками обслуживания соответствующих компаний. Другая компания, продукт или название услуги могут быть торговыми марками или знаками обслуживания, принадлежащими иным физическим или юридическим лицам.

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

    IBM в России Конфиденциальность Контакты