Статьи по меткам ‘xsystem’

Развитие XSystem

Август 27th, 2009

Как-никак, а развитие ядра потихоньку идёт.
В последнее время мною был реализован загрузчик PE-файлов в память с последующим запуском в user level. Реализация загрузчика PE немножко замедлила реализацию загрузчика файлов формата ELF, так как я обнаружил серьёзные изъяны в функциях, работающих с файлами. Нужно будет переписывать их реализацию. А так, надеюсь, к сентябрю успею выпустить новый релиз.

Менеджер виртуальной памяти

Июнь 26th, 2009

Всё-таки нашёл в себе силы реализовать менеджер виртуальной памяти в XSystem. Конечно, готов он не на все 100%, но бОльшая часть уже действительно оттестирована и работает. Как подтверждение этого ядро было переведено на новый менеджер, а старый был выкинут из дерева проекта.
Теперь ядро умеет одинаково хорошо обращаться с обычной страничной адресацией и PAE (Page-Address Extension). Для этого достаточно перекомпилировать ядро с соответствующими параметрами.
В ближайшее время на wiki постараюсь разместить документацию по сделанному менеджеру. Зато сейчас как гора с плеч: пришлось очень долго и очень много думать, как правильнее реализовать менеджер. Теперь же можно потихоньку начинать разделять user-space и kernel-space для процессов.
Механизм подкачки пока не реализован, но это уже — отдельный разговор.

Inline assembly: GCC + Watcom.

Апрель 8th, 2009

Задумался о кросс-компиляции моего ядрышка GCC (сейчас пока компилируется только Watcom’ом).

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

Хитрый код…

Hand-made синхронизация репозиториев Subversion

Март 29th, 2009

Несмотря на то, что репозиторий ОС XSystem мигрировал ко мне на домашний сервер, всё же хорошо было бы хранить бэкапы на каком-нибудь удалённом сервере.
Для этого я решил воспользоваться уже имеющимся репозиторием subversion на http://sourceforge.net/.

Идея работы такая: раз в сутки мой репозиторий должен синхронизироваться с удалённым репозиторием. При этом, все изменения в одном репозитории должны однозначно отражаться на другом. С версии subversion 1.4 появилась такая тулза, как svnsync, но она для моего случая не подходит: оба репозитория не предоставляют прямого доступа к svnroot.

Поэтому, немного порывшись в гугле, решил прибегнуть к собственному механизму синхронизации. Идея простая: раз в сутки сливается содержимое первого и второго (будем называть source и destination) репозитория. После этого сверяем содержимое source-репозитория с содержимым destination-репозитория: создаём несуществующие каталоги и копируем несуществующие файлы. Файлы, имеющие различные контрольные суммы md5, также перезаписываем. Но это не всё. После того, как мы влили новое файло в локальное дерево destination-репозитория, мы должны удалить из него те файлы, которых уже нет в source-репозитории. Для этого осуществляем обратную сверку снимка destination-репозитория с source-репозиторием и удаляем из него лишние файлы.

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

#!/usr/bin/perl

use strict;

my @blacklist   =
(
    qr(^\.svn|\/\.svn$),
    qr(^\.{1,2}$|\/\.{1,2}$)
);


my $src_path  = 'xsystem';
my $dst_path  = 'xskernel-sync';
my $svn_user  = '';
my $svn_pass  = '';

# Update repositories
`svn update $src_path`;
`svn update $dst_path`;

# now search files in src_path and compare to dst_path

add_files();
remove_files();

`svn commit $dst_path -m "Synchronization commit" --username $svn_user --password $svn_pass`;

Как видно, работа скрипта достаточно примитивна. Для его работы нужно иметь два рабочих снимка репозитория: source и destination. У меня source-репозиторий находится в каталоге xsystem, а destination — в каталоге dst_path.
Скрипт сначала обновляет снимки репозиториев, затем осуществляет вливание новых файлов в destination-репозиторий при помощи функции add_files(). После этого удаляются устаревшие файлы и каталоги из destination-репозитория функцией remove_files() и производится коммит изменений в destination-репозиторий.

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

sub md5sum
{
    my $fname = shift;
    if (open PIPE, "md5sum $fname |")
    {
        my $line = ;
        close PIPE;
        my ($sum) = ($line =~ /^(\w+)\s+/o);
        return $sum;
    }
    return undef;
}

В принципе, ничего нового. Вызывается утилита md5sum и анализируется её вывод.

Также необходимо игнорировать каталоги ".svn", "." и "..", для чего вводится массив @blacklist и пишется функция банинга файлов:

sub ban_file
{
    my $src_file = shift;
    foreach (@blacklist)
    {
        ($src_file =~ $_) and
            return 1;
    }
    return undef;
}

После этого можно спокойно разобрать функцию add_files():


sub add_files
{
    my @directories = ();
    my $curr_dir = '';

    do
    {
        # Открываем каталог
        if (opendir DIRHDL, "$src_path$curr_dir")
        {
            CYCLE: # Читаем содержимое каталога
            while (my $fname = readdir DIRHDL)
            {
                # Баним ненужные файлы
                my $src_file = "$src_path$curr_dir/$fname";
                (ban_file($src_file)) and
                    next CYCLE;

                my $dst_short = "$curr_dir/$fname";
                my $dst_file  = "$dst_path$dst_short";

                # Файл является каталогом?
                if (-d $src_file)
                {
                    # необходимо проверить, что он есть в destination-репозитории
                    unless (-d $dst_file)
                    {
                        # если каталога нет - его нужно создать
                        print "mkdir   $dst_short\n";
                        `mkdir -p $dst_file`;
                        `svn add $dst_file`;
                    }

                    # Запомним каталог для того, чтобы в будущем его просмотреть
                    push @directories, $dst_short;
                }
                else
                {
                    # проверяем, существует ли файл в destination-репозитории
                    unless (-e $dst_file)
                    {
                        # файл не существует, его нужно скопировать и добавить
                        print "add     $dst_short\n";
                        `cp -f $src_file $dst_file`;
                        `svn add $dst_file`;
                    }
                    else
                    {
                        # файл существует, вычисляем md5sum обоих файлов
                        my $sum1 = md5sum($src_file);
                        my $sum2 = md5sum($dst_file);

                        # если суммы не совпадают - заменяем файл новым
                        if ($sum1 ne $sum2)
                        {
                            print "replace $dst_short\n";
                            `cp -f $src_file $dst_file`;
                        }
                    }
                }
            }
        }
        else
        {
            print "Can't open dir $src_path$curr_dir\n";
        }

        # закрываем каталог и получаем следующий каталог, который следует обработать
        closedir DIRHDL;
        $curr_dir = shift @directories;
    }
    while (defined $curr_dir); # крутимся, пока в списке присутствуют обрабатываемые каталоги.
}

При удалении функция будет очень похожа, только теперь надо осуществлять поиск файлов в destination-репозитории и смотреть, есть ли они в source-репозитории:

sub remove_files
{
    my @directories = ();
    my $curr_dir = '';

    do
    {
        # опять же, открываем каталог destination-репозитория
        if (opendir DIRHDL, "$dst_path$curr_dir")
        {
            CYCLE: # читаем файлы
            while (my $fname = readdir DIRHDL)
            {
                # баним недопустимые diren'ы
                my $src_file = "$dst_path$curr_dir/$fname";
                (ban_file($src_file))
                    and next CYCLE;

                my $src_short = "$curr_dir/$fname";
                my $dst_file  = "$src_path$src_short";

                # проверяем, является ли это каталогом
                if (-d $src_file)
                {
                    # проверяем, существует ли этот каталог в source-репозитории
                    unless (-d $dst_file)
                    {
                        # каталога нет - удаляем его из destination-репозитория
                        print "rmdir   $src_short\n";
                        `svn delete $src_file`;
                    }
                    else
                    {
                        # каталог существует, запоминаем его для дальнейшей обработки
                        push @directories, $src_short;
                    }
                }
                else
                {
                    # Это обычный файл, проверяем, есть ли он в source-репозитории
                    unless (-e $dst_file)
                    {
                        # Файла нет, удаляем его из destination-репозитория
                        print "unlink  $src_short\n";
                        `svn delete $src_file`;
                    }
                }
            }
        }
        else
        {
            print "Can't open dir $dst_path$curr_dir\n";
        }

        # Закрываем каталог, получаем следующий
        closedir DIRHDL;
        $curr_dir = shift @directories;
    }
    while (defined $curr_dir);
}

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

Как я поднимал SVN

Март 29th, 2009

Собственно, данный пост я решил написать после ночных бдений с SVN. Да, у меня были проблемы, которые пришлось решить, возможно, нестандартными методами, но зато теперь всё работает так, как я хотел.

Управление репозиторием

Итак, для всего этого нам нужнен сам Apache (я использовал Apache 2) и дополнительные модули: dav и dav_svn.

Помимо этого, я ещё поставил просматривалку репозитория ViewVC, с которой потом долго и провозился.

Для того, чтобы заставить работать subversion через http, достаточно сделать следующее (делал в OpenSUSE 10.3):
Сначала включаем модули при помощи a2enmod:


a2enmod dav
a2enmod dav_svn

Теперь можно перезагрузить конфигу апача (либо через restart, либо через reload):


/etc/init.d/apache2 restart

или


/etc/init.d/apache2 reload

После этого необходимо сконфигурировать виртуальный хост. Лично я хотел, чтобы у меня SVN-репозиторий был как отдельный поддомен в домене xskernel.org — то есть, svn.xskernel.org.

Для этого заводим отдельный виртуальный хост в апаче:


<VirtualHost *:80>
    ServerName svn.xskernel.org
    ErrorLog    /var/log/apache2/svn-error.log
    TransferLog /var/log/apache2/svn-access.log

    <Location /svn >
      DAV svn
      SVNPath /home/svn/repositories/svn.xskernel.org
      SVNListParentPath on
      AuthType Basic
      AuthName "XSystem Kernel Team repository"
      AuthBasicProvider file
      AuthUserFile /home/svn/auth/svn.xskernel.org.htpasswd
      SetOutputFilter DEFLATE

      <LimitExcept GET PROPFIND OPTIONS REPORT>
        Require valid-user
      </LimitExcept>
    </Location>

</VirtualHost>

Как видно, здесь в конфиге заводится локейшн /svn, который используется для работы DAV. Именно DAV позволяет полноценно работать с репозиторием через http.

Рассмотрим некоторые параметры:
SVNPath задаёт каталог, в котором располагается репозиторий, который будет ассоциирован с данным виртуальным хостом. Естественно, сам SVNRoot я спрятал (не стал использовать SVNRootPath).
AuthUserFile — файл, в котором будут в дальнейшем храниться пользователи и хэши их паролей, которым будет разрешён доступ в SVN.
LimitExcept накладывает ограничения на все команды кроме GET, PROPFIND, OPTIONS и REPORT, требуя авторизации (Require valid-user).

Отлично, теперь нужно завести соответствующий репозиторий. Я решил хранить все репозитории в отдельном каталоге /home/svn/repositories, поэтому создал репозиторий таким образом:


mkdir -p /home/svn/repositories
svnadmin create /home/svn/repositories/svn.xskernel.org

Отлично, теперь репозиторий есть, надо сделать авторизацию. Для этого создаю файл паролей и завожу в нём пользователя:


mkdir -p /home/svn/auth
touch /home/svn/auth/svn.xskernel.org.htpasswd
htpasswd2 /home/svn/auth/svn.xskernel.org.htpasswd username

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


chown -Rv webserver:web /home/svn

Сохраняем конфигурационный файл виртуальных хостов апача, перезагружаем конфигурацию по reload, и пробуем зайти по адресу http://svn.xskernel.org/svn/. WebDAV работает!

Просматривание репозитория

Вот с просматривалкой у меня и возникло много проблем. Хотелось, чтобы при заходе на http://svn.xskernel.org/ автоматически запускалась просматривалка, при этом она отображала бы только тот репозиторий, который ассоциирован с данным виртуальным хостом. Я перепробовал много различных вариантов и, в конце-концов, остановился на том, что изложу ниже.

WebDAV я поставил штатными средствами OpenSUSE — из репозитория, после чего забрал его из /srv/www и переместил в каталог /home/svn.
Для своего виртуального хоста завёл отдельную конфигу /home/svn/viewvc-svn.xskernel.org.conf, в которой прописал следующие параметры:


# Доступные репозитории для просмотра
svn_roots:
        svn.xskernel.org : /home/svn/repositories/svn.xskernel.org
# Репозиторий, который следует просматривать по умолчанию
default_root = svn.xskernel.org
# Адрес обратной связи
address = team@xskernel.org
# Не использовать корень как компонент URL (то есть, не отображаются остальные репозитории в корне)
root_as_url_component = 0
# Путь к файлам с шаблонами отображения веб-страницы
template_dir = /home/svn/viewvc/svn.xskernel.org/templates
# компонент URL, по которому будут располагаться ресурсы для просматривалки (картинки и пр.)
docroot = /viewvc-docroot

Теперь заводим скрипт, который цепляет эту конфигу, копируя стандартный:


cp /home/svn/bin/cgi/viewvc.cgi /home/svn/bin/cgi/viewvc-svn.xskernel.org.cgi

И редактируем строки, прописывая:


LIBRARY_DIR = r"/home/svn/lib"
CONF_PATHNAME = r"/home/svn/viewvc-svn.xskernel.org.conf"

Теперь скрипт /home/svn/bin/cgi/viewvc-svn.xskernel.org.cgi хватает конфигу /home/svn/viewvc-svn.xskernel.org.conf.
После всего этого заводим свои темплейты для ViewVC:


mkdir -p /home/svn/viewvc/svn.xskernel.org
cp -R /home/svn/templates /home/svn/viewvc/svn.xskernel.org
cp -R /home/svn/templates/docroot /home/svn/viewvc/svn.xskernel.org/viewvc-docroot

Прикручивание ViewVC к апачу

Теперь надо в каталоге /home/svn/viewvc/svn.xskernel.org завести файл index.html, который редиректит на подкаталог "/viewvc":



<pre>
<html><head><META HTTP-EQUIV="Refresh" CONTENT="0; URL=/viewvc"><head>
<body></body>
</html>
</pre>

Сделано это так потому, что если сам Апач осуществит редирект, SVN-клиент начнёт ругаться, что не может выполнить PROPFIND при импорте репозитория (проверено уже часовыми бдениями над mod_rewrie).

Прописываем ViewVC в конфиге виртуального хоста:


<VirtualHost *:80>
    #...
    ScriptAlias /viewvc "/home/svn/bin/cgi/viewvc-svn.xskernel.org.cgi"
    Alias / /home/svn/viewvc/svn.xskernel.org/

    <Directory /home/svn/viewvc/svn.xskernel.org/ >
        Order allow,deny
        Allow from all
        DirectoryIndex index.html
    </Directory>
</VirtualHost>

Параметр ScriptAlias указывает, какой скрипт следует запускать, когда URL содержит "/viewvc".

Перезагружаем конфигу апача, пробуем: http://svn.xskernel.org/.
Грузится страничка index.html, которая автоматом нас редиректит на http://svn.xskernel.org/viewvc/ и запускается скрипт /home/svn/bin/cgi/viewvc-svn.xskernel.org.cgi .

Заключение

Как видно, не всё так красиво в моей настройке, как хотелось бы. Если есть соображения/советы, как сделать лучше, то я их внимательно выслушаю.

Тем не менее, репозиторий ОС XSystem переехал с SourceForge.net ко мне на домашний сервер. Работает на порядок быстрее, чем тормозной сервис от SourceForge.net. Однако, от SF.net я не стал отказываться, а сделал его зеркалом моего репозитория. Как — в следующем посте.

Не все виртуалки превосходны.

Ноябрь 6th, 2008

В связи с тем, что на форуме появился очень интересный баг:

http://forum.xskernel.org/viewtopic.php?f=10&t=18

Решил поиграться с виртуальными машинами, а именно проверить, как на них запускается XSystem.

Вот что из этого получилось:

Переснял в увеличенном масштабе…

А развитие идёт дальше…

Ноябрь 3rd, 2008

Выпущен новый релиз ОС XSystem — October 2008 Fishes: Carp.
Основные нововведения:
- Из дерева проекта удалены утилиты ‘xarch’ и ‘fontcut’.
- Полностью переписан планировщик (теперь более быстрый и надёжный).
- Блочный распределитель памяти теперь выделяет блоки с адресом, кратным 8 байтам.
- Исправлены ошибки в контроллере клавиатуры (теперь работает в Bochs).
- Оптимизации реализации библиотеки <string.h>.
- Частично перенесён код Watcom C++ Runtime Library, необходимый для использования C++ — конструкций.
- Изменены сборочные скрипты.
- Кодовые страницы перемещены в ‘media/share/codepages’.
- Изменён метод ‘for_file’ в утилите ‘xsmake’.
- Большинство архитектурно-зависимого кода вынесено в ветку ‘include/arch’ ядра.
- Написан прототип будущего механизма подкачки виртуальной памяти.
- Добавлена поддержка записи конфигурационного пространства шины PCI (экспериментальное).
- Реализована поддержка загрузки/сохранения контекстов FPU/MMX/SSE при переключении задач.
- Добавлена защита от ошибочного прерывания со стороны PIC.
- Доступна загрузка с USB Flash Drive.
- Первичный загрузчик (‘bootload’) полностью переписан для поддержки файловых систем FAT12 и FAT16.
- Вторичный загрузчик ‘xload’ переписан на C++.
- Добавлены функции ‘unlink’, ‘cp’ в утилите ‘xsmake’.
- Добавлена условная конструкция ‘if-else’ в утилиту ‘xsmake’.
- Добавлена проверка зависимостей в OMF-файлах утилитой ‘xsmake’.
- Переписана утилита ‘rawmake’ (поддержка создания образов FAT12 и FAT16-дисков).
- Утилиты ‘xsmake’, ‘exe2bin’ и ‘rawmake’ теперь также можно собрать с помощью GNU GCC под Linux.

Форум

Октябрь 15th, 2008

Вот и дожили до того, что открыл форум своего проекта.
Расположен он здесь: http://forum.xskernel.org/
Если есть желание реально поучаствовать в проекте и/или обсудить его — приветствую гостей.
Основной сайт тут: http://xskernel.org/ .
А здесь можно найти кое-какую полезную документацию: http://wiki.xskernel.org/ .

Странно…

Октябрь 5th, 2008

Уже где-то вторую или третью неделю непроизвольно соблюдаю правило «ни дня без коммита».

Хм… К чему бы это? Наверное, к новому релизу…

Написал статейку на WIKI про планировщик потоков:

http://wiki.xskernel.org/doku.php/xskernel/ipc/scheduler

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

xskernel.org жив!

Август 30th, 2008

Домен xskernel.org после долгого пребывания в небытии снова вернулся ко мне!
Ура ура ура!