2010年10月22日金曜日

Mercurialでパッチの管理

分散バージョン管理システムのMercurialでパッチの管理を行うときは、mq を使う。
使い方のメモ

拡張を登録する

~/.hgrc に拡張機能を登録する。

[extensios]
mq=

元のソースファイルを展開し、 mq を初期化する。
hg init
hg commit --addremove -m "initial commit"
hg qinit
編集する前にパッチの名前をつける
hg qnew -m "説明文" pathc_no_namae

編集後パッチを作成
hg qrefresh


パッチファイルがある場合は

hg qimport patch_file

ちなみに今回はカーネルにvserverとaufsのパッチを当てた。

hg qimport patch-2.6.35.4
hg qimport patch-2.6.35.2-vs2.3.0.36.31.diff
hg qimport aufs2-base.patch
hg qimport aufs2-kbuild.patch
hg qimport aufs2-standalone.patch

hg qnew aufs2-files
include/linux/Kbuild に

header-y = aufs_type.h

を追加。README にはコピーするように書いてあったが、コピーするのはaufs_type.hだけ。

aufs2-standalone/include/linux/aufs_type.h , aufs2-standalone/fs, aufs2-standalone/Documentation をコピー

リポジトリに追加

hg add .
パッチをリフレッシュ

hg qrefresh


.hg/patchesの中身
$ ls .hg/patches/ -1
aufs2-base.patch
aufs2-files
aufs2-kbuild.patch
aufs2-standalone.patch
patch-2.6.35.2-vs2.3.0.36.31.diff
patch-2.6.35.4
series
status


aufsについては、クローンを作って、READMEを読む。

git clone git://aufs.git.sourceforge.net/gitroot/aufs/aufs2-standalone.git

2010年10月2日土曜日

CDイメージを作ってそれをオンメモリで起動する方法

タイトルのとおり、Linuxのroot イメージを作ってそれをオンメモリにマウントして起動するためのアイディア。

-- USBなどの内容物 --

/カーネル
/ルートファイルシステム(initramfs)

-- ルートファイルシステムの内容 --

/init
/bin/busybox
/cdrom-image.iso

-- cdrom-image.iso に必要なもの --
/linuxrc

起動方法

1. syslinux とかでカーネルとルートファイルをロードして、ルートファイルの initが実行される。

2. init で busybox を使って CD イメージをマウントし、switch_root で CD イメージ中の linuxrc を動かす。

3. CD イメージ中のlinuxrc で proc や sys をマウントする。

4. 最後に /sbin/init を実行する。

2010年8月28日土曜日

Debianカーネルパッケージの再構築

debianのカーネルを再構築をしたいのだが、これまで make-kpkg を使った再構築方法しか知らずちょっと調べたのでメモ

make-kpkg を使ったカーネルパッケージの作成方法はここに書いてある。

http://www.debian.org/releases/stable/i386/ch08s06.html.ja

なにをやりたいかというと、今あるカーネルパッケージと同じパッケージを再構築すること。
もしくは、もとから少しだけ変えたい。

make-kpkg を使った方法だと、自分でカーネルのコンフィグレーションをやるようになる。

それの方法は、"Debian Linux Kernel Handbook" にちゃんと書いてあった。
http://kernel-handbook.alioth.debian.org/ch-common-tasks.html#s-common-official


準備


カーネルパッケージをインストール

$ apt-get source linux-2.6

再構築に必要なパッケージをインストール

# apt-get install build-essential fakeroot
# apt-get build-dep linux-2.6

パッチの適用

展開したディレクトリに移動してパッチを当てる。

ソースを展開
$ dpkg-source -x linux-2.6.......dsc

$ fakeroot debian/rules source
$ fakeroot debian/rules setup

お目当てのパッケージを作る

$ fakeroot debian/rules source
$ fakeroot make -f debian/rules.gen binary-arch_i386_none_686

rules.gen の後ろの引数は rules.gen の中身を見て決める。
お目当ては、 binary-arch_i386_vserver_686-bigmem

変更したいときは、url の続きをやるのだが、今日はここまで

2010年8月10日火曜日

squeeze でフォルダ名を日本語にする

$ sudo apt-get install xdg-user-dirs-gtk
$ LANG=C xdg-user-dirs-gtk-update
(vi .config/user-dirs.dirs が編集される)
ログインしなおす。

フォルダをリネームしてくれるわけではないみたい。
日本語フォルダ内にファイルがあるとそのままになっているのであとで自分で移動する。

再ログイン後、ファルダ名を日本語にするか聞かれるが、古いままにする。

squeeze amd64 環境内で i386 の環境を schrootで作成

開発環境を squeeze に入れ替えた。
build は i386 なので、schroot の環境を作成


$ sudo aptitude install cdebootstrap schroot



$ sudo cdebootstrap --arch=i386 --flavour=build squeeze squeeze-i386 \ http://ftp.jp.debian.org/debian



$ sudo groupadd pnuts

自分をpnuts グループに追加


[sarge-i386]
# Optional. The chroot with alias 'default' is used if you just type
# 'schroot' without the -c option.
aliases=testing,default
# Whatever you like
description=Debian sarge
# Relative to what was /mnt until a moment ago
location=/sarge-i386
# Below here is standard for all the chroots
# Adjust according to the space available and size of builds you'll do
lvm-snapshot-options=--size 2G
device=/dev/デバイス
type=lvm-snapshot
priority=3
groups=pnuts,root
root-groups=pnuts,root
source-groups=pnuts,root
source-root-groups=root


$ sudo schroot -c squeeze-i386-source
(squeeze-i386-source)root@debian:~# apt-get upgrade
(squeeze-i386-source)root@debian:~# apt-get install devscripts vim-tiny sudo \ fakeroot aptitude build-essential
(squeeze-i386-source)root@debian:~# apt-get clean


ここから、pnut 用の環境作成

デフォルトの設定をコピー

$ cd /etc/schroot
$ sudo cp -a defaults pnut

schroot.conf を編集して、

script-config=pnut/config

を追加。
pnut/config を編集

FSTAB="/etc/schroot/pnut/fstab"
COPYFILES="/etc/schroot/pnut/copyfiles"


pnut/fstab に次の行を追加

/mnt/src /mnt/src none rw,rbind 0 0

(適当にbind でマウントする.)

pnut/copyfiles も適当に追加

2010年3月13日土曜日

Amazon AWS また 最初から

新しいノートパソコンがきたので、AWS用の環境設定のやり直し

ElasticFox を再インストール

2010年1月10日日曜日

erlangの非同期ドライバーでのタームの扱い

非同期ドライバーは非同期スレッドで使いたくてやっているわけだが、
erl_interfaceは使えない。

すべて、eiライブラリだけでやりとりする必要がある。よって、ETERMも使えない。
この結論にいたるまでずいぶんと無駄をした。

それで、前回のコードをeiを使用して書いてみた。

まずは、erlang側のコード

注意点や前回との違いは

erl_ddll:load_driver(".", SharedLib) はspawn してから行う
open_portは binary でオープンする(use_stdioがあるとデバックに便利)
データを渡すときは、term_to_binary、受けとるときは、binary_to_termを使う
サンプルは、整数を扱っているのでリストではなくタプルで渡す。
(サンプルの場合、リストで渡すと、C側で-1と255の区別ができない)


start(SharedLib) ->
spawn(?MODULE, init, [SharedLib]).

init(SharedLib) ->
register(complex, self()),
erl_ddll:load_driver(".", SharedLib),
Port = open_port({spawn_driver, SharedLib}, [binary, use_stdio]),
loop(Port).

stop() ->
complex ! stop.

foo(X) ->
call_port({foo, X}).
bar(Y) ->
call_port({bar, Y}).

call_port(Msg) ->
complex ! {call, self(), Msg},
receive
{complex, Result} ->
Result
end.

loop(Port) ->
receive
{call, Caller, Msg} ->
%Port ! {self(), {command, encode(Msg)}},
Port ! {self(), {command, term_to_binary(encode(Msg))}},
receive
{Port, {data, Data}} ->
Caller ! {complex, decode(Data)}
end,
loop(Port);
stop ->decode([Int]) -> IC側のコードnt;
decode(Res) when is_binary(Res)->
binary_to_term(Res).

Port ! {self(), close},
receive
{Port, closed} ->
exit(normal)
end;
{'EXIT', Port, Reason} ->C側のコード
io:format("~p ~n", [Reason]),
exit(port_terminated)
end.

encode({foo, X}) -> {1, X};
encode({bar, Y}) -> {2, Y}.

decode([Int]) -> Int;
decode(Res) when is_binary(Res)->
binary_to_term(Res).


examplebar.cも変更

C側のコード

long bar(int a) {
return a+1;
}

long foo(int b) {
return b*2;
}

ドライバーの方は抜粋。
いろいろ大変だったが、何とか動いた。
ei_decode_XXX を行う度にindexが書き換わる。


...

typedef struct {
char fn;
int arg;
long res;
} our_async_data;

...

static void example_drv_foobar(void * async_data)
{
our_async_data* d = (our_async_data*)async_data;

if (d->fn == 1) {
d->res = foo(d->arg);
} else if (d->fn == 2) {
d->res = bar(d->arg);
}else{
d->res = 0;
}
}

static void example_drv_error(void * async_data){
our_async_data* d = (our_async_data*)async_data;
d->res = 255;
}

static void example_drv_output(ErlDrvData handle, char* buff, int bufflen)
{
example_data* d = (example_data*)handle;
our_async_data* a = (our_async_data*)malloc(sizeof(our_async_data));
int i, ver, size, type, arity;
int val;
long long_val;
unsigned char str[3];
// indexの初期化を忘れないように
i = 0;
if(0 != ei_decode_version(buff, &i, &ver))printf("error\n\r");
// printf("version is %d.\n\r", ver);
ei_get_type(buff, &i, &type, &size);
printf("term type is %d,(%c).\n\r", type,type);
printf("size is %d.\n\r", size);

if( type == ERL_SMALL_TUPLE_EXT ){
ei_decode_tuple_header(buff, &i, &arity);
printf("list size is %d .\n\r", arity);
ei_get_type(buff, &i, &type, &size);
printf("i1 type is %d,(%c).\n\r", type,type);
if( type == ERL_SMALL_INTEGER_EXT){
ei_decode_char(buff, &i, str);
printf("function is %d\n\r",str[0]);
a->fn = str[0];
ei_get_type(buff, &i, &type, &size);
printf("i2 type is %d,(%c).\n\r", type,type);
if( type == ERL_SMALL_INTEGER_EXT){
ei_decode_char(buff, &i, str);
a->arg = (unsigned int)*str;
printf("arg is %d\n\r",a->arg);
driver_async(d->port, NULL, example_drv_foobar, a, free);
}else if( type == ERL_INTEGER_EXT){
ei_decode_long(buff, &i, &val);
a->arg = val;
printf("arg is %d\n\r",val);

driver_async(d->port, NULL, example_drv_foobar, a, free);
}else{
driver_async(d->port, NULL, example_drv_error, a, free);
}
}else{
driver_async(d->port, NULL, example_drv_error, a, free);
}
}

static void ready_async(ErlDrvData handle, ErlDrvThreadData async_data)
{
ei_x_buff x_buff;
ei_x_new_with_version(&x_buff);
example_data* d = (example_data*)handle;
our_async_data* a = (our_async_data*)async_data;

if( a->res <>res >= 0 ){
ei_x_encode_char(&x_buff, a->res);
}else{
ei_x_encode_long(&x_buff, a->res);
}

driver_output(d->port, x_buff.buff, x_buff.index);
/* not thread safe */
// driver_output_term(d->port, bin, sizeof(bin)/sizeof(bin[0]));
ei_x_free(&x_buff);

free(a);
}

...