Linux Native KVM Toolsのメモリ割り当て

LKNTが仮想マシンにメモリをどのように割り当てているのか調べました. 流れとしては,ゲスト作成時にメモリを確保,KVMに確保したメモリを伝える,ゲストが終了する際に確保していたメモリを開放という手順です. 今回はユーザ側のコードですが,いずれはKVMの内部でメモリがどのように扱われているのかも調べてみたいです.

ユーザインタフェース

$ ./kvm run -m 256

ユーザがゲストに割り当てるメモリのサイズを指定するにはコマンドライン引数を用います.

メモリ確保

static u64 ram_size;

指定した値は,グローバル変数のram_sizeに格納されます.

build-run.c/int kvm_cmd_run

if (!ram_size)
    ram_size    = get_ram_size(nrcpus);

コマンドライン引数で指定しなかった場合どうなるのでしょうか? build-run.cの中でram_sizeに値が格納されているかどうかを確認し,格 納されていない場合はget_ram_size関数で割り当てるメモリサイズを算出 し,ram_sizeに格納します.

build-run.c

#define RAM_SIZE_RATIO      0.8
static u64 get_ram_size(int nr_cpus)
{
    u64 available;
    u64 ram_size;

    ram_size    = 64 * (nr_cpus + 3);

    available   = host_ram_size() * RAM_SIZE_RATIO;
    if (!available)
        available = MIN_RAM_SIZE_MB;

    if (ram_size > available)
        ram_size    = available;

    return ram_size;
}

get_ram_sizeには使用可能なCPUコア数を渡しています.そして,コア数からメモリサイズを算出します. コア数が2なら,64x(2+3)=320MBとなるようです. ゲストに割り当てられるメモリサイズはマシン全体のメモリサイズにRAM_SIZE_RATIOを掛けたサイズとなります. 算出したメモリサイズが割り当てられる限界値を越えている場合,限界値に修正してram_sizeを返却します.

build.c/host_ram_size

static u64 host_ram_size(void)
{
    long page_size;
    long nr_pages;

    nr_pages    = sysconf(_SC_PHYS_PAGES);
    if (nr_pages < 0) {
        pr_warning("sysconf(_SC_PHYS_PAGES) failed");
        return 0;
    }

    page_size   = sysconf(_SC_PAGE_SIZE);
    if (page_size < 0) {
        pr_warning("sysconf(_SC_PAGE_SIZE) failed");
        return 0;
    }

    return (nr_pages * page_size) >> MB_SHIFT;
}

get_ram_sizeの中で呼び出されているhost_ram_size関数はホストマシンのメモリサイズを調べる関数です. sysconf(_SC_PHYS_PAGES)で物理メモリのページ数を取得,sysconf(_SC_PAGE_SIZE)でページサイズをバイト単位で取得します. ページ数xページサイズ=メモリサイズ(バイト)となります. 最後に単位をメガバイトに変更して返却します. メガバイトに変換する時,右シフトを使っています.

build.c

#define MB_SHIFT      (20)

1メガバイト = 1048576バイトで,2進数にすると1048576 = 0b100000000000000000000となります. これを20ビット右シフトすると1になり,バイトからメガバイトへ変換ができるわけです.

build-run.c/int kvm_cmd_run

if (ram_size < MIN_RAM_SIZE_MB)
    die("Not enough memory specified: %lluMB (min %lluMB)", ram_size, MIN_RAM_SIZE_MB);

if (ram_size > host_ram_size())
    pr_warning("Guest memory size %lluMB exceeds host physical RAM size %lluMB", ram_size, host_ram_size());

ram_size <<= MB_SHIFT;

ゲストに割り当てるメモリのサイズが最小サイズより大きいか,もしくはホストのメモリサイズより大きくなっていないか確認します. 問題なければ,ram_sizeをメガバイトからバイトに戻しています.

KVMへ確保したメモリを登録する

さて,kvmの初期化関数に移動しましょう.

builtin-run.c/kvm_cmd_run

kvm = kvm__init(dev, ram_size, guest_name);

kvm_initは,さらにアーキテクチャ固有のinit関数を呼び出しています.

kvm.c/kvm__init

kvm__arch_init(kvm, kvm_dev, ram_size, name);

x86/kvm.c

/* Architecture-specific KVM init */
void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, u64 ram_size, const char *name)
{
    struct kvm_pit_config pit_config = { .flags = 0, };
    int ret;

    ret = ioctl(kvm->vm_fd, KVM_SET_TSS_ADDR, 0xfffbd000);
    if (ret < 0)
        die_perror("KVM_SET_TSS_ADDR ioctl");

    ret = ioctl(kvm->vm_fd, KVM_CREATE_PIT2, &pit_config);
    if (ret < 0)
        die_perror("KVM_CREATE_PIT2 ioctl");

    kvm->ram_size       = ram_size;

    if (kvm->ram_size < KVM_32BIT_GAP_START) {
        kvm->ram_start = mmap(NULL, ram_size, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
    } else {
        kvm->ram_start = mmap(NULL, ram_size + KVM_32BIT_GAP_SIZE, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
        if (kvm->ram_start != MAP_FAILED) {
            /*
             * We mprotect the gap (see kvm__init_ram() for details) PROT_NONE so that
             * if we accidently write to it, we will know.
             */
            mprotect(kvm->ram_start + KVM_32BIT_GAP_START, KVM_32BIT_GAP_SIZE, PROT_NONE);
        }
    }
    if (kvm->ram_start == MAP_FAILED)
        die("out of memory");

    madvise(kvm->ram_start, kvm->ram_size, MADV_MERGEABLE);

    ret = ioctl(kvm->vm_fd, KVM_CREATE_IRQCHIP);
    if (ret < 0)
        die_perror("KVM_CREATE_IRQCHIP ioctl");
}

kvm->ram_sizeにコマンドライン引数から取得した/自動生成したメモリサイズを格納します. ここで,32bitのギャップについてチェックしています.

#define KVM_32BIT_GAP_START   ((1ULL << 32) - KVM_32BIT_GAP_SIZE)
#define KVM_32BIT_GAP_SIZE    (768 << 20)

KVM_32BIT_GAP_SIZEは (768<<20) = 805306368 = 768MB. KVM_32BIT_GAP_STARTは ((1ULL << 32) – KVM_32BIT_GAP_SIZE) = (4294967296 – 768MB) = (4096MB -768MB) = 3328MB.

指定したram_sizeが3328MBより小さい場合,そのサイズをmmapで確保します. ram_sizeが3328MB以上の場合,ram_size+768MBをmmapでマッピングします. メモリのマップに成功した場合,mprotectを使ってkvm->ram_start + KVM_32BIT_GAP_START〜KVM_32BIT_GAP_SIZEのメモリ範囲のアクセス保護を設定しています. PROT_NOTEは,メモリに全くアクセスできない設定となります. メモリのマップに失敗した場合はdieです.

madviceはメモリの利用に関するアドバイスを設定する関数です. kvm->ram_startからkvm->ram_sizeの範囲について,MADV_MERGEABLEに設定しています.MADV_MERGEABLEは,ユーザがマージしてもよいという設定です.

メモリの設定

build-run.cでしばらく先にあるkvm__init_ramでメモリ設定を行います.

builtin-run.c

kvm__init_ram(kvm);

x86/kvm.c

void kvm__init_ram(struct kvm *kvm)
{
    u64 phys_start, phys_size;
    void    *host_mem;

    if (kvm->ram_size < KVM_32BIT_GAP_START) {
        /* Use a single block of RAM for 32bit RAM */

        phys_start = 0;
        phys_size  = kvm->ram_size;
        host_mem   = kvm->ram_start;

        kvm__register_mem(kvm, phys_start, phys_size, host_mem);
    } else {
        /* First RAM range from zero to the PCI gap: */

        phys_start = 0;
        phys_size  = KVM_32BIT_GAP_START;
        host_mem   = kvm->ram_start;

        kvm__register_mem(kvm, phys_start, phys_size, host_mem);

        /* Second RAM range from 4GB to the end of RAM: */

        phys_start = 0x100000000ULL;
        phys_size  = kvm->ram_size - phys_size;
        host_mem   = kvm->ram_start + phys_start;

        kvm__register_mem(kvm, phys_start, phys_size, host_mem);
    }
}

ここでも32ビットギャップを調べて,結果によって挙動を変えています. メモリサイズが3328MBより小さい場合,ゲストに設定する仮想メモリのサイズにkvm->ram_sizeを,ホストメモリの開始位置にkvm->ram_startを格納し,kvm__register_memを呼び出してVMのメモリの設定を行います.

3328MB以上の場合,仮想メモリのサイズに3328MBを設定してVMのメモリ設定を行い, その後,残りのサイズを再びVMに設定しています.

/kvm.c

 */
void kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr)
{
    struct kvm_userspace_memory_region mem;
    int ret;

    mem = (struct kvm_userspace_memory_region) {
        .slot           = kvm->mem_slots++,
        .guest_phys_addr    = guest_phys,
        .memory_size        = size,
        .userspace_addr     = (unsigned long)userspace_addr,
    };

    ret = ioctl(kvm->vm_fd, KVM_SET_USER_MEMORY_REGION, &mem);
    if (ret < 0)
        die_perror("KVM_SET_USER_MEMORY_REGION ioctl");
}

ioctlのKVM_SET_USER_MEMORY_REGIONを使い,VMにメモリの変更を許可します.

KVM_SET_USER_MEMORY_REGIONはKVMのAPIです. mem_slotsがマザーボードのメモリスロットに対応するようです. 3328MB以上のメモリを扱う場合は,複数スロットに分割するわけですね. これで,VMがメモリを使えるようになります.

メモリの開放

VMを終了するときにメモリを開放する必要があります.kvm__deleteの中で開放されています.

builtin-run.c

kvm__delete(kvm);

kvm.c

void kvm__delete(struct kvm *kvm)
{
    kvm__stop_timer(kvm);

    munmap(kvm->ram_start, kvm->ram_size);
    kvm_ipc__stop();
    kvm__remove_socket(kvm->name);
    free(kvm);
}

munmapを使い,指定したアドレス範囲のマップを消去するだけのようです.

Emacsのデータストアを見てみる

本記事はEmacs Advent Calendar jp: 2011 : ATNDの23日目です. emacs lispで,keyとvalueを扱う方法について調べていたので,そのま とめです. emacs lispでkey-valueを扱う方法としては,alist(連想リスト), plist(属性リスト),ハッシュテーブルがあるようです. alistとplistはS式を使ったもので,シンプルです.ただ,リストを順番 に見ていくため,計算量は最悪の場合O(n)となり,効率が悪そうです. ハッシュテーブルの場合,計算量はO(1)なので,大量のデータを扱う場 合はplistやalistより速いのですが,データをS式で扱うのではなくハッ シュテーブル型になります. どれを使うかは,用途によるでしょう,plistはユーザが設定を書く時に よく使われますね.

alist(連想リスト)

alist(association list)はコンスセルを用いたリスト.

(setq color '((meiko . red)
              (kaito . blue)
              (miku . green)))          ; => ((meiko . red) (kaito . blue) (miku . green))

(assoc 'miku color)                     ; => (miku . green)

(rassoc 'red color)                     ; => (meiko . red)

keyを与えるとkeyとvalueのコンスセルが返ってきます.valueを取り出 すためにcdrを使うのが少し手間な気がします.

plist(属性リスト)

plist(property list)は属性を保持するためのリスト.

(setq color '(:meiko red :kaito blue :miku green)) ; => (:meiko red :kaito blue :miku green)

(plist-get color :meiko)                ; => red

(plist-put color :ruka 'pink)           ; => (:meiko red :kaito blue :miku green :ruka pink)

個人的に好きなデータ構造です.リストなので扱いやすいためです.

hash table

名前の通り,ハッシュテーブル.

(setq color (make-hash-table))          ; => #s(hash-table size 65 test eql rehash-size 1.5 rehash-threshold 0.8 data ( ...))

(puthash :miku 'green color)            ; => green

(gethash :miku color)                   ; => green

ハッシュテーブルは,今回調べていて初めて存在を知りました.Emacsで 大量のkeyとvalueを扱う場合は素直にハッシュテーブルを使うのがよさ そうですね.

おわりに

EmacsLispでkeyとvalueを扱う構造について紹介しました. Emacs で IPC や RPC (Emacs Advent Calendar jp: 2011) – 技術 日記@kiwanamiのように,emacs lispから外部の言語やDBにアクセスす る試みも行われています.RDBやKVSをemacsから使う日もそう遠くはなさ そうです.

ありえるたんがかわいい

こんにちは,来年の4月からアリエルで8クイーンを書く予定になっている r_takaishiです.Ariel Advent Calendar 2011 : ATNDの22日目です. CTOに誘われたので書くことにしたのですが, 社内ネタを持っていないので,ありえるの中の人であるありえるたん を紹介 します.

twitterでは,ありえるえるあの更新告知をしたり,時々呟いているよう です.ArielAdventCalendarでも記事を書いていて ,なかなか活発ですね.さて,前から気になっていたのですが,ありえるたんのアイコンは こんなアイコンです.

http://a2.twimg.com/profile_images/1374385066/20110529kaeru-ariel-400.jpg

かわいいですね.なぜカエルスーツなのでしょうか?気になります.

http://a0.twimg.com/profile_background_images/145928719/20100907ariel-autamn-500.jpg

カエルスーツを脱ぐとこんな格好のようです.かわいいですね.アリの 触角みたいなのがチャームポイントのようです.

かわいいので,ぜひグッズ化してほしいですね.明日は,闇えるたん さんです.

Linux Native KVM Toolsを使ってみよう

少しずつ認知され始めたLinux Native KVM Tools(NLKT)を使ってゲス トを起動する方法について解説します.この記事は,カーネル/VM Advent Calendar : ATNDの11日目です.

Linux Native KVM Toolsとは?

今広く使われているKVMは,QEMUを用いたものですが,Linux Native KVM Tools(以下LNKT)は,QEMUを使わず1から書いたVMMです.またカーネルの メインラインにはマージされていませんが,近い内にマージされるよう です.Github上(penberg/linux-kvm – GitHub)で開発が行われています.

使ってみる

さて,何はともあれまずは動かしてみましょう. 私は,X60s,i386,GentooLinuxで検証しています.えらく古い環境です が,VTは動くので検証する分には問題ありません.

まずはソースコードを入手します.Githubからリポジトリをcloneするの が一番簡単です.

$ cd ~/
$ git clone https://github.com/penberg/linux-kvm.git

linux-kvm/tools/kvmに移動してmakeしましょう.

$ cd linux-kvm/tools/kvm
$ make

とりあえず動かすために,linux-0.2のディスクイメージを使います.ダ ウンロードして展開しておきます.

$ wget http://wiki.qemu.org/download/linux-0.2.img.bz2 && bunzip2 linux-0.2.img.bz2

kvm-toolsではディスクイメージとは別にカーネルイメージが必要です. ホストマシンで使っているカーネルイメージを使ってもいいでし, linux-kvm用に作ってもいいですね.その際, カーネルは以下の設定が有効になっている必要があります.

  • デフォルトコンソール出力
    • CONFIG_SERIAL_8250=y
      • CONFIG_SERIAL_8250_CONSOLE=y
  • 32ビットのイメージを62ビットのホストで動かす
    • CONFIG_IA32_EMULATION=y
  • ディスクイメージで使っているファイルシステム(例: CONFIG_EXT2_FS, CONFIG_EXT4_FS) linux-0.2.imgを使う場合はCONFIG_EXT2_FSを有効にする.
  • virtioデバイス
    • CONFIG_VIRTIO=y
    • CONFIG_VIRTIO_RING=y
    • CONFIG_VIRTIO_PCI=y
  • virtio-blkデバイス(–disk, -dで使う) 疑似仮想化ブロックデバイス向けの仮想ブロックデバイスドライバら しいです.
    • CONFIG_VIRTIO_BLK=y
  • virtio-netデバイス([–network, -n] virtio): 仮想ネットワークドライバ.
    • CONFIG_VIRTIO_NET=y
  • virtio-9pデバイス(–virtio-9p):
    • CONFIG_NET_9P=y
    • CONFIG_NET_9P_VIRTIO=y
    • CONFIG_9P_FS=y
  • virtio-balloonデバイス(–balloon): 動的メモリ割当のためのメモリドライバで,これがあるとゲストに割 り当てるメモリを動的に変更できる.
    • CONFIG_VIRTIO_BALLOON=y
  • virtio-consoleデバイス(–console virtio):
    • CONFIG_VIRTIO_CONSOLE=y
  • virtio-rngデバイス(–rng):
    • CONFIG_HW_RANDOM_VIRTIO=y

カーネルを用意できたら,後は起動するだけです.今回は,linux-kvm内 でビルドしたカーネルを使っています.

$ ./kvm run -k ~/linux-kvm/arch/i386/boot/bzImage -d linux-0.2.img
  # kvm run -k /home/takaishi/linux-kvm/arch/i386/boot/bzImage -m 320 -c 2 --name guest-632

Decompressing Linux... Parsing ELF... done.
Booting the kernel.
[    0.000000] Initializing cgroup subsys cpuset
[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Linux version 3.0.0-rc5+ (takaishi@localhost) (gcc version 4.5.3 (Gentoo 4.5.3-r1 p1.0, pie-0.4.5) ) #3 SMP Wed Dec 7 14:39:03 JST 2011
[    0.000000] BIOS-provided physical RAM map:
[    0.000000]  BIOS-e820: 0000000000000000 - 000000000009fc00 (usable)
[    0.000000]  BIOS-e820: 000000000009fc00 - 00000000000a0000 (reserved)
[    0.000000]  BIOS-e820: 00000000000f0000 - 00000000000fffff (reserved)
[    0.000000]  BIOS-e820: 0000000000100000 - 0000000014000000 (usable)
[    0.000000] bootconsole [earlyser0] enabled
...
[    1.543773] VFS: Mounted root (ext2 filesystem) on device 253:0.
[    1.545773] Freeing unused kernel memory: 432k freed
[    1.548772] Write protecting the kernel text: 6504k
[    1.550772] Write protecting the kernel read-only data: 2184k
[    1.964708] mount used greatest stack depth: 6132 bytes left

Linux version 3.0.0-rc5+ (takaishi@localhost) (gcc version 4.5.3 (Gentoo 4.5.3-r1 p1.0, pie-0.4.5) ) #3 SMP Wed Dec 7 14:39:03 JST 2011

QEMU Linux test distribution (based on Redhat 9)

Type 'exit' to halt the system

sh-2.05b# ls
20thfull.mp2  nbench
sh-2.05b# df
Filesystem           1K-blocks      Used Available Use% Mounted on
rootfs                   19827     17136      1667  92% /
/dev/root                19827     17136      1667  92% /
sh-2.05b# ps
[   20.218915] ps[761]: segfault at b7845000 ip b783e737 sp bf9511a0 error 4 in libproc.so.2.0.11[b7837000+a000]
Segmentation fault

VMを終了するには,kvm stopを使います.その際に,VMの名前を指定す るのですが,これはkvm listで確認することができます.

$ ./kvm list
パスワード:
   PID NAME                 STATE
------------------------------------
632    guest-632            running
$ ./kvm stop -n guest-632

kvm runには他にもオプションがあり,kvm help runで見ることができま す.残念ながら,筆者の環境と能力では全てのオプションの動作確認を することができませんでした.また,動作したオプションについては別 の記事で紹介する予定です.

  • –name: ゲストの名前
  • -c,–cpus: VMに割り当てるCPU数を指定
  • -m,–mem: VMのメモリサイズ.MBで指定する.
  • –shmem: PCIデバイス経由でホストとゲストが共有するメモリを指定
  • -d,–disk: ディスクイメージまたはrootfsディレクトリを指定
  • –balloon: virtio balloonを有効にする
  • –vnc: VMCフレームバッファを有効にする
  • –sdl: SDLフレームバッファを有効にする
  • –rng: virtio Random Number Generatorを有効にする
  • –9p virtio 9pを有効に.ホストとゲストのファイル共有に用いる.
  • –console 使用するコンソールを指定
  • –dev=: KVMのデバイスファイル
  • –tty: ゲストのTTYをホストのptyにリマップする
  • -k,–kernel=: VM用カーネル
  • -r,–initrd=: initrdのイメージを指定する
  • -p,–params: カーネルに与える追加の引数
  • -n,–network: ゲストNICを作成
  • –no-dhcp: rootfs中ではカーネルのDHCPを無効に
  • –vidmode: Video mode
  • –debug: デバッグメッセージを有効に
  • –debug-single-step: シングルステッピングを有効に
  • -debug-ioport: ioportingデバッグを有効に
  • -debug-iodelay: IOのディレイをミリ秒で指定

Debianのイメージを起動してみる

さて,次はDebianを起動してみましょう.まずは,イメージファイルを ダウンロードします.

$ wget http://people.debian.org/~aurel32/qemu/i386/debian_squeeze_i386_standard.qcow2

さて,このイメージファイルをディスクに指定して起動するのですが, カーネルに引数を与えることに注意します.このイメージファイルは, 内部がパーティションで区切られているため,どのパーティションが rootなのかを指定する必要があるのです.カーネルの引数は-pオプショ ンで指定できます.

$ ./kvm run --name test -m 64 -c 1 -k ~/linux-kvm/arch/i386/boot/bzImage -d debian_squeeze_i386_standard.qcow2 -p "root=/dev/vda1"
  Warning: Forcing read-only support for QCOW
  # kvm run -k /home/takaishi/linux-kvm/arch/i386/boot/bzImage -m 64 -c 1 --name test

Decompressing Linux... Parsing ELF... done.
Booting the kernel.
[    0.000000] Initializing cgroup subsys cpuset
[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Linux version 3.0.0-rc5+ (takaishi@localhost) (gcc version 4.5.3 (Gentoo 4.5.3-r1 p1.0, pie-0.4.5) ) #3 SMP Wed Dec 7 14:39:03 JST 2011
[    0.000000] BIOS-provided physical RAM map:
[    0.000000]  BIOS-e820: 0000000000000000 - 000000000009fc00 (usable)
[    0.000000]  BIOS-e820: 000000000009fc00 - 00000000000a0000 (reserved)
[    0.000000]  BIOS-e820: 00000000000f0000 - 00000000000fffff (reserved)
[    0.000000]  BIOS-e820: 0000000000100000 - 0000000004000000 (usable)
[    0.000000] bootconsole [earlyser0] enabled
[    0.000000] Notice: NX (Execute Disable) protection missing in CPU!
[    0.000000] DMI not present or invalid.
[    1.373799] EXT3-fs: barriers not enabled
[    1.375799] kjournald starting.  Commit interval 5 seconds
[    1.377798] EXT3-fs (vda1): mounted filesystem with writeback data mode
[    1.379798] VFS: Mounted root (ext3 filesystem) readonly on device 253:1.
[    1.381798] Freeing unused kernel memory: 432k freed
[    1.383797] Write protecting the kernel text: 6504k
[    1.385797] Write protecting the kernel read-only data: 2184k
SELinux:  Could not open policy file <= /etc/selinux/targeted/policy/policy.26:  No such file or directory
INIT: version 2.88 booting
[    1.606763] stty used greatest stack depth: 5928 bytes left
Using makefile-style concurrent boot in runlevel S.
.udev/ already exists on the static /dev! ... (warning).
Starting the hotplug events dispatcher: udevd.
Synthesizing the initial hotplug events...done.
Waiting for /dev to be fully populated...done.
Setting preliminary keymap...done.
Activating swap...[    2.913563] Adding 731132k swap on /dev/vda5.  Priority:-1 extents:1 across:731132k
done.
Checking root file system...fsck from util-linux-ng 2.17.2
/dev/vda1: clean, 25194/1003680 [    3.030545] EXT3-fs (vda1): using internal journal
files, 261172/4010752 blocks
done.
Cleaning up ifupdown....
Setting up networking....
Loading kernel modules...done.
Activating lvm and md swap...done.
Checking file systems...fsck from util-linux-ng 2.17.2
done.
Mounting local filesystems...done.
Activating swapfile swap...done.
Cleaning up temporary files....
Configuring network interfaces...done.
Starting portmap daemon....
Starting NFS common utilities: statd.
Cleaning up temporary files....
Setting console screen modes.
Skipping font and keymap setup (handled by console-setup).
Setting up console font and keymap...[    4.786277] dhclient-script used greatest stack depth: 5792 bytes left
done.
Setting kernel variables ...done.
[   34.685701] rc used greatest stack depth: 5720 bytes left
INIT: Entering runlevel: 2
Using makefile-style concurrent boot in runlevel 2.
Starting portmap daemon...Already running..
Starting NFS common utilities: statd.
Starting enhanced syslogd: rsyslogd.
Starting ACPI services...RTNETLINK1 answers: No such file or directory
acpid: error talking to the kernel via netlink
.
Starting deferred execution scheduler: atd.
Starting periodic command scheduler: cron.
Starting MTA: exim4.

Debian GNU/Linux 6.0 debian-i386 ttyS0

debian-i386 login: root
Password:
Linux debian-i386 3.0.0-rc5+ #3 SMP Wed Dec 7 14:39:03 JST 2011 i686

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@debian-i386:~# ls /
bin   etc         lib         mnt   root     srv  usr
boot  home        lost+found  opt   sbin     sys  var
dev   initrd.img  media       proc  selinux  tmp  vmlinuz
root@debian-i386:~# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/vda1             15791024    792904  14195972   6% /
tmpfs                    27364         0     27364   0% /lib/init/rw
udev                     10240       148     10092   2% /dev
tmpfs                    27364         0     27364   0% /dev/shm
root@debian-i386:~# ps
  PID TTY          TIME CMD
 1593 ttyS0    00:00:00 login
 1594 ttyS0    00:00:00 bash
 1610 ttyS0    00:00:00 ps
root@debian-i386:~#

起動できました.まだうまくいっていませんが,KVMで作成したディスク 等も起動できそうです.

まだまだ実用的なレベルとは言えませんが,きちんと動いていておもし ろいですね.また,カーネルのデバッグ用途に使えるようなので,こち らについても試したい所です.

tmux内でコマンドを実行する際に新しいウィンドウやウィンドウを分割して実行する

本記事はターミナルマルチプレクサ Advent Calendar 2011 : ATNDの3日 目です.2日目はtmuxのjoin-paneからpaneの指定方法を学ぶ (ターミナ ルマルチプレクサ Advent Calendar 2日目) – kozo2のはてなダイアリー でした. tmuxとzshを使った小ネタです.zsh以外のシェルでも可能だと思います.

  • tmux内でsshを実行すると新しいウィンドウを作成してそこで実行する
  • tmux内でmanを実行するとウィンドウを分割してそこで実行する

~/.zshrcに設定するだけです.

# tmuxの中でsshを実行した場合,新しくウィンドウを作成する
if [ $TERM = screen ]; then
    function ssh_tmux() {
        eval server=\${$#}
        tmux new-window -n $@ "exec ssh $@"
    }
    alias ssh=ssh_tmux
fi


# tmuxの中でmanを実行した場合,新しくペインを作成する
if [ $TERM = screen ]; then
    function man_tmux() {
        eval server=\${$#}
        tmux split-window "exec man $@"
    }
    alias man=man_tmux
fi

tmuxのnew-windowやsplit-windowは,実行した後に引数のコマ ンドを実行することができるので,それを利用しているだけです. ただ,この設定だと,新規ウィンドウや新規ペインでssh・manを実行し たくない時どうすればいいのか分かりません.誰か知っている人がいた ら教えてください.