NetBSDが全てのexecutableをdynamic linkに 51
ストーリー by wakatono
ダイナミックリンクの正しい使い方 部門より
ダイナミックリンクの正しい使い方 部門より
brake-handle曰く、"Luke Mewburnがnetbsd-current-usersに流したmailによると、NetBSD-currentは一両日中に/binや/sbin以下を含めた全ての実行可能ファイルをdynamic linkにするそうだ。これにともない、/binや/sbin向けのshared objectが/libへ移動する、static link版のexecutableを/rescue以下に用意するなどの変化が生じる。
全てのexecutableをdynamic linkにする最大の効用はファイルサイズの節約。Luke Mewburnが測定した結果によると、/binおよび/sbinのサイズが15.9MBから9.2MBに減少、約4割減となった(1.6_BETA3/i386)。容量の厳しいFDやflash cardなどでは助かることだろう。
Solarisでも/binが実は/usr/binでdynamic linkだったなんてことはあったが、/sbinまでやってしまうとは。恐れ入りました。"
いまさら容量節約なんて…と思う人もいるかもしれないが、PDA等大きな記憶領域を持てないデバイスにとって切実な問題だ。そういうデバイスでもっとBSDを…という人には朗報かな。
sbinの意味が (スコア:3, 参考になる)
なんてことは既に議論されているんでしょうねぇ?
Re:sbinの意味が (スコア:2, すばらしい洞察)
FreeBSDで/usr/sbin見たらdynamically linkedなバイナリが満載。かと思えば/usr/binにもstatic linkedなバイナリは存在します。さらに言えば、/binや/sbinはほとんどがstatic linkedです。ってことで、リンク方式で言えば、
static : /{bin,sbin}
dynamic: /usr/{bin,sbin}
と分かれていて、それぞれの中に入ってるコマンドの傾向としては
一般用途 : /bin /usr/bin
システム管理用途 : /sbin /usr/sbin
に分かれているんだと今まで思っていました。この認識を改めないといけないでしょうか?
Re:sbinの意味が (スコア:1, おもしろおかしい)
#恥さらしなのでACで
Re:sbinの意味が (スコア:0)
知るは一瞬の恥。知らぬは一生の恥。
ということでー。
勉強になります。φ(.. )メモメモ
Re:sbinの意味が (スコア:1)
Re:sbinの意味が (スコア:0)
「一時の恥」なー。
Re:sbinの意味が (スコア:0)
SunOS のアレは気持ち悪いでそ。
Re:sbinの意味が (スコア:0)
static link binaryは必然、それ単体で動くために
スーパユーザが実行するものが多く、結果system binary
とかsuperuser binaryとか思ってしまった、ってことかし
らん?
ライブラリの更新時にもメリット? (スコア:3, 参考になる)
普通は /bin や /sbin が static link だろうが dynamic link だろうが、 /usr/lib に入っているライブラリを更新したときには全体を make し直すものかもしれませんが。
鵜呑みにしてみる?
Re:ライブラリの更新時にもメリット? (スコア:1)
多くのソフトウェアで使われているライブラリに障害が見つかった場合、
稼働中のシステムでは全部 make し直すというのは
かなり厳しい作業でしょうから、そういった意味でも
dynamic link になるのはいいことですよね。
ただ、今度はライブラリの下位互換性の問題が生まれるのでしょうが……
.NET Framework では、共有アセンブリのバージョン管理に工夫をしているようで
サイドバイサイド実行 [microsoft.com]なんていうものもできるそうなのですが、
Unix の .so はどうなっているのでしょう。
よく、
/usr/local/lib/libVFlib2.so -> libVFlib2.so.24.0.1*
/usr/local/lib/libVFlib2.so.24 -> libVFlib2.so.24.0.1*
/usr/local/lib/libVFlib2.so.24.0.1*
のようになっているので、うまくやれば下位互換性に
悩まされずに共有ライブラリを使えそうだなぁ、とは思うのですが
実際の所はどうなのでしょう。
バージョン番号に関する共通のコンベンションってあるんでしょうか。
elf shared objectの場合 (スコア:3, 参考になる)
とりあえず、現在最もよく用いられているelfの場合。
elfの場合、shared objectにはversion numberという概念はありません(確かa.outではld.soの動作に意味を持つversion numberが存在した)。その代りに、major version number(executable作成時とruntimeで一致していなければならない)をheaderに埋め込むことによってversion controlを実現しています。
major version numberは、dynamic sectionのSONAMEに保存されます。gnu binutilsの場合、objdump(1)で確認できます。
silver% objdump -x /usr/lib/libc.so.5 | head -n 20
(snip)
Dynamic Section:
SONAME libc.so.5
.NETのやり方は、fileではなくsymbolにversion controlを入れようという考え方です。Unixのlinkerにもweak symbol(weakでない同名のsymbolがあった場合、weakでないものを優先する)がありますが、これをより複雑にしたものです。並列開発などでは効くのかも知れませんが、runtime linkerの仕事が非常に重くなりそうなのでprocessをたて続けに起動するような場合にはつらいかも知れません。
Re:elf shared objectの場合 (スコア:1)
.NETも、unixみたいに、「processを」たて続けに起動する
なんて使い方をするんだろうか?とか、一瞬思ってしまいました。
やっぱり、目指す(べき)ところは、「立ち上げっぱなし」および
「動かすかどうか、と、Loadされているかどうか、の独立」っすよね…
Re:elf shared objectの場合 (スコア:0, 余計なもの)
最近はprocessを使うのもずいぶん楽になりました。risc-based workstationを使い慣れていない人は全く知らないと思いますが(私もついこの前初めて知った)、実はaddress spaceの切り換えというのはprocessorの工夫によってある程度安く済むようになっています。典型はSPARC V9上のSolaris 2で、kernel address spaceにprocess address spaceを全くmapしません。もともとはkernel address spaceを増やす事が目的でしたが、system callのた
Re:elf shared objectの場合 (スコア:0)
IntelとUltraSPARCのaddress space (スコア:2, 参考になる)
virtual address spaceが使えるprocessorには、virtual address spaceの各pageをphysical memoryのpageに変換する(対応するphysical pageが存在しないこともある)表を持っています。この表は通常memory上にあるのですが、実際にはそれをaddress参照の度に読んでいるとprocessorの実行がmemory busの帯域にboundしてしまいます。そこで、通常は表の一部をcacheに持っておきます。これがTLB(Translation Lookaside Buffer)です。
Intelのprocessorでは、一度に1つの変換表しか使うことができません。また、TLBはvirtual address spaceを切り換えた時に全て無効化されてしまいます。これはTLB miss(注目しているvirtual addressがTLBに見つからない場合のcache miss)を増加させる原因になります。UltraSPARC IおよびIIではaddress space identifier(実体は8bitの数値)によってaddress spaceに名前をつけ、address space全体を切り換えることなく複数のaddress spaceを使い分けることが可能です。TLBがそのまま使えるので、kernel address spaceからuser process address spaceへのデータ転送などで不必要なTLB missを防ぐことができます。
Re:IntelとUltraSPARCのaddress space (スコア:1)
Intelだとaddress変換表のcacheがムダになってしまうことが多いが、SPARCはその心配がないというぐらいの意味です。実際、TLBに入っている情報というのは変換表の一部をコピーしたものなので。
補足ですが、TLBは変換表のコピーに過ぎないので、TLB missが生じたらtrapを発生してOSにTLBの補充を行わせるという考え方もあります。MIPSやUltraSPARCのようにriscの血を引き継いでいるprocessorではどちらかというとこの発想が普通です。
Re:elf shared objectの場合 (スコア:0)
実際 glibc が使ってます。元ネタは Solaris 。
振り向くとそこにはプロストではなくて Solaris がいるのが UNIX の世界。
Re:elf shared objectの場合 (スコア:1)
元仕事場のSolaris 7で調べてみました。mapfileの中にsymbolのversionが書けるようですね。
...しかし、gnu libtoolが対応するまでは存在に気づかない人が多いのでは?
Re:elf shared objectの場合 (スコア:0)
とっくに対応していますが何か?
Re:elf shared objectの場合 (スコア:1)
gnu binutilsやlibtoolなど、objectを扱うものの場合「とっくに対応している」という論法は通用しません。というのは、各種Unixごとに採用しているbinutilsなどのversionが異なる(主にkernel buildの際、address spaceを正しく作る必要がある)ため、いまだに古いものを使わざるを得ない場合もあるのです。
Re:ライブラリの更新時にもメリット? (スコア:0)
これが NetBSD の a.out 実装でも踏襲されていたんですが、
ELF の採用に伴って退化しました。
Re:ライブラリの更新時にもメリット? (スコア:1, 参考になる)
そのものは a.out のときのものを踏襲しています。つまり、
- メジャーバージョンが違うものは全くバイナリ互換性がない
- メジャーバージョンが同じ場合、マイナーバージョンが
大きなものほど新しく、新しいものは古いものに対して
後方互換性をもっている
- libc のメジャーバージョンを変更するのは禁忌 :D
という感じです。
i386でも恩恵あり (スコア:2, 参考になる)
少し補足すると、最近私用で可動部分を一切用いない、1UのハイトでハーフサイズのPC/AT機を見せてもらいました。Linuxが載っていてflash ATAでbootするのですが、どう頑張っても256MBの壁があるためやはり/binや/sbinは厳しいそうです(機能拡張のためにHDDを載せるオプションもあるそうで)。
多くのarchitectureでflash ATAが使えるようになったという背景もあるでしょうが、i386などに絞り込んでみても太ったbashやashの問題が片づくと思わぬ使い方が出てきそうで楽しみです。
Re:i386でも恩恵あり (スコア:0)
容量がきびしい環境では crunched binary にすれば? という気がするんだが…
それはさておき、/ と /usr を別パーティションにする習慣が一部にあるためにライブラリの置き場が /usr/lib と /lib の2箇所になってしまうのがなんかいやん。
別パーティションにする習慣が一部にある (スコア:3, 興味深い)
ものだと思いました。
BSDの歴史において、/と/usrを別にするのは伝統であり、
暗黙の了解事項だと思って今まで生きてきました。
PDPあたりのディスクの制限であったり、シングルユーザモード
で走行するための最小環境であるために、歴史的に/は小さく
作られてきたのだと思います。
また、ディスクレスWSなるものが導入された時、/は個々のWS
固有のデータを、/usrは共有可能な領域でリードオンリーとされた
こともありました。
バックアップ時は、/はシステムの一時ファイルを保持したり、
システム設定ファイルが編集修正されるため、バックアップ頻度
を多くし、/usrは新ソフトを追加しない限り変更はないものとし、
頻度を下げることが出来る領域だとも思っていました。
僕は今もそう思って、多くのサーバを今でも管理しています。
ひとによって環境は違うのでしょうが、僕にはちょっと驚きの表現
でした。
Re:別パーティションにする習慣が一部にある (スコア:1)
むしろ/が小さすぎて、システムアップグレード時に溢れちゃったりすると悲しかったり(/kernel.oldと/modules.oldを削除してなんとかなりましたが)。
FreeBSDあたりはAを押せばお任せでパーティションを切ってくれるのでそのまま使ってますが、linux系のシステムはそういうのが無いので、/とswapだけ作ってインストール、なんてこともよくやります。
はじめて使うシステムなどですと、どこがどれだけ食うか把握できないので、この方が安全なこともあったりしますね。debianをはじめていれた時、FreeBSDしか知らなかったもので、/varに30Mしか割り振らずに悲しい思いをしました。debianは/varを酷使しますね。今では1Gあっても足りないと思ってます^^;;
Re:別パーティションにする習慣が一部にある (スコア:0)
/tmpはmfsするもんだし。
#ちなみにNetBSDはcronで /var/backupにcvsで/etcの各種設定ファイルを保存してくれる。便利。
なもんで/に一時ファイルとか言われるとなんか気持ち悪い。
Re:別パーティションにする習慣が一部にある (スコア:1)
使い方によっては、/varだけでなく/var/spoolや/var/mailも別にしてしまうこともありますね。/var/spool以下はinodeを大量に使う可能性がありますし(mailやnewsをため込む場合)、/var/mailはファイルサイズが太る恐れがあります。
うちの場合、/var/spoolで何度かinodeが足りなくなったため、現在はinode数を4倍に増やしたfilesystemを使っています。
Re:別パーティションにする習慣が一部にある (スコア:0)
/var が別パーティションゆーんは当然。
まあ同じアーキテクチャの同じ OS の同じバージョンのマシンを何台も管理してれば / と /usr をわけるとちょっとは楽なんでしょうけど。その程度のことでしょ? / で変更されやすいのは /etc ぐらいだろうし、/bin /sbin の更新頻度と /usr/bin /usr/sbin の更新頻度が違
Re:別パーティションにする習慣が一部にある (スコア:1)
/etcを/と別パーティションにしても問題ないもんでしょうか?
#fstabのある/etcが別だと、mountするために見に行く先が
#mount後まで見えない、なんてまぬけな話になりそうな気が・・・。
#・・・間違ってますかね(汗)?
---- redbrick
Re:別パーティションにする習慣が一部にある (スコア:0)
Re:別パーティションにする習慣が一部にある (スコア:0)
その他は /etc マウント前の /etc に
/etc/fstab, /etc/passwd, 他が最小限あればどうにかなるかな。
NetBSD あたりなら mount_union でいけそう?
Re:別パーティションにする習慣が一部にある (スコア:0)
#自分でrcをぐちゃぐちゃと弄り回すってのは黒魔術だよな。
/を別にするのは/etcを(単体で別にすることはできないから/ごと)別にして/usrを(同一アーキテクチャで)共通にしたいからですよね。
#/usr/shareも(異アーキテクチャで)共通にしたいな。
こういう人は「/varが別パーティションとゆーんは当然」です。
でも「変更さ
Re:別パーティションにする習慣が一部にある (スコア:0)
/別にしたいのはマシンごとにカーネルを別にしたいからっていう理由も考えられますね。
Re:i386でも恩恵あり (スコア:1)
boot fdとかだと、crunchかつ{g,b}zipしても1.44MBに収まるかどうかという厳しい条件になることもあります(そのたびに何を削るかでもめる)。こういう場合は/libが別建てになると助かります。
もしPC/ATが早い段階で素直にOpenBootを使っていて、どんな計算機でも気軽にnetbootできる状況ならばSolarisよろしくいきなり/、/var、/usrをmountできて一番楽なんだけどなぁ...(恨めしい)
省メモリも可能か? (スコア:1)
crunchで残る問題として、crunched binary全体をaddress spaceにmapしなければならないことがあります。crunchが大きくなれば必要なpage数も増えます。中には実際には実行されないにもかかわらずmapされてしまうpageもあるでしょう。
こんな時にshared objectが使えれば、実行しないtext、読まないdataには一切pageを使う必要がありません。pmapを初めとするvm metadataを切り詰めた状態でも動くものができる可能性があります。
Re:i386でも恩恵あり (スコア:0)
Re:i386でも恩恵あり (スコア:0)
Re:i386でも恩恵あり (スコア:0)
Re:i386でも恩恵あり (スコア:1, すばらしい洞察)
Dynamic linkのメリット (スコア:2, 参考になる)
dlopen()を呼べるようにする、というのが目的かと。
今のままではPAMやlocaleのサポートに無理があります。
デメリットとしては、遅くなることと、なんとなくイヤ (笑) と
いうのがあります。前者は遅いプラットフォームを多数抱える
NetBSDではかなり辛いものがあります。
ちなみにld.soやlibc.soが壊れたときのために、/rescue/*に
いちぶ実行ファイルがcrunched binaryとして用意されます。
Re:Dynamic linkのメリット (スコア:0)
というのもあります。/ パーティションを太らせないためには
/lib をクリーンアップする必要があるので、開発者には
ちょっとだけ負担がかかります。
# cron で古いライブラリを /usr へ移動させればいいだけだが。
サイズ減少幅が違うと思います (スコア:2, 参考になる)
急すぎ? (スコア:0)
# とはいえ結論を覚えていない:)
現在のcurrent-usersのメールは当時の蒸し返しと理解の足りない一部の人による感情論とであり、読む必要はありません。
誤読 (スコア:1)
Only Jav^Hpanese available :-)
/rescue の容量が増えるのでは? (スコア:0)
どうせ、static版のバイナリを /rescue に置くぐらいなら
そのまま今まで通り /sbin に static版のものを
置いておけば良いような?
Re:/rescue の容量が増えるのでは? (スコア:1, 参考になる)
動的にロードする nsswitch モジュールを提供しようとした
時に、dynamic でないと困ります。
Re:/rescue の容量が増えるのでは? (スコア:0)
# 最初のタレコミで 先入観を植え付けられてしまった。
Re:/rescue の容量が増えるのでは? (スコア:0)
そうなんですな。
lukem のアナウンスもこのタレコミも容量削減が目的のように読めてしまうけど、ほんとは dlopen() を使えるようにするのが目的なわけで。current-users がヒートしたのも、lukem のアナウンスでの説明不足が原因じゃないかな。
Re:/rescue の容量が増えるのでは? (スコア:0)