Author Archives: Сергей Царь

BrainGames retro-игры под Linux

Здравствуйте.

Задача: взять все доступные игры на http://www.braingames.getput.com/
и собрать их под современный Линукс (modern Linux).

Задача решена успешно, игры классные, живые скриншоты всех игр я представлю!
Результаты моей работы – переделанные готовые для сборки сорцы, без объектных файлов,
можно скачать здесь: http://beotiger.com/download/braingames
Архивчик весит окло 80 Мегабайт, для некоторых игр включены их Windows-версии со всеми нужными библиотеками. Все Windows-версии игр Вы можете скачать с сайта BrainGames, адрес вверху. Я оставил Windows версии для сравнения.

Ниже русский текст перемежается с английским, сам не знаю почему.
Я – двуязычен, bilingual, хорошо, что не двуличен, хотя кто его знает! 🙂

Для сборки игр надо поставить в систему SDL: Simple DirectMedia Layer
(старый SDL, 1.2), а также некоторые сопутствующие ему либы, как то:
SDL_image SDL_mixer SDL_sound SGE etc.
причем их девелоперские версии (обычно оканчивающиеся на -dev или -devel)

В системах на основе APT'а (Debian/Ubuntu/Mint и другие), это делается так:
$ apt install build-essential libsdl-dev libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-sound1.2-dev libsdl-ttf2.0-dev libsdl-sge-dev

Начал я тогда с месяц, а то и более, назад:

Date: 7-14 May 2015 AD
System: Linux justy 3.13.0-37-generic #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

justy@justy ~/src/braingames $ c++ –version
c++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ОК, у нас современный Линукс Минт (Linux Mint), который идентифицируется как Ubuntu, ну и хорошо,
и современный компилятор c++ 4.8 (это g++).

Да, в играх BrainGames Alt+Enter переключает полный экран/окно, F12 – быстрый выход из игры.

Поехали игры:
0. TransballGL – only demo for Windows? But in archive there is src directorty, that should be compiled later!?
OK, Makefile created, SDL_rotozoom.h not found, it the part of SDL_gfx?
Install libSDL-gfx1.2-4 ?

collision.cpp:28:20: fatal error: GLtile.h: No such file or directory
#include "GLtile.h"

OK, Makefile needed to be changed!

Смысл такой, что TransballGL – крутая штука, и надо собрать её под нашу систему,
но пока не знаем как. Что-то много всего отсуствует.
Но в итоге мне удалось его собрать, он идёт ближе к кноцу. Оно стоит того!

1. supertransball2: compiled without problems from SuperTransball/stransball2-v15-windows/stransball2sources/.
Эта игра – предшественник TransballGL, только графика попроще, и уровней поменьше.
Стоит того, чтобы поиграть пару-тройку уровней.

Как собирается:
$ cd braingames/SuperTransball/src
$ make
После этого исполняемый файл stransball2 будет перемещен в папку вверх.

чтобы поиграть, делаем
$ cd ..
$ ./stransball2
 

strb1.jpg

strb2.jpg

2. RoadFighter

Linking errors.
Need to change string in Makefile:
$(CC) $(LDFLAGS) $^ -o $@ to $(CC) $^ -o $@ $(LDFLAGS)
e.g. LDFLAGS should go last.

Then all's OK!

Да, в RoadFighter'е ошибки линкощика обнаружились,
новый GCC использует другой порядок линка? Не знаю точно.

Новый Makefile должен работать без проблем:
$ cd braingames/roadfighter
$ make
$ ./roadfighter

В директорию src заходить не нужно, Makefile расположен здесь, он сам распознает нужную папку.
Игра играет!

 

rf1.jpg

rf2.jpg

rf3.jpg

rf4.jpg

3. F1 Spirit

Same LDFLAGS issue as in RoadFighter.
Also: delete curl/types.h line (it's obsolete long time ago).
To avoid linking against libm and others libc++ libraries we should change default compiler from gcc to g++.

Да, те же проблемы с линком, что и у RoadFighter. Плюс ещё пара нюансов вылезло (см. выше, на английском).

Итого: игрушка супер, RoadFighter * 100, свои уровни, реальные гонки. Но не проста в прохождении.
На сайте написано, что не доделана, но 3 трассы играются на ура!

Собираем:
$ cd braingames/F-1\ Spirit/
$ make
$ ./f1spirit

То есть в sources, как и в случае с roadFighter, заходить не надо, игра собирается и запускается с корня.
Наслаждаемся:
 

f1s1.jpg

f1s2.jpg

f1s3.jpg

f1s4.jpg

f1s5.jpg

f1s6.jpg

4. The Goonies

Same LDFLAGS issue as in RoadFighter.
Same needing g++ compiler instead of gcc.
Then make is OK!

ОК, собираем:

$ cd braingames/TheGoonies
$ make
$ ./goonies
 

goon1.jpg

goon2.jpg

goon3.jpg

goon4.jpg

goon5.jpg

5. NETHER EARTH

Как я сначала компилировал, и какие ошибки исправил (на английском, не обесудьте):
Ниже будет сборка готовой игры на русском.

$ cd NETHER EARTH/Nether Earth v0.52/src
$ make
g++ -c cmc.cpp -o cmc.o
cmc.cpp:11:21: fatal error: GL/glut.h: No such file or directory
#include "GL/glut.h"
^
compilation terminated.
make: *** [cmc.o] Error 1

No glut dev lib?
OK:
$ sudo apt-get install freeglut3-dev freeglut3

Yep, now it compiles!

Now, after runnig I got following error:
freeglut ERROR: Function <glutStrokeWidth> called without first calling 'glutInit'.

In main.cpp in main function I added line:
glutInit(& argc, argv);

and added:
#include "GL/gl.h"
#include "GL/glut.h"
at the head of it.

OK, rm *.o && make done it well!
Nether Earth works now!

Да, для NetherEarth – крутой 3D ретро-стратегии – надо доустановить GLUT:

$ apt install freeglut3-dev
$ cd braingames/NETHER\ EARTH/src
$ make
$ cd ..
$ ./nether_earth

Смысл игры похоже – захватить все ресурсы или уничтожить вражескую базу?
Мы управляем каким-то подом, можем строить роботов из различных компонентов,
потом отдавать им приказы – захватывать ресурсы/уничтожать вражеских роботов и т.п.
Или управлять ими с помощью своего пода. Круто!
 

ne1.jpg

ne2.jpg

ne3.jpg

ne4.jpg

6. The Maze of Galious

Same $(LDFLAGS) as in RoadFighter.
All is OK!

В этой игрушке есть фишка: нажатие клавиши F10 меняет скины игры,
превращая её то в версию для Dendy, то в версию для MSX, то в современную ретро-версию и т.п.
Я насчитал 6 шкурок.

Итак, сборка проста:

$ cd braingames/The\ Maze\ of\ Galious/
$ make
$ ./mog
 

tmg1.jpg

То же самое с другой шкуркой:
 

tmg2.jpg

tmg3.jpg

tmg4.jpg

tmg5.jpg

Другая шкурка:

tmg6.jpg

7. Transball GL

Вот и добрались до неё!

Этапы начальной сборки игры показаны ниже, уже на русском.
Потратил наверное около часа на всё это.
Сборка игры сейчас описана ниже, там же идут скриншоты.

justy@justy ~/src/braingames/TransballGL/TGL/src $ make
g++ -w -c state_playerprofile.cpp -o state_playerprofile.o `sdl-config –cflags`
state_playerprofile.cpp: In member function ‘int TGLapp::playerprofile_cycle(KEYBOARDSTATE*)’:
state_playerprofile.cpp:120:7: error: ‘m_profile_profiles_names’ was not declared in this scope
m_profile_profiles_names.Add(tmp);
^
make: *** [state_playerprofile.o] Error 1

> Тут опечатка: не m_profile_profiles_names, а m_profile_profile_names

g++ -w -c XMLparser.cpp -o XMLparser.o `sdl-config –cflags`
XMLparser.cpp:19:20: fatal error: symbol.h: No such file or directory
#include "symbol.h"
^
compilation terminated.
make: *** [XMLparser.o] Error 1

> И опять опечатка, не symbol.h а Symbol.h
> Тоже самое было с GLtile.h (вместо GLTile.h)
> Linux это не Windows, тут регистр в именах файлов имеет значение

> Пришлось тж. добавлять #else include <dirent.h> etc. вместе с #ifdef _WIN…
> И вместо _mkdir и т.п. использовать mkdir в условных выражениях
> В некоторых файлах… где ругался на DIR и dirent и прочее, надо было делать так:

#ifdef _WIN32
#include "windows.h"
#else
#include <unistd.h>
#include <stddef.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include "ctype.h"
#endif

То есть под #else я тут подразумеваю Linux. Попробовать бы собрать под MacOS X!?

Игра в итоге собралась успешно и играет как надо, так что всё жуе позади!
Итак, собираем сейчас:

$ cd braingames/TransballGL/src
$ make
$ cd ..
$ ./tgl

Цель игры – управляя мини-ракетой, захватить шарик, избегая любых препятствий и вытащить его на самый верх уровня.
Любое столкновение, кроме шарика, карается моментальной гибелью и переигрыванием всего уровня.

Кроме того, ещё расходуется горючее, за которым надо следить на некоторых уровнях.

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

Уровни есть те же, что и в SuperTransball2, а есть я так понял и новые, но до них я пока не дошёл.

 

trgl1.jpg

trgl2.jpg

trgl3.jpg

trgl4.jpg

И на закуску –

8. Magical Tree

Эта игра не доделана и вряд ли когда будет.
К сожалению, исходники не представлены, мне по крайней мере не удалось их найти.

Играется через WINE:

$ cd braingames/Magical\ Tree/
$ wine Demo.exe

Доходит до конца дерева, и всё, даже если все яблоки собрал.
 

mt1.jpg

mt2.jpg

mt3.jpg

Пока всё, от BrainGames ничего не слышно уже лет 6, с 2009 года. Жаль, классные римэйки делали!
И сорцы крутые!

Спасибо вам, господа из BrainGames за наше счастливое дество!

$ date
Пн. июня 8 22:31:04 MSK 2015

$ uname -a
Linux justy 3.13.0-51-generic-tuxonice #84~ppa1-Ubuntu SMP Wed Apr 29 19:39:16 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

$ g++ –version
g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ free -gho
total used free shared buffers cached
Память:7,8G 2,8G 5,0G 53M 49M 1,0G
Swap: 3,0G 0B 3,0G

~/src $ zip -r9 braingames.zip braingames/

$ du -sh *.zip
78M braingames.zip
34M retrospec.zip
 

PHP: HTML::render – грамотно рендерим свои странички

Здравствуйте.

Лет 5 назад мы работали над одним сайтом, и использовали какой-то open source framework, я уже не помню какой именно. Так вот, он мне нравился, хоть и был слегка замороченный, я в нём ковырялся, и наткнулся на функцию рендеринга конечной веб-страницы. Она мне показалась довольно милой, я её максимально сократил, оставив практически всю функциональность, и облёк в форму класса.

Это мощный рендерер занимает всего строчек 40, очень удобный и быстрый. Я им пользуюсь уже 5 лет и ни разу не пожалел об этом. Всегда используйте этот рендерер, даже в демо-проектах, нечего сваливать PHP-код и HTML-разметку в кучу.

HTML::render

Вот его полный код:

///////////////////////////////////////////////
//////////// PARSE HTML FUNCTIONS ////////////
/////////////////////////////////////////////
// use STATIC rendering - используем статический рендеринг
class HTML
{
        // deafult folder for html pages (templates)
	static private $folder = 'html';
	// change default folder for html templates
	static public function changeFolder($folder) {
		self::$folder = $folder;
	}
 
	static public function render($template, $data = array()) {
		$content = file_get_contents(self::$folder."/{$template}.html");
		$content = self::design_render_text($content, $data);
		return $content;
	}
 
	static private function design_render_text($content, $data = array()) {
		$content = self::design_parse_function($content, $data);
		$content = self::design_parse($content, $data);
		return $content;
	}
	static private function design_parse_function($content, $data = array()) {
		preg_match_all('/\<\<(.*?)\>\>/is', $content, $res);
		if (@$res[1])
			foreach ($res[1] as $el) {
				$middle = self::design_parse($el, $data);
				$middle = '$result = '.$middle.';';
				eval($middle);
 
				$content = str_ireplace('<<'.$el.'>>', $result, $content);
			}
		return $content;
	}
	static private function design_parse($content, $data) {
		preg_match_all('/\%\%(.*?)\%\%/si', $content, $res);
		if (@$res[1])
			foreach ($res[1] as $el) $content = str_ireplace('%%'.$el.'%%', $data[$el], $content);
		return $content;
	}
}

Достаточно включить этот класс в свой проект и вы можете легко и просто рендерить странички. Как он работает?

Синтаксис:
HTML::render( template [ , array ] );

template – имя шаблона веб-странички. Используется без расширения. По умолчанию шаблоны расположены в папке html (её можно поменять вызовом HTML::changeFolder(‘tpl’), чтобы использовать папку tpl вместо html, к примеру). Шаблоны в папке должны иметь расширение html. Можно использовать любое кол-во вложенных подпапок, естественно.

array – ассоциативный массив, все ключи которого сопоставляются с вхождениями %%…%% в шаблоне и с заменой их значениями. Можно не использовать, если на страничке нет таких элементов.

Например:

$html = array('TITLE' => 'Добро пожаловать!');
$page = HTML::render('index', $html);
die($page);

и браузер выдаст нам отрендеренную страничку. Если в шаблоне html/index.html будет присутствовать вхождение %%TITLE%%, оно будет заменено в данном случае на Добро пожаловать!

Странички состоят из простейших шаблонов – HTML-код + вставка переменных и любых PHP-конструкций.
%%VAR%% – используем подстановку для VAR. VAR – ключ ассоциативного массива, который идёт вторым параметром в вызове HTML::render() (см. выше).
<<PHP_code>> – выполнение PHP кода и отображение на страничке его результата. Можно использовать любые доступные при вызове рендерера функции, и супер-глобальные переменные, например <<$_SERVER[‘HTTP_HOST’]>>
Также может быть использовано для логического ветвления в шаблоне, когда рендерер отобразит особую часть из шаблона при выполнении определённого условия. Пример смотрите ниже.

Пример

Но всё слова-слова, но без примера не всё так понятно, верно.

Вот наш шаблон:

<!DOCTYPE html>
<html lang="ru">
 
<head>
	<meta charset="utf-8">
	<title>Ошибка соединения с БД</title>
</head>
 
<body>
<h1 style="color: blue">Ошибка соединения с БД.<br>
Повторите попытку через минуту!</h1>
<<('%%DEBUG_MODE%%')?'
<div class="info">
%%DB_ERR%%
</div>':''>>
</body>
</html>

Использование:

$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
$user = 'dbuser';
$password = 'dbpass';
 
try {
    $dbh = new PDO($dsn, $user, $password);
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die(HTML::render('err/db', 
      array('DEBUG_MODE' => $_DEBUGGING, 'DB_ERR' => $e->getMessage())))
}

В этом примере делается попытка соединиться с БД, и если она не удалась, выводится страница из шаблона, находящегося в файле html/err/db.html. %%DB_ERR%% заменяется значением $e->getMessage(), и оно будет включено в страничку, только если %%DEBUG_MODE%%, который преобразуется в true/false согласно переменной $_DEBUGGING, будет равен true.

Этот класс можно применять не только для рендеринга цельных (оконечных) страничек, но и для обработки любых HTML-кусков. Да, возможно не хватает выполнения циклических блоков, как в Smarty, например, но для 40-ка строчек PHP-кода, я полагаю, и это совсем неплохо. Любую нужную функциональность уже добавляем по мере необходимости и по прихоти клиентов.

Удачи на даче! И крепкого чая, крепкой любви и крепкого имбиря.

Моя статья в Хакер “Заморозь своего пингвина”

Предисловие

Здравствуйте.
Почти 8 лет назад в журнале Хакер 2007 года за сентябрь (№105) была опубликована моя статья. Как она создавалась? Я уже сейчас не помню точно, помню только, что я увлекался Линуксом тогда и мне понравился Suspend2 (ныне TuxOnIce), я настроил его у себя в Gentoo и у меня всё получилось. Это было круто и я захотел поделиться с сообществом по теме. моим любимым журналом тогда был “Хакер” (сейчас – LinuxFormat), там был раздел Unixoid. Я связался с редактором раздела, объяснил ему тему, он мне ответил что в принципе тема неплоха, давай попробуем. Объяснил условия, формат статьи и её объем максимальный. Что в итоге – я всё сделал по их стандартам (журнала Хакер), выслал им архивчик, и моя статья была опубликована в Хакере №9 (105) от 2007 года – https://xakep.ru/issues/xa/105

Статья

Статья назвается “Заморозь своего пингвина – отправляем Линукс в спячку”. Правда почему-то рядом с моим именем красовлось какое-то имя Goabruce (написано было GOABRUCE & BEOM BEOTIGER). Я написал редактору, что за goabruce и как он тут оказался, ведь статью писал и компоновал всё в ней я один (редактор только её урезал). Он ответил, мол, извините ошибка вышла. Это просто фантастика. За всё время чтения журнала Хакер я такого больше не встречал. Ну да ладно, Бог с этим goabruce’ом, кто бы он ни был. Может он и правда во сне помогал мне делать эту статью.

Буду краток как никогда. В статье рассказывалось о новом методе погружения Линукса в сон (hibernation), названным автором Suspend2. Суть его в том, что текущая RAM системы записывается на диск (в файл или раздел подкачки), и компьютер выключается/перезагружается, а при повторном входе в систему память полностью восстанавливается как есть с диска – и всё текущее окружение становится доступным сразу. то есть все открытые программы, процессы, окна и т.п. при таком входе в систему остаются на месте, и ты можешь продолжить работу как есть, как будто компьютер вовсе не выключался на ночь (или день, смотря кто когда работает).

Круто? Да, круто. Удобно? Несомненно. Да просто супер!

Сегодня

Итак, после большого перерыва, когда я пользовался Linux’ом только время от времени (в виртуальных машинах), с 2008 по 2015 год, когда я поставил себе сначала Kubuntu, потом снес её и установил Linux Mint, чему несказанно рад сейчас, мне на глаза попалась эта моя старая позабытая сейчас уже статья. Ради интереса я подумал, а что там с Suspend2 – заглянул на сайт http://www.suspend2.net, бывший визитной карточкой проекта, а там реклама – он на продажу!

Я подумал, проект загнулся, автор утратил к нему интерес, как часто бывает с открытыми проектами, не приносящими прибыль, потом на глаза мне попалось словосочетание TuxOnIce. Пингвин на Льду? Правильнее было бы назвать – TuxInIce – пингвин во льду. поиск tuxonice в гугле вывел на страничку, до боли знакомую – http://tuxonice.nigelcunningham.com.au Так вот же он, мой родной suspend2! Для прикола я решил попробовать, получится ли у меня поставить его на свой Mint, только без перекомпиляции ядра и всеми прочими долгими настройками, что описывались в моей статье.

Сделал по инструкции на сайте – у них есть прекомплированная версия для Ubuntu (а Mint 100% совместим с Юбунту, по крайней мере так я прочитал в руководстве по Минту), устанавливаемая через PPA – крутая штука, из-за которой я променял Деби на Убунту, а потом Убунту на Минт. Здесь – https://launchpad.net/~tuxonice/+archive/ubuntu/ppa

Просто apt install linux-generic-tuxonice tuxonice-userui, потом выполнил команду “sudo pm-hibernate” и … ничего. Блин, обидно, не работает. Ещё на каком то источнике по теме я прочитал слово “reboot”, перезагрузился, попробовал снова sudo pm-hibernate и всё заработало. Линукс мой ушел в спячку, а потом вернулся волшебным образом. И сейчас я пользуюсь TuxOnIce без проблем (где-то с месяц наверное, правда у меня раздел подкачки около 4 гигов против 8 гигов RAM, как бы это проблем не вызвало, если память будет моя загружена достаточно – а разбираться с подменой образа честно лень пока).

Сама статья

А в качестве бонуса я публикую здесь свою как есть, без купюр, тем более тот номер Хакера от 2007 года/сентябрь давно доступен для скачивания бесплатно с сайта xakep.ru – https://xakep.ru/issues/?y=2007

Скачать оригинал статьи от 2007 года вместе с рабочими материалами и скриншотами можно здесь: http://beotiger.com/download/xakep_article2007

Заморозь своего пингвина.

Предыстория.

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

В этом случае на помощь придёт Suspend2 (http://www.suspend2.net). Почему именно он? Во-первых, это активно развивающийся и успешный проект Найджэла Канингхэма (Nigel Cunningham), Бернарда Блэкхэма (Bernard Blackham), Флоренца Шобо (Florent Chabaud) и многих других, который в своё время отделился от swsusp и сейчас развивается независимо. Во-вторых, он обладает вкусностями, мимо которых не может пройти ни один заядлый линуксоид, да и просто любитель компьютеров. Вот основные из них:

  • Динамическая и быстрая компрессия образа памяти (по умолчанию используется метод LZF).
  • Полная поддержка асинхронного или предупреждающего чтения-записи
  • Поддержка любого количества своп-разделов или файлов.
  • Возможность безопасно прервать процесс засыпания нажатием клавиши ESC.
  • Возможность записи полного образа памяти
  • Поддержка сжатия и кодирования записываемого образа.
  • Доброжелательный графический интерфейс.
  • Поддержка больших объёмов памяти (на настоящий момент – вплоть до 4 Гигабайт), многопроцессорных систем.
  • Поддержка скриптов.
  • Может быть полноценной заменой стандартному swsusp.

Если вкратце, то Suspend2 сохраняет содержимое RAM компьютера и выключает питание. При последующем включении он восстанавливает содержимое RAM, и вы можете продолжать работу как ни в чём не бывало – нет необходимости снова запускать программы, открывать документы, терминалы и т.д. и т.п.

Что нужно для успешной установки и работы Suspend2? В принципе, если у вас современный компьютер на базе процессора Pentuim и IDE диски, а так же свежее ядро ветки 2.6, то с большой вероятностью Suspend2 будет работать без проблем. В частности, для корректной работы необходима поддержка процессором pse или pse36 (page size extensions).

Проверяем:

$ cat /proc/cpuinfo | grep flags

flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe cid xtpr

В данном случае процессор (а это относительно старенький Celeron 2ГГц), имеет поддержку и того, и другого.

Скриншот 1: Основная страница проекта Suspend2.

Как уже упоминалось, проект отделился от swsusp, но, к сожалению, по некоторым разногласиям среди кёрнел-хакеров, в отличие от последнего не включён в ванильные ядра, и чтобы использовать Suspend2, нам надо будет наложить патч и перекомпилировать ядро.

Готовим ядро.

Да. Если вы никогда раньше не компилировали ядро своему любимому Пингвину… что ж, самое время сделать это сейчас. Как говорится, всё всегда когда-нибудь бывает в первый раз. Тем более процедура компиляции ядра не такая сложная и утомительная, как может показаться на первый взгляд. Но, поначалу, конечно, всё будет не так просто. Главное, помните, что не следует сжигать мосты за собой, то есть не удаляйте ваше текущее рабочее ядро из /boot и ссылки на него из загрузчика, пока не убедитесь в течение достаточного времени, что новое ядро, которое вы сами откомпилировали, работает без проблем. Ссылки на статьи по конфигурировании и компиляции ядра в Линуксе вы можете найти во врезке.

Итак, сперва убедитесь, что исходники работающего в данный момент ядра лежат в /usr/src/linux (дефолтовое место для большинства линукс-дистрибутивов).

Смотрим:
$ uname -a
Linux beoplanet 2.6.19.2 #3 Mon May 14 17:09:01 MSD 2007 i686 Intel(R) Celeron(R) CPU 2.00GHz GenuineIntel GNU/Linux
$ file /usr/src/linux
/usr/src/linux: symbolic link to `linux-2.6.19.2'
$ ls /usr/src/linux
arch Documentation ipc Makefile REPORTING-BUGS usr
block drivers Kbuild mm scripts vmlinux
COPYING fs kernel Module.symvers security
CREDITS include lib net sound
crypto init MAINTAINERS README System.map

Здесь мы видим, что у нас рабочее ядрышко 2.6.19.2, а символическая ссылка (/usr/src/linux) указывает на каталог с исходниками именно для этой версии.

Если у вас нет каталога /usr/src/linux, или он пуст, значит, исходники ядра скорее всего просто не установлены в вашей системе. Ничего страшного. Давно пора перейти на свежее ядро, тем более что на каждом диске журнала "Хакер" есть новые ванильные ядра Пингвина. А именно ванильные ядра (то есть истинные, чистые ядра с kernel.org безо всяких патчей, одобренные самим Линусом Торвальдсом) наиболее точно подходят Suspend2! (почему – читайте ниже). Скачиваем свежее ядро с kernel.org, распаковываем его в /usr/src/ и делаем на него симлинк /usr/src/linux.

Обратите внимание на версию ядра. В данный момент на основной странице закачки Suspend2 для версии 2.2.10 предлагаются патчи для следующих версий ядер: 2.6.18.8, 2.6.19.7, 2.6.20.11, 2.6.21.1, 2.6.22-rc1 и ubuntu-feisty.

Для других версий вы можете поискать патчи здесь: http://www.suspend2.net/downloads/all/.

Замечания для владельцев Линукса на базе ядер 2.4. С главной страницы Suspend2 были убраны все ссылки на патчи для этих версий, потому что были сообщения о разрушении файловых систем при их использовании.

Помимо всего прочего, если вы пользователь Gentoo/GNU Linux, то для вас уже есть пропатченные ядра. Просто выполняем команду:
# emerge suspend2-sources

и патчить ядро нам уже не нужно (то есть можно сразу переходить к настройке и компиляции ядра).

Для пользователей последних версий Fedora Core и Red Hat так же есть готовое решение:
# yum install kernel-suspend2

В этом случае штатный инсталлятор всё сделает за вас – вам надо будет только перезагрузиться и использовать hibernate.

Накладываем патч.

Скриншот 2: Страница для закачки патчей и скриптов.

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

Пришло время наложить патч Suspend2. Идём на http://www.suspend2.net/downloads, выбираем подходящий под нашу версию ядра патч, скачиваем его, например, в нашем случае для версии 2.6.19.2 скачиваем suspend2-2.2.9-for-2.6.19.patch.bz2. В общем случае, ядра версий 2.6.X.Y не слишком отличаются от версий 2.6.X, поэтому возможно использование одного и того же патча.

# wget http://www.suspend2.net/downloads/all/suspend2-2.2.9-for-2.6.19.patch.bz2 -P /tmp
Командуем:
# cd /usr/src/linux
# bzcat /tmp/suspend2-2.2.9-for-2.6.19.patch.bz2 | patch -p1
(путь и версия патча в вашем случае могут быть другими).

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

Компилируем ядро.

Теперь делаем make menuconfig, загружаем нашу текущую рабочую конфигурацию и приступаем к настройке поддержки Suspend2 в ядре.

Сперва убедимся, что включён Prompt for development and/or incomplete code/drivers в секции Code Maturity, включающий некоторые тестовые опции в конфигурировании ядра. Затем заходим в секцию Power management options (ACPI, APM) и видим там новый пункт Suspend2. Отмечаем его, и тут же заходим в подменю.

Здесь нужно сделать паузу и решить, что мы будем использовать в качестве буфера – специальный файл на жёстком диске или раздел подкачки. За это отвечают две опции: File Allocator и Swap Allocator. В принципе, можно отметить оба пункта, и решать откуда грузиться, непосредственно в самом загрузчике (см. далее). Но должен быть отмечен хотя бы один пункт! Другие опции можно оставить как есть, но, забегая вперёд, скажу, что если при восстановлении со свопа в загрузчике вы не хотите указывать девайс свопа, можно сделать это здесь, в пункте Default resume device name задав имя свопа, например, так: swap:/dev/hdb4, где /dev/hdb4 и есть раздел файла подкачки (в вашем случае он, скорее всего, будет другим).

Теперь идём в раздел Cryptographic options, находим пункт LZF compression algorithm и включаем его. Заметьте, что он должен быть встроен непосредственно в ядро, а не включен в виде модуля, иначе сжатие не будет работать.

Также, если у вас карточка от Nvidia на шине AGP, и вы не хотите при пробуждении лицезреть тёмный экран, необходимо в ядре отключить agpgart – поддержку AGP, включённую по умолчанию, тем более что у драйверов от Nvidia есть своя поддержка этой шины. Итак, заходим в секцию Device Drivers, подсекцию Character devices, там находим пункт /dev/agpgart (AGP Support) и выключаем его.

Скриншот 3: Конфигурируем ядро.

Если эта версия ядра не использует Initrd/Initramfs, то здесь можно сохраняться и компилировать своё ядро:

#make && make modules_install

и переходить к следующему пункту.

Если же вы используете Initrd/Initramfs, то вам надо будет вручную включить пробуждение: или модифицировать создание initrd/ramfs вашего дистро, или изменить скрипт linuxrc или init, включив туда следующую строчку:

echo 1 > /sys/power/suspend2/do_resume

ВАЖНО: эта строчка должна идти ПЕРЕД тем, как initrd/ramfs монтирует файловую систему! Если этой строчки нет, пробуждение не будет возможным, если же эта строчка идёт ПОСЛЕ монтирования файловой системы, она (файловая система) может быть разрушена! Помните об этом, и будьте осторожны.

Чтобы получить дополнительную информацию об initrd почитайте Documentation/initrd.txt (из каталога исходников ядра).

Предварительная настройка Suspend2

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

Управлять Suspend2 можно через виртуальный каталог /sys/power/suspend2, составляя свои скрипты для пробуждения/восстановления системы, но удобнее всё же будет воспользоваться готовым решением – hibernate-скриптом, который всю работу будет делать за нас.

Скачиваем hibernate-скрипт и устанавливаем его:

#wget http://www.suspend2.net/downloads/all/hibernate-script-1.95.tar.gz -P /tmp
#tar xzf /tmp/hibernate-script-1.95.tar.gz
#cd /tmp/hibernate-script-1.95
#./install.sh

Сам скрипт по умолчанию инсталлируется в /usr/sbin (это можно изменить в install.sh), а конфигурационные файлы (их может быть несколько) инсталлируются в каталог /etc/hibernate/.

Для пользователей Gentoo и Debian дистрибутивов уже есть включённый в их дистрибутивы hibernate-script.

В случае Gentoo делаем

#emerge hibernate-script

А в Debian (и ему подобных) что-то типа этого:

#apt-get install hibernate

По умолчанию настройки Suspend2 разбиты на три файла конфигураций: hibernate.conf, suspend2.conf и common.conf. В принципе, никто не мешает нам собрать их все в один главный файл (hibernate.conf), но мы пойдём по пути наименьшего сопротивления 😉 .

Начнём с первого и отредактируем файл /etc/hibernate/hibernate.conf

#vim /etc/hibernate/hibernate.conf

TryMethod suspend2.conf
#TryMethod disk.conf
#TryMethod ram.conf

Так как мы используем Suspend2, оставляем только его, disk.conf и ram.conf нам не понадобятся.

Дальше смотрим файл /etc/hibernate/suspend2.conf

#vim /etc/hibernate/suspend2.conf

UseSuspend2 yes
Reboot no
EnableEscape yes
DefaultConsoleLevel 1
Compressor lzf
Encryptor none

Include common.conf

Здесь находятся общие для Suspend2 настройки. Перечислю лишь основные из них.

Первая строчка UseSuspend2 yes говорит, что мы собираемся использовать именно Suspend2 (а иначе зачем мы вообще патчили наше ядрышко? 😉 )

Опция Reboot решает, хотим ли мы перезагружаться сразу после заморозки.
Опция EnableEscape yes позволит нам отменить процесс заморозки нажатием клавиши ESC.
Опция DefaultConsoleLevel 1определяет вид отображения при заморозке и разморозке (0 – простой прогресс-бар, 1 – прогресс-бар с процентами, 2 и выше выдаёт обильную отладочную информацию о происходящем).
Опции Compressor и Encryptor определяют методы сжатия и шифрования образа. Их имена можно узнать, выполнив команду #cat /proc/crypto.

Остальные настройки здесь вы можете править по вкусу или оставить их как есть, подробную информацию о них вы можете узнать из man(5)hibernate.conf:

$ man 5 hibernate.conf

Теперь переходим к основным настройкам, собранным в файле /etc/hibernate/common.conf:

Подробнее остановлюсь на, пожалуй, самых важных из них, остальные вы так же можете изменить по вкусу, сверяясь с man(5)hibernate.conf.

# vim /etc/hibernate/common.conf

UnmountFSTypes – здесь можно перечислить типы файловых систем, которые нужно размонтировать перед заморозкой, например, UnmountFSTypes smbfs nfs ntfs vfat. Смотрите ниже, раздел Подводные камни, зачем это может понадобиться. В принципе, если у вас есть чётко заданные устройства, можно размонтировать их в пункте Unmount (например, Unmount /media/winC /media/MyHomeNetwork)

Их же можно смонтировать обратно при пробуждении в пункте Mount (Mount /media/winC /media/MyHomeNetwork), иначе при пробуждении Suspend2 не сделает это автоматически.

Пункт UnloadModules позволяет перечислить модули, которые обязательно надо выгрузить перед заморозкой, но можно воспользоваться пунктами UnloadAllModules yes для выгрузки всех модулей, или UnloadBlacklistedModules yes для выгрузки тех модулей,чьи имена перечислены в файле /etc/hibernate/blacklisted-modules. Пункт LoadModules позволяет задать имена модулей, загружаемых при пробуждении (LoadModules auto автоматически загрузит все модули, которые были выгружены).

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

Пункт RestartServices позволяет останавливать/запускать перечисленные здесь службы. Имена служб должны соответствовать названиям скриптов в каталоге init.d и быть активными на данном уровне запуска (runlevel).

SwitchToTextMode позволяет во время засыпания переключаться в текстовый режим, а при пробуждении возвращаться обратно к X'ам. Это может быть полезно, если BIOS при пробуждении не восстанавливает ваш графический адаптер, и ядро не может его опознать.

Опция UseDummyXServer также может помочь в ряде случаев, когда, например, при пробуждении на некоторых видеокартах наблюдается потеря ускорения в 3D графике.

Параметрами в IncompatiblePrograms вы можете указать программы, которые по каким либо причинам не совместимы с Suspend2, в этом случае, если Suspend2 обнаружит, что такая программа выполняется в настоящий момент времени, он отменит заморозку.

Также можно запереть вход в систему после пробуждения, одним из параметров в опциях LockConsoleAs, LockXScreenSaver, LockGnomeScreenSaver, LockKDE, LockXLock, LockXAutoLock (в таком случае правильным будет определить лишь один из вышеперечисленных параметров). Если вы это сделаете, то после пробуждения необходимо будет вновь залогиниться, чтобы продолжать работать.

Наконец, если в опции XStatus вы укажете одно из значений (kde, gnome или x), то Suspend2 будет выводить прогресс-бар при засыпании/пробуждении, а также выдавать сообщения об ошибках в окошках для указанной графической среды.

Скриншот 4: Настраиваем конфиг.

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

В /etc/hibernate/suspend2.conf ищем строку FilewriterLocation, раскомментируем её и переделываем по своему вкусу, например, так:

FilewriterLocation /var/suspend_file 1024

Здесь первый параметр – это имя файла под буфер, второй – его размер в мегабайтах. Обычно его размер можно указывать равным объёму оперативки вашего бокса – не забудьте, что Suspend2 сжимает сохранённый образ RAM!

Теперь командуем:

#hibernate –no-suspend

и Suspend2 сам подготовит для нас файл. Смотрим, что выдаёт /sys/power/suspend2/resume2

#cat /sys/power/suspend2/resume2

Это может быть что-то типа file:/dev/hda1:0x10011f. Записываем или запоминаем эту строчку – она нам позже понадобится при конфигурировании загрузчика.

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

В файле /etc/hibernate/suspend2.conf находим и заполняем следующий пункт:

SuspendDevice swap:/dev/hda3/swap_file

Запускаем:

# hibernate –no-suspend.

Смотрим:

# cat /sys/power/suspend2/swap/headerlocations

Мы можем получить что-то типа swap:/dev/hda3:0xfd400. Также записываем или запоминаем эту строчку и сперва укажем её в /etc/hibernate/suspend2.conf:

SuspendDevice swap:/dev/hda3:0xfd400

В случае изменения местоположения файла подкачки, или если вы его удалили, а потом вновь восстановили, вам необходимо будет вновь свериться с /sys/power/suspend2/swap/headerlocations, чтобы узнать его новые координаты (для файлов Suspend2 запоминает абсолютное расположение их на жёстком диске).

Эти новые координаты необходимо будет прописать в конфиге и в загрузчике (смотрите ниже).

Настройка загрузчика

Итак, мы откомпилировали ядро и поместили его в /boot, например так: cp arch/i386/boot/bzImage /boot/kernel-2.6.19.2suspend2 (имя по вашему желанию).

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

Если вы используете своп, это может выглядеть так: resume2=swap:/dev/hdb4

Если же вы решили использовать файл, сюда надо подставить значение из /sys/power/suspend2/resume2 с префиксом file:, то есть это может выглядеть так: resume2=file:/dev/hda1:0x10011f.

Если это своп-файл, то строчка может выглядеть так: resume2=swap:/dev/hda3:0xfd400

Вся секция (в случае использовании свопа на /dev/hdb4) может выглядеть так (при использовании grub):

title Wake UP! (Gentoo Linux – kernel 2.6.19.2 with Suspend2)
root (hd0,0)
kernel /boot/kernel-2.6.19.2suspend2 root=/dev/hdb1 init=/sbin/init quiet resume2=swap:/dev/hdb4

В вашем случае имена разделов и образа ядра могут быть другими.

В lilo это же надо указывать примерно так:

image = /boot/ kernel-2.6.19.2suspend2
label = Wake UP! (Gentoo Linux – kernel 2.6.19.2 with Suspend2)
append = "resume2=swap:/dev/hdb4"

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

Такая секция может выглядеть, например, так (опять же, если мы используем grub в качестве загрузчика):

title Boot without resume (Gentoo Linux – kernel 2.6.19.2 with Suspend2)
root (hd0,0)
kernel /boot/kernel-2.6.19.2suspend2 root=/dev/hdb1 init=/sbin/init quiet resume2=swap:/dev/hdb4 noresume2

Для lilo:
image = /boot/ kernel-2.6.19.2suspend2
label = Wake UP! (Gentoo Linux – kernel 2.6.19.2 with Suspend2)
append = "resume2=swap:/dev/hdb4 noresume2"
append = "noresume2"

Не забудьте, если вы используете lilo, каждый раз после изменения lilo.conf презапускать lilo:
#/sbin/lilo

Теперь вы всегда сможете загрузить систему без пробуждения, выбрав строчку Boot without resume.

Итак, у нас всё готово. Но сперва необходимо убедиться, что мы всё сделали верно, и можем использовать Suspend2. Для этого сначала необходимо просто перезагрузиться в новом ядрышке (если вы сделали два пункта – без noresume2 и с ним, как мы советовали, можно выбрать любой из них – Suspend2 сам распознаёт готовность системы к пробуждению), и смотрим лог ядра:

$ dmesg | grep Suspend2

Suspend2 Core.
Suspend2 Userspace UI Support module loaded.
Suspend2 Checksumming module loaded.
Suspend2 Userspace Storage Manager module loaded.
Suspend2 Compressor module loaded.
Suspend2 Encryptor module loaded.
Suspend2 Block I/O module loaded.
Suspend2 Swap Allocator module loaded.
Suspend2 2.2.9: SwapAllocator: Signature found.
Suspend2 2.2.9: Resuming enabled.
Suspend2 2.2.9: Normal swapspace found.
Suspend2 2.2.9: No image found.

Обратите внимание на строчку Suspend2 2.2.9: Resuming enabled. Она показывает, что наш пингвин готов к заморозке/разморозке! Несмотря на это, впервые для апробирования этой фичи рекомендуется усыпить систему без X'ов.

Переходим на текстовую виртуальную консоль (Alt+Ctrl+F1) , закрываем X'ы, например, так

# /etc/init.d/xdm stop (или # init 3, если у вас Red Hat, Fedora или Mandrake)

и делаем:

#hibernate

Если засыпания не состоялось (например, Suspend2 не смог выгрузить модуль – а он сообщит об этом на экране или в логе (по умолчанию в /var/log/hibernate.log), можно форсировать процесс:

#hibernate –force

и Suspend2 должен сделать свою работу в любом случае.

Скриншот 5: Примерно так может происходить процесс засыпания.

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

Теперь включаем компьютер опять (если у нас в опции Reboot стояло no), выбираем в загрузчике пункт Wake UP! (Gentoo Linux – kernel 2.6.19.2 with Suspend2), и через небольшой промежуток времени (если всё пошло по плану, конечно) мы оказываемся в той консоли, откуда ушли, с сохранением всего рабочего окружения!

Стартуем X'ы (/etc/init.d/xdm start или init 5), открываем консоль и пробуем заснуть отсюда:
$ su
# hibernate

Потрясены?? Я вас понимаю. Да, Suspend2 работает очень быстро. Например, на засыпание при полной графической среде KDE (у меня система на Celeron-2GHz с 512 метрами RAM и обычными ATA-дисками с разделом подкачки на 512 мегабайт, дешёвый графический адаптер Nvidia MX-440BX с последней версией legacy-драйвера от Nvidia (1.0-9631-pkg1) я трачу около 30 секунд, а на просыпание – 22 секунды! С восстановлением, естественно, полного рабочего окружения KDE, открытых окон с загруженными документами и тому подобное.