VBE grubを起動し、GRUBコマンドライン上でvbeprobeとコマンドを実行すると、現在実行できるVBEのビデオモード番号、解像度、色数が表示される。VMWare Workstation 6で試したところ、このビデオモード番号と解像度が仕様書と番号と解像度が一致していない。

vbeprobeの結果は以下の様になる。(実行環境はVMware Workstation 6)

grub> vbeprobe
 VBE version 2.0
  0x120: Packed pixel, 320x200x8
  0x121: Packed pixel, 320x400x8
  0x122: Packed pixel, 640x400x8
  0x123: Packed pixel, 640x480x8
  0x124: Packed pixel, 800x600x8
  0x125: Packed pixel, 1024x768x8
  0x126: Direct Color, 320x200x16
  0x127: Direct Color, 320x400x16
  0x128: Direct Color, 640x400x16
  0x129: Direct Color, 640x480x16
  0x12a: Direct Color, 800x600x16
  0x12b: Direct Color, 1024x768x16
  0x12c: Direct Color, 320x200x32
  0x12d: Direct Color, 320x400x32
  0x12e: Direct Color, 640x400x32
  0x12f: Direct Color, 640x480x32
  0x130: Direct Color, 800x600x32
  0x131: Direct Color, 1024x768x32
  0x100: Packed pixel, 640x400x8
  0x101: Packed pixel, 640x480x8
  0x103: Packed pixel, 800x600x8
  0x105: Packed pixel, 1024x768x8
  0x10e: Direct Color, 320x200x16
  0x111: Direct Color, 640x480x16
  0x114: Direct Color, 800x600x16
  0x117: Direct Color, 1024x768x16

ビデオモード番号0x131などは1024x768で32ビットカラーで実行できる。VBE Wikipedia:enとビデオモード番号と解像度が違っている。videoset 0x131でVMware上ではGRUBの結果道理に動くからWikipediaが違っているかもしれない(当てにならないけど)。

リニアフレームバッファについて仕様書にはすこし書いてあるが実装が難しい、32ビットカラーの解像度だとうまくいくが、それ以外の解像度だと表示は出るが何かおかしい。だれかVBE リニアフレームバッファについて説明されいるドキュメントを知りませんか?

GRUB Multibootを使用し自作のカーネルなどでSVGAを使う方法

GRUB Multibootの仕様書にはVBE Controller InformationやVBE Mode Informationの構造体のアドレスを取得できると書いてあるが、現在のGRUB 0.97では構造体のアドレスを取得できない。これはGRMUのmenu.lstにvbesetコマンドを書いてもVGAの画面のままでVBEを利用することができない事が原因である。

GRUB Multibootを使い、かつVBEを利用したいときはGRUBの古いバージョンを使用するか、もしくはVBE grubを使用すればこの問題を解決できる。パッチを当てるときはGRUBソースコードcvsからチェックアウトしVBE grubのパッチを当てるとうまくいく。ftp://alpha.gnu.org/gnu/grub/grub-0.97.tar.gzソースコードにパッチを当ててもうまくいかなかった。(configureのオプションが原因かもしれない)

GRUBの設定

GRUBの設定ファイルであるmenu.lstにvbesetのコマンドの引数に値を設定するとカーネル起動時にGRUB側がSVGA表示に切替えてくれる。引数の値は解像度の値でありVBEの仕様書を見るかhttp://en.wikipedia.org/wiki/VESA_BIOS_Extensionsを参考にするととてもわかりやすい。

例えば/boot/grub/menu.lstは以下のように設定する。

title           pxegrub + kernel
dhcp
tftpserver      server_address
root            (nd)
kernel          /kernel
vbeset          0x117
savedefault
boot

フレームバッファなどの取得

VBE Controller InformationやVBE Mode Informationの構造体のアドレスを取得するにはmultiboot.hをGUB Multboot仕様書に書いてあるように追加する。具体的には以下のようにmultiboot_headerとmultiboot_infoの構造体に以下の変数を追加する。

@@ -56,6 +45,10 @@
   unsigned long load_end_addr;
   unsigned long bss_end_addr;
   unsigned long entry_addr;
+  unsigned long mode_type;
+  unsigned long width;
+  unsigned long height;
+  unsigned long depth;
 } multiboot_header_t;
 
 /* The symbol table for a.out.  */
@@ -93,6 +86,17 @@
   } u;
   unsigned long mmap_length;
   unsigned long mmap_addr;
+  unsigned long drives_length;
+  unsigned long drives_addr;
+  unsigned long config_table;
+  unsigned long boot_loader_name;
+  unsigned long apm_table;
+  unsigned long vbe_control_info;
+  unsigned long vbe_mode_info;
+  unsigned short vbe_mode;
+  unsigned short vbe_interface_seg;
+  unsigned short vbe_interface_off;
+  unsigned short vbe_interface_len;
 } multiboot_info_t;
 

変更後、VBE Controller InformationやVBE Mode Informationの構造体のアドレスは以下のように簡単に取得ができる。VBE Mode Informationの構造体にフレームバッファの先頭のアドレスがある。

void vga_init(multiboot_info_t *info)
{
	vbe_info_block_t *vbe_info_blk = (vbe_info_block_t *)info->vbe_control_info;
	mode_info_block_t *mode_info_blk = (mode_info_block_t *)info->vbe_mode_info;

	...
}

スクリーンショット

VMWare上でVBEのデバイスドライバ書いて、四角をランダムに表示するプログラムを試してみた。

iperf

iperfはend-to-endで、ネットワークのスループットの測定ができます。
iperfはTCP, UDPどちらにも対応しいます。

iperfの使いかた

iperfはサーバーとクライアントが必要になります。やり方は次のようにします。

始めに、サーバー側でiperfの待ち状態にします。

$ iperf -s

次に、クライアント側でサーバーに負荷をかけます。

$ iperf -c server_name

デフォルトのオプションはTCPで、クライアント、サーバーの両方に-uのオプションをつけるとUDPになります。

iperfのUDPで帯域負荷の制御

クライアント側でUDPの一秒間に送信できるパケットの数を変更することができます。このオプションは-b size[KM]で使用することができるのですが、オプションを挿入する位置によって"WARNING: option -b is not valid for server mode"と表示されます。

次のようにすると、警告を表示し"-b"のオプションが無視されます。

$ iperf -u -b 1000M -c server_name

次のようにすると、何故か期待した動作をしてくれます。

$ iperf -u -c server_name -b 1000M

"-b"のオプションを"-c"の後につけると期待した動作します。
ほかにもいくつかうまくいくパターンとダメなパターンがあります。

asmlinkage

LilyVMのコード読んでいるとき、asmlinkageのマクロが出てきたが定義がされていない。Linuxカーネルなどにも使用されているので調べてみた。

asmlinkageマクロとは

Linuxカーネルなどによく見かけるマクロの一つとして、asmlinkageマクロがある。このマクロは関数の整数引数を確実に、スタックに渡すことを保証するマクロである。Linuxではシステムコールなどに使われる。システムコールの引数の渡しかたは次の様になる。

  1. システムコールの引数を各レジスタに代入
  2. ソフトウェア割り込み(int0x80)を行う。
  3. カーネル権限に移行後、レジスタから各引数を取り出す。

システムコールの引数は、スタックから各レジスタに代入を行う実装なので、asmlinkageマクロを使用する。

GCC拡張 regparm (number)

asmlinkageのコードは以下の様になっている。

#define asmlinkage __attribute__((regparm(0)))

regparm (number)はコンパイラにnumberの数だけ引数をレジスタに渡します。i386では最大3個まで渡すことが可能です。eax, edx, ecxレジスタを使用します。x86_64環境では最大6個まで渡すことが可能です。edi, esi, edx, ecx,r8d, r9dレジスタを使用します。

regparm使用した結果

i386環境
#include <stdio.h>

__attribute__((regparm(3))) int add(int a1, int a2, int a3, int a4,
				    int a5, int a6, int a7, int a8, int a9)
{
        return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
}

int main(void)
{
        int ret = add(1, 2, 3, 4, 5, 6, 7, 8, 9);

        printf("ret: %d\n", ret);

        return 0;
}

/*
$ objdump -d a.out

08048354 <add>:
 8048354:       55                      push   %ebp
 8048355:       89 e5                   mov    %esp,%ebp
 8048357:       83 ec 0c                sub    $0xc,%esp
 804835a:       89 45 fc                mov    %eax,0xfffffffc(%ebp)
 804835d:       89 55 f8                mov    %edx,0xfffffff8(%ebp)
 8048360:       89 4d f4                mov    %ecx,0xfffffff4(%ebp)
 8048363:       8b 45 f8                mov    0xfffffff8(%ebp),%eax
 8048366:       03 45 fc                add    0xfffffffc(%ebp),%eax
 8048369:       03 45 f4                add    0xfffffff4(%ebp),%eax
 804836c:       03 45 08                add    0x8(%ebp),%eax
 804836f:       03 45 0c                add    0xc(%ebp),%eax
 8048372:       03 45 10                add    0x10(%ebp),%eax
 8048375:       03 45 14                add    0x14(%ebp),%eax
 8048378:       03 45 18                add    0x18(%ebp),%eax
 804837b:       03 45 1c                add    0x1c(%ebp),%eax
 804837e:       c9                      leave
 804837f:       c3                      ret
*/
x86_64環境
#include <stdio.h>
__attribute__((regparm(3))) int add(int a1, int a2, int a3, int a4,
				    int a5, int a6, int a7, int a8, int a9)
{
        return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
}

int main(void)
{
        int ret = add(1, 2, 3, 4, 5, 6, 7, 8, 9);

        printf("ret: %d\n", ret);

        return 0;
}

/*
$ objdump -d a.out

0000000000400478 <add>:
  400478:       55                      push   %rbp
  400479:       48 89 e5                mov    %rsp,%rbp
  40047c:       89 7d fc                mov    %edi,0xfffffffffffffffc(%rbp)
  40047f:       89 75 f8                mov    %esi,0xfffffffffffffff8(%rbp)
  400482:       89 55 f4                mov    %edx,0xfffffffffffffff4(%rbp)
  400485:       89 4d f0                mov    %ecx,0xfffffffffffffff0(%rbp)
  400488:       44 89 45 ec             mov    %r8d,0xffffffffffffffec(%rbp)
  40048c:       44 89 4d e8             mov    %r9d,0xffffffffffffffe8(%rbp)
  400490:       8b 45 f8                mov    0xfffffffffffffff8(%rbp),%eax
  400493:       03 45 fc                add    0xfffffffffffffffc(%rbp),%eax
  400496:       03 45 f4                add    0xfffffffffffffff4(%rbp),%eax
  400499:       03 45 f0                add    0xfffffffffffffff0(%rbp),%eax
  40049c:       03 45 ec                add    0xffffffffffffffec(%rbp),%eax
  40049f:       03 45 e8                add    0xffffffffffffffe8(%rbp),%eax
  4004a2:       03 45 10                add    0x10(%rbp),%eax
  4004a5:       03 45 18                add    0x18(%rbp),%eax
  4004a8:       03 45 20                add    0x20(%rbp),%eax
  4004ab:       c9                      leaveq
  4004ac:       c3                      retq
*/

タグ付き正規表現で置換

タグ付き正規表現は、一度使用した正規表現を繰り返し使いたいときに使用します。
sed, awk, emacs, grep, egrepなどがタグ付き正規表現が使えます。

使いかたは

例は次の様になります。
次のような文章があり、先頭の";; "を除去したいときタグ付き正規表現を使用し置換する。

;; This buffer is for notes you don't want to save, and for Lisp evaluation.
;; If you want to create a file, visit that file with C-x C-f,
;; then enter the text in that file's own buffer.

次の正規表現で置換する。emacsではreplce-regexp, sed, awkでも同様に使える。

置換前 ^;; \(.*\) 
置換後 \1

実行結果は次の様になります。

This buffer is for notes you don't want to save, and for Lisp evaluation.
If you want to create a file, visit that file with C-x C-f,
then enter the text in that file's own buffer.

X11で透過処理

Gnome + BerylからFluxboxに環境を移動したとき、ウィンドウの透過処理ができなくなった。
この問題を解決するために、transset, xcompmgrを使用すればウィンドウの透過処理を実現できる。

transset, xcompmgr インストール

$ cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xapps co transset
$ cd transset
$ make
$ cp translet /usr/local/bin
$ cd ..

$ cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xapps co xcompmgr
$ cd xcompmgr
$ ./autogen.sh 
$ configure --prefix=/usr/local
$ make install

透過処理のしかた

まず始めにxcompmgrを起動させる。.xinircなどに次の行を追加させれば自動的に起動する。

xcompmgr -cf &

次にtranssetを実行する。次のように実行するし、透過したいウィンドウをマウスでクリックすると50%の透過する。

$ transset 0.5

透過するのにコマンドを入力するのは大変なのでショートカットキーでコマンドを実行させる、Fluxboxでは~/.fluxbox/keysコマンドを書けばコマンドを登録できる。
自分の環境では次のように登録した。Ctrl+Alt+F[1-10]で透過を90%から0%まで変更できるようにした。

Mod1 Shift F1 :ExecCommand transset 0.1
Mod1 Shift F2 :ExecCommand transset 0.2
Mod1 Shift F3 :ExecCommand transset 0.3
Mod1 Shift F4 :ExecCommand transset 0.4
Mod1 Shift F5 :ExecCommand transset 0.5
Mod1 Shift F6 :ExecCommand transset 0.6
Mod1 Shift F7 :ExecCommand transset 0.7
Mod1 Shift F8 :ExecCommand transset 0.8
Mod1 Shift F9 :ExecCommand transset 0.9
Mod1 Shift F10 :ExecCommand transset 1.0

make代替ツール

Jam(just another make)とはmakeの様なビルドツールです。makeより後発に開発されたのでmakeよりはるかに優れています。
Windowsだとバイナリ配布、Linuxなどではapt-get install jamなどで簡単にインストールができるので手軽に試せます。

Jamの特徴は次の様な事があげられます。

  • 移植性がある。
    • 環境(Windows, Linux, etc)ごとにルールがあり、それを利用することにより簡単に移植性があるJamfileを書くことが可能。
  • 高速に実行される。
    • Jamfileを読み込み、構文解析をし、逐次的に実行されるのでとても高速に実行ができる。
  • 簡単に並列コンパイルができる。
    • オプションの引数に-j nとすればn個並列にコンパイルする。
  • C言語などのヘッダファイル依存関係を自動的に処理を行ってくれる。

使用してみた感じとして、makeよりはるかに単純だがJam特有の構文やルールを覚えるのに少してこずる。Jamのチュートリアル(PDF)のがあるので最初はこれを見るのがいいだろう。

C言語のファイルをmain.c sub1.c sub2.cのファイルをコンパイルしa.outのプログラムを作るときの簡単なJamfileの例は以下の様になる。

CC      = gcc ;
CCFLAGS = -Wall -Wextra ;
#HDRS = ../include ;

Main a.out : main.c sub1.c sub2.c ;