Author Archives: admin

std::map でキーに文字列のポインタをもつ

キー、値とも文字列の場合、以下のようにやってもうまく動かない。
typedef map<LPCTSTR,LPCTSTR> MYSTRINGMAP;

これはキーの比較をポインタでやるため、文字列として同じであっても、ポインタが違えば違うものとみなしてしまうからだ。

std::stringで以下のようにやってもいいが重くなるのでやりたくない。
typedef map<string,string> MYSTRINGMAP;

そこで比較を文字列自体でやらせるには以下のように定義する。(2017/9/25 const追加)

operator()は左の方が大きければtrueを返さなければならない。

ただし値もポインタだと持ちまわりずらい場合は

でいいと思われる。

udevの話、lfs関連

lfs7.1からまとめ

udevの歴史
元来Linuxはデバイスを静的に作成していた。/dev配下にはたくさんのデバイスがあった。本当にハードが存在しているかは関係なかった。それらはMAKEDEVスクリプトによってつくられていた。スクリプトはデバイスとメイジャー番号マイナー番号をもっており、mknodを呼ぶ。

udevを使うとカーネルが検知したデバイスだけを作成する。システムがブートするたびにつくられる。それらは仮想ファイルシステムdevtmpfsに保存される。

2000年月、devfsと呼ばれるファイルシステムが2.3.46カーネルにマージされ、2.4シリーズのステーブルカーネルで利用できた。この動的デバイス作成方法はカーネルソースに組み込まれていたが、カーネル開発者の十分な支援を受けられなかった。

devfsの問題点はデバイスの検知、作成、名前付けの扱い方にあった。とくに名前付けがまずかった。もし名前が設定可能なら、名前付けポリシーはシステム管理者の仕事にであるべきで、開発者の仕事ではない。devfsはレースコンディション問題もあって本格的に直さなければならなかった。そしてメンテナンスがなくなっていき2006年カーネルから削除された。

2.5カーネルの開発上で、sysfsが来た。sysfsの仕事はハードの情報をユーザスペースに見せることだった。これによりdevfsをユーザスペースに移す見通しが立った。

sysfsはどうやってシステム上のハードを知り、デバイスナンバーを知るのだろうか。カーネルに組み込まれたドライバは自身をsysfsに登録し、カーネルに見つけてもらえる。モジュール化されたドライバの場合、登録はモジュールロード時に行われる。sysfsが/sysにいったんマウントされたら、ユーザスペースからはドライバが登録した情報を見ることができるようになる。そしてudevdが処理を開始し、デバイスノードの調整を行う。

カーネルブート時/etc/rc.d/init.d/udevスクリプトがデバイスノードの作成を行う。このときueventハンドラのデフォルトの/sbin/hotplugを解除する。カーネルはもはや外部バイナリーを呼ぶ必要がないためだ。代わりにudevdがnetlinkソケットをlistenし、カーネルがあげたueventsのめんどうを見ることになる。つぎにスクリプトは/lib/udev/devicesにある静的デバイスを/devにコピーする。いくつかのデバイス、ディレクトリ、シムリンクは動的デバイス制御が始まる前に存在しなければならない。これらはブートの初期段階やudevd自体によって利用される。この方法は動的にデバイスが作成されない場合の簡単な対処方法でもある。スクリプトはそして、udevデーモンudevdを起動する、これはueventsを処理することになる。最後にスクリプトはカーネルにueventsのリプレイさせ、udevdの処理が終わるのを待たせる。

/etc/rc.d/init.d/udev_retryスクリプトはサブシステムのために再トリガされたイベントのめんどうを見る。サブシステムのルールはまだmountfsが走っておらずマウントされていないファイルシステム(/usrや/var)に依存するかもしれない。このスクリプトはmountfs実行後に走り、ルールが再トリガされたとき2度目には成功する。これらは/etc/sysconfig/udev_retryで設定される。このファイルの記述はサブシステムの名前でリトライ時トリガされるものである。(デバイスのサブシステムをしるには、udevadm info –attribute-walkを使う)

Udev-181の時点ではudevdはもはや/devにデバイスを作成しない。代わりにdevtmpfsによるカーネルで扱われる。デバイスノードを登録したいドライバはdevtmpfs経由(ドライバコア経由)することになる。devtmpfsが/devにマウントされたとき、最初はデバイスのノードは固定の名前、パーミション、オーナーで作成される。

すぐ後で、カーネルはudevdにueventを送る。/etc/udev/rules.d, /lib/udev/rules.d, /run/udev/rules.dに書かれたルールに則り、udevdはデバイスノードへのシムリンクを作成し、パーミションやオーナー、グループを調整し、udevdデータベースを修整する。

モジュールとしてコンパイルされたドライバはエリアスをもっている場合がある。modinfoで確認できるが通常はモジュールによってサポートされるbus特定のIDになる。たとえばsnd-fm801ドライバはvendorID 0x1319とdeviceID 0x0801のPCIデバイスをサポートするがエリアスは”pci:v00001319d00000801sv*sd*bc04sc01i*”になる。多くのデバイスにとって、エリアスを提供しているドライバがsysfs経由でデバイスを扱う。たとえば/sys/bus/pci/devices/0000:00:0d.0/modaliasファイルは“pci:v00001319d00000801sv00001319sd00001319bc04sc01i00”という文字列を含むだろう。Udevで提供されるデフォルトルールはudevdにueventの環境変数MODALIASによって、/sbin/modprobeを起動させ、それに適合するモジュールをロードする。MODALIASはsysfsのmodaliasと同内容のはずだ。

USBのMP3プレイヤーなどを差し込んだとき、カーネルはそれを検知しueventを発生させる。前述のとおりudevdによって処理される。

Udevがロードできるのはbus特定エリアスをもち、ドライバがそれをsysfsに登録したものに限る。それ以外の場合は他の方法を使わなければならない。

ドライバがUdevで扱えるかはmodinfoを実行してみることだ。

lubuntuを使ってLFS7.1に挑戦する(最後)

前回からの続き

結局やりなおして、やっと起動できたのでまとめ。
構築的に大変なのはリンカやGCCを移す作業。
まず/mnt/lfs/toolsをつくり、ホストでコンパイルしてここに作る。
つぎにchroot /mnt/lfsして/toolsは見えるようにして、これをつかって/binや/usr/binにつくる。
ダイナミックリンカの設定やspecファイルを更新しながら移していって、最後には/tools/binがなくてもいいようして出来上がりになる。
ここから/toolsをPATHから外して、chrootすることにより、ホストに依存しない環境にはいる。
またGCCなどをコンパイルしたのか?よく覚えていないが、結局ここでカーネルを最後に構築して出来上がりになる。

vmwareでやって最初にはまったのがSCSIだと思う。(本当にそうかはまだ確証はないが)
vmwareはSCSIを推奨してくるのでついついやってしまった。
あとは、なぜかcheckfsが動いて、read-onlyでマウントして動かなくなるので/etc/sysconfig/rc.siteでFASTBOOT=yesにしておいた。

lfsに関係なく難しいのはudev関連だったが、これはもう少ししらべよう。FASTBOOTにしなければならないのはudev関連か起動スクリプトのどこかがおかしいからだと思われる。


画面ではeth0がないが、これはHDDを他のvmに移した直後でeth1になってるからだろう(まだ試していない)。
いずれにしろ最小構成のvmができたのでよしとしよう。

追記。ネットワークはドライバがないからか、カーネルを以下のようにコンフィグしたらeth0が見えるようになった。

bashのキーボードショートカット

行全体を消したいときいつも迷うのでメモ。
bashにはtabによる補完でしられるショートカットがたくさんある。

便利そうなのをメモ
行全体を消すには、CTRL + UK
前に実行したのをまた実行したくて、↑では見つけるには遠い場合はCTRL+R
slと打ってしまった場合は、CTRL+T

その他のやつ

BoostのregexをVC2005expressでつかう

BoostのregexをVC2005expressでつかう。

Windows.hやuser32.libがあってこれらを使ったコンパイルが通ることが前提。

1.47を使う。最新の1.49ではなんかおかしかったのでパスした。

展開したら、コマンドプロンプトを開き。まずVC2005のvcvarsallを実行する。

次に展開したboostの下の、C:\aaa\boost_1_47_0\libs\regex\buildに行く。

nmakeする。

環境変数INCLUDEやLIBが正しく設定されてないとエラーが出るので、以下のような感じで直す。

メイクが成功すると、vc8フォルダに*.libファイルがたくさんできる。
ファイル名の意味は以下のようになる。
先頭に “lib” がついてるのはスタティックライブラリ。大きい
‘s’ はランタイムへのスタティックリンクをしているもの。
‘d’ はデバッグビルドしたもの。
‘g’ はデバッグランタイムでビルドしたもの。
‘mt’ はマルチスレッドだが、これからはこれが標準(以下参照)

以下のコマンドを実行すれば、標準のLIBパスにコピーしようとするがここではやらない。

ここでできた*.libを適当な場所にコピーして、vc2005の「追加のライブラリパス」に追加する。
ただしメイクの際に/MLdを無視しますみたいなwarningが出てたのでシングルスレッドのは意味がないかもしれない。

最初にboostのインクルードを追加する。

これであとは、boostのソースコード(おそらく
config/auto_link.hpp)がコンパイル時に適切なlibを探してリンク(#pragma comment lib)してくれる。

以下はboostのサイトにあったソースコード

ワイド化してもコンパイルできる。

lubuntuを使ってLFS7.1に挑戦する(その7)

前回からの続き

6.63. Stripping Again

デバッグ情報を削除してハードディスクを節約する。
chroot環境から抜けて再び入る。動いてるプログラムがないか確認するため

stripする。
再びchrootから抜けて入りなおす。こんどはtools/bin/bashではなく、/bin/bashで起動する。
この時点で/toolsが必要なくなったので削除してもいい。

リブートしたりして、仮想カーネルファイルシステムがアンマウントされたらまた手動でマウントしないとならない。chrootを抜けただけなのは関係ないはず。

Chapter 7. Setting Up System Bootscripts

一般的な設定やブートスクリプトの設定。initスクリプトはSystemV系でつくる。

7.2. General Network Configuration

ネットワークの設定。NICが一枚しかない場合は設定しなくてもいいらしいが、設定しても問題ないらしい。
まず、udevが同じNICにおなじ名前を割り当てるように設定、

/sysはホストのにマウントされていて、それに対して何かするらしい。

これはNICがひとつしかないからか?よくわからん。

7.2.2. Creating Network Interface Configuration Files

/etc/sysconfigの設定。自分の環境に合わせて書く。

7.2.3. Creating the /etc/resolv.conf File

Googleは8.8.8.8でDNSを公開しているらしい。

/etc/hostsの作成。いくつかのプログラムが利用する。

udevの説明が長くて難しいのでスルー。

7.6. LFS-Bootscripts-20120229

LFSようのブートスクリプトいろいろ

/etc/rc.d/以下にいろいろ入れる

7.7.1. Configuring Sysvinit

/etc/inittabの作成

7.8. Configuring the system hostname

これが/etc/hostsに書かれる。

7.9. Configuring the setclock Script

ハードウェアクロックがUTCかどうか調べる

これがハードウェアクロックの時刻。これに9時間を足して日本の時刻ならUTCになっている。

UTCだったのでUTC=1にする。時刻が合っていたら0にする。ただしこのlubuntuは英語でやってるのでそれによる影響もあるかもしれないがスルー。

7.10. Configuring the Linux Console

キーボードやフォントを設定、化けるといやなのでキーボード以外は英語でやる。UTF-8も今はスルー
というかviが使えるのでcatでやる必要なかった。

Chapter 8. Making the LFS System Bootable

fstabを作って、GRUBもインストールする。
スワップパーティションを作ってなかったので512Mのスワップファイルを作る。

8.3. Linux-3.2.6

以下を選択

Device Drivers —>
Generic Driver Options —>
Maintain a devtmpfs filesystem to mount at /dev

メイクする。

レスキューisoを作るため、xorrisoをインストールする。wgetするのでchroot外の別の端末でやる。

またchroot側へ戻る。

isoを作る。

このファイルをchrootじゃない端末からとって、VMwareの外のホストに移しておく。

grubのデバイスマップを確認

しかしsdbはホストから分離してそれ自体で起動する予定なので、これは意味がないと思われる。いまはsdbだが完成形ではsdaになるだろう。

grubをインストール

なんでパーティションがないんだろう。
mke2fsするときにsdb0と書かずにsdbと書いてしまったからか。どうしよう。今からできるのだろうか。

ここからLFSとは関係ない個人的な復旧作業

VMWareに新たに10Gのハードディスクを追加する。これは/dev/sdcとして見えるはず。
これにパーティションテーブルを作成しプライマリパーティションの1をディスク全体に作る。これはfdiskで行った。
次に/dev/sdbの全内容を/dev/sdc1にコピーする。/dev/sdb自体がパーティションなのでこれでうまくいくかも。

見えたのでホストをシャットダウンして、8Gの/dev/sdbはVMwareから切り離て再起動する。

/dev/sdcが今度は/dev/sdbとして見えるようになった。これで復旧できたはず。
マウントしなおして、chrootしなおす。

ここまでLFSと関係のない話

ここから本番の続き

grubのインストールをする。
# grub-install /dev/sdb
Installation finished. No error reported.
#

これは単独で起動させる予定なのでsdaになるはず

Chapter 9. The End

9.3. Rebooting the System
ついにリブートだか、ここではシャットダウンしてから、あたらしいVMwareゲストをつくり、このゲストは今の/dev/sdbだけをハードディスクに持つようにして起動する。

起動しませんなぁ
いろいろ調べた結果、まずSCSIディスクを使ったのが失敗だった。
SCSIからの起動はinitrdなどのラムディスクが必要でLFSでは取り扱っていなかった。
SCSIからIDEにddしたけどエラーがでたので今回はあきらめてはじめからやることにした。

最後につづく

lubuntuを使ってLFS7.1に挑戦する(その6)

前回からの続き

6.18. Sed-4.2.1

6.19. Bzip2-1.0.6

6.20. Ncurses-5.9

6.21. Util-linux-2.20.1

hwclockは/var/lib/hwclockにあったほうがいいらしい。

6.22. Psmisc-22.15

6.23. E2fsprogs-1.42

6.24. Coreutils-8.15

6.25. Iana-Etc-2.30

6.26. M4-1.4.16

6.27. Bison-2.5

6.28. Procps-3.2.8

6.29. Grep-2.10

6.30. Readline-6.2

6.31. Bash-4.2

入る。

6.32. Libtool-2.4.2

6.33. GDBM-1.10

6.34. Inetutils-1.9.1

6.35. Perl-5.14.2

6.36. Autoconf-2.68

6.37. Automake-1.11.3

checkがすごく時間かかる。エラーなのかも良く分からないし直す気もないのでスルー

6.38. Diffutils-3.2

6.39. Gawk-4.0.0

6.40. Findutils-4.4.2

6.41. Flex-2.5.35

6.42. Gettext-0.18.1.1

checkは時間かかるらいのはもう省略。

6.43. Groff-1.21

珍しいcppのパッケージ

6.44. Xz-5.0.3

6.45. GRUB-1.99

6.46. Gzip-1.4

6.47. IPRoute2-3.2.0

6.48. Kbd-1.15.2

6.49. Kmod-5

6.50. Less-444

6.51. Libpipeline-1.2.0

6.52. Make-3.82

6.53. Man-DB-2.6.1

6.54. Patch-2.6.1

6.55. Shadow-4.1.5

shadowedパスワードを有効にする。
ルートパスワード設定

6.56. Sysklogd-1.5

設定

6.57. Sysvinit-2.88dsf

6.58. Tar-1.26

6.59. Texinfo-4.13a

6.60. Udev-181

LFSようのファイルもインストールする。

6.61.1. Installation of Vim

テストが面白い。

Vimの設定

つづく

lubuntuを使ってLFS7.1に挑戦する(その5)

前回からの続き

6.11.1. Installation of Zlib

6.12. File-5.10

6.13. Binutils-2.22

PTYがちゃんと動いているか確認。このように表示されるはず。

古いstandards.infoをインストールしないようにする。

binutilsのテストは大事

ライブラリヘッダをインストール

6.14. GMP-5.0.4

GMPのテストは重要

ドキュメントをインストール

6.15. MPFR-3.1.0

またもやテストは重要

6.16. MPC-0.9

6.17. GCC-4.6.2

binutilsで作ったlibiberty.aを利用するようにする。

configureする。インストールしたzlibを使うようにする。

テストはすごく重要。
スタックサイズを増やしておく

すごく長いのでVM内でやったほうがいい。

エラーでた。

libmudflapはエラーが出るらしいがGCCのバグらしいのでスルー。

この結果がマニュアルと順番が違う。けどもうスルー

つづく

lubuntuを使ってLFS7.1に挑戦する(その4)

その3からの続き

5.34. Stripping

ここは省略しても言いようだが、ハードディスク節約のためにはやったほうがいいらしい。

デバッグシンボルを取り除く

ドキュメントを削除

5.35. Changing Ownership
ここからはrootでやる。$LFSに値が設定されているか確認すること。

ここでバックアップを取っておくといいらしい。一応VMWareのハードディスクごとコピーしておいた。バックアップを取るならtarしたソースやmakeしたオブジェクトは要らないと思うが、それは作業ディレクトリにあるという想定なのだろうか、いずれにしてもvmwareなので小さくするのは面倒なのでスルー。

Part III. Building the LFS System
ここから本格的なLFSシステムの構築が始まる。chrootでミニリナックスに入り、パッケージのインストールを行う。

6.2. Preparing Virtual Kernel File Systems
ある種のファイルはカーネル自身が通信するために使う。これらは実際のファイルではなくメモリ上に存在する。それらを作成する。

6.2.1. Creating Initial Device Nodes
カーネルがブートするときいくつかのデバイスノードを必要とする。consoleやnullデバイス。udevdが始まる前にこれらは存在しないとならない。

c はキャラクターデバイスをあらわす。キャラクターデバイスとはシークできないもの。キーボードや乱数がある。その後の番号はそのデバイスの種類を決めたものでカーネル作成者が決めている。詳しくは/usr/src/linux/Documentation/devices.txtにある。

–bindを使ってホストの/devを再マウントする。

6.4. Entering the Chroot Environment

これで$LFSがルートディレクトリになった。これからは$LFSは必要ない。
I have no name!と表示されるのは/etc/passwdがないからだそうだ。

ここから先はすべてここでの環境になる。ホストをリブートしたりしたときはまた、/devなどを作り直さないとならない。

標準的なディレクトリをつくる。

シンボリックリンクなどを作成

パスワードファイルとグループファイルを作成

udevなどのためにいろいろなグループがあるらしい。

“I have no name!”を変える。Glibcはインストールされ、/etc/passwd, /etc/groupはできたのでできるはず。

login, agetty, initがログをとるようにファイルを作る。ファイルがないとログをとらないらしい。

/var/run/utmpは現在ログインしているユーザの記録。/var/log/wtmpはすべてのログインログアウトの記録。/var/log/lastlogはユーザごとの最後のログインの記録。/var/log/btmpはbad loginの記録。

6.7. Linux-3.2.6 API Headers

なんか/bin/shがないとか言われたのでシンボリックリンクをつくって再トライ。

6.8. Man-pages-3.35

6.9. Glibc-2.14.1
現在のコンパイラのスペックは/toolsを指していて、これだとtestスクリプトが失敗する。コンパイラのスペックはGlibcができるまでは直せないので、このテストスクリプトをいじる。

コンフィグする。こんどは/usrになる。

ここでのGlibのテストは重要。
いつくかのテストが失敗しないようにコピーをとってやる。

とくにエラーはないみたいなので先に進む。

NISとRPC関連のヘッダをインストール

最小限のロカールをインストール。

EUCJPになってるので全部のロカールをインストール

Glibcのために/etc/nsswitch.confをつくる。

タイムゾーン設定

–remove-destinationをつけるのはシンボリックリンクだった場合に削除するため。
このファイルはシングルユーザモードのためにコピーしておくらしい

6.9.3. Configuring the Dynamic Loader

ダイナミックローダがライブラリを探すディレクトリの設定

もっと探せるようにする。

6.10. Re-adjusting the Toolchain

Cライブラリがインストールされたので、ツールチェインの調整をする。これにより新しくコンパイルされるプログラムは、新しいライブラリを見るようになる。

前のをとっておく。

gccのスペックファイルを編集して、あたらしいダイナミックリンカを指すようにする。

本当にできているか確認。

このように表示されるはず。

このように表示されるはず。

このように表示されるはず。

このように表示されるはず。

このように表示されるはず。

このように表示されるはず。


続く