「Binary Hacks Rebooted」読んだ

Amazonアフィへのリンク

約17年前に発売された「Binary Hacks」の名前を冠する続編本。一般的に「低レイヤー」と呼ばれることの多い、コンピュータソフトウェアの中でも特にOSやCPUに近い部分の技術を、章ごとに1つずつ紹介するという内容になっている。

「Binary Hacks」はそれなりに反響のあった本だったため、その名前を冠するだけで、それ相応に注目を集めることになる。本を読んだ限りでは、名前に恥じることのない程度には濃い内容に仕上がっている。まぁ逆に、こんな内容の濃い本を好き好んで読もうと思うような人がいったいどれだけいるのかというあたりにも疑問を持つ。20年ほど前と比べると、今やこの日本でこういった内容のソフトウェア技術を必要とする仕事やらは本当に減ってしまったなというのが個人的な印象だ。

低レイヤーは技術の進化が早いわけではないとはいえ、20年近くも時代が進むとそれ相応に変わっていくわけで、その内容を雑多的に情報として知れるというのは実際のとこ個人的には非常にありがたい。書籍として出版されることが減ってきているという時代に、しかも需要がどんどん減ってる日本語での技術情報提供でというあたり、儲かりもしないのにこれだけのレベルでまとめ上げてくれた各位には本当に感謝したい。

著者らは「*年後にさらにこの本の続編が出ることを期待して」のような記載を残している。これこそ、こういう領域に熱意を持って力を注ぎこむような人が今後も続くのかどうか、もっと言えば、こんな領域のソフトウェア技術開発を未来の時代に行っているほど日本(なのか日本語なのか)がグローバルに競争力を維持できているのかどうか、という話なのかなと思う。

前作と比べるとページ数が約1.5倍になっている。改めて前作を斜め読みするに、あまり細かく丁寧に説明するような文章にはなっていなくて、それに対し本作は文章をかなり丁寧に書いている事が多いので、その分がページ数の差なのかなと感じた。600ページ超えとなるともはや大型本よね。「サクッと読む」には少々重いというのが若干残念なところか。

というわけで、低レイヤー技術を対象に日本語で書かれた非常にレアな本で、その領域に片足を突っ込んでる人は迷わず買っておけというところ。逆に、低レイヤーに興味がない人には全くささらないと思う。

下記は本の内容で気になったところをメモがてらに。

HACK#6 共有ライブラリの検索の実例
P39「AT_SECUREタグを持つエントリが含まれていた場合」
今まではsuなどのときにLD_LIBRARY_PATHが無効になる条件がわからなかったけど、補助ベクトルが効いていることを知れてよかった。
過去の記事のどこかに「わからない」と自分で書いた記憶があるんだけど、探しても見つからなかったので、訂正ができない。。

HACK#10 TLSのしくみを理解する
P58「TLSアクセスモデル」
gdbでattachしている最中にThread Local Storageな変数へアクセスする方法がいつもわからずに苦労していた。このあたりの記載を頼りに調査すれば、今どきのgdbからのアクセス方法を確立できそう。

HACK#17 LIEFを使ってELFバイナリを書き換える
P92あたり
まさに最近はシンボルの書き換えがクソめんどいから、こういう専用のツールがあることを知れてよかった。ただPython製というのはどうなんだろ。特にクロス環境にて、いずれにしてもlibelfに依存することを考えれば、Pythonに追加対応させるためのツール整備も最近なら大した事ない?

HACK#38 cgroupでプロセスのリソースを管理する
P248 「IOCOST」
I/O Schedulerで制御することしか知らなかった私からすると、こんな他の手段もあるんだなぁと知れてよかった。けど、本書での紹介っぷりからすると、必ずしも思い通りにI/O量を制御できるわけではなさげ?I/O Schedulerでも制御が難しいし、やっぱりI/O制御は難しいという話なのか?

HACK#43 /proc/PID/rootからコンテナ内のファイルに直接アクセスする
docker内のファイルへ外から簡単にアクセスする方法、ずっとこれのやり方が知りたかった。わからなかったので、わざわざdocker cp使って毎回中から外へ大量のコピーをしてしまっていた。

HACK#49 ftraceを使ってカーネル内で起こっていることをトレースする
P341あたり、
KernelShark trace-cmd、あたりは過去に使ってみたことはあるんだけど、これ、目的を定めて使わないと逆に迷走するなと感じた。GUIで可視化すると一部のエライ幹部に受けが良くて、かえって性能改善活動のジャマになって(以下略

セキュリティの大章は全般的にツールを使った力技的な話が多くて「HACKしている」感があまりしないと感じた。数値表現の大章はいわゆる数値計算の分野だというイメージが強くて「まぁ知らなくてもいいかな」と読み飛ばし気味になってしまった。

● いきなり結論
dtorは可能な限り noexcept を明示的につける。

● 参考サイト
非自明なデフォルトのデストラクタは暗黙にnoexcept
https://faithandbrave.hateblo.jp/entry/20120322/1332399681
C++ の noexcept specifier のちょっとややこしい仕様
https://zenn.dev/mafafa/articles/a8ae1e546f7634

● 仕様の要点だけを抽出
- 派生クラスのdtorが例外を出すなら、dtorは暗黙にnoexcept(false)である
- 基底クラスのdtorがvirtualかつ例外を出すなら、dtorは暗黙にnoexcept(false)である
- = deleteと定義したら、dtorのnoexceptは翻訳対象から外れ考慮外になる
- 上記に当てはまらなかったら暗黙にnoexcept(true)である
上記のルールにより、declareとdefineとでnoexcept(true|false)が入れ替わるということが起こり得る

● ハマった点
Effective Modern C++ 項目22: Pimpl イディオムを用いる際は特殊メンバ関数を定義する
のルールに則ると、
- a.hpp に class A で virtual ~A(); とdeclare する
- a.cpp に class A で A::~A() = default; と define する
という具合になると思う。
が、このように書くと、バカマジメに仕様を解釈しようとするやつ(某静的解析ツール)は、
- declare と define とで noexcept のprototypeが異なるかもしれない
みたいなことを言い出す。
回避するためには、基本的に noexcept(true) であると明示した方が良いとなる。
- a.hpp に class A で virtual ~A() noexcept; とdeclare する
- a.cpp に class A で A::~A() noexcept = default; と define する

● 所感
C++マジ闇。。マリカしょ。。

Linux memo 2024/05/23 録画サーバ編

● 概要
「Mirakurun + EPGStationで録画サーバを作ってみた」みたいな記事はもはやそこら中に溢れてるし、手順通りやると構築するだけなら難しくないので、ここではそういうのに書かれてなさそうな点を中心にメモしておく。

● パソコン
TRIGKEY G4 N95にした(Amazonアフィ)
ライセンスの怪しいWindowsは使わない、技適が怪しいBluetooth/WiFiは使わない。
以前にも書いたけど、BIOSで「Advacnced→Power→GT→RC6」を「Enable」にするとGPU消費電力を抑えやすい。あとは、PL1/PL2制限をキツめにし、Ethernetを100Base-TXに制限し、不要なUSBは接続しない(キーボード・マウス)、不必要なHDMIを接続しない、systemctlでbluetoothdを止める、/sys/devices/system/cpu/cpufreq/policy0以下で「energy_performance_preference = balance_power」「scaling_governor = powersave」「scaling_max_freq = 1500000」とかしておけば、idle時で5W前後にはなるはず。WiFiドライバやBluetoothドライバをrmmodしても特に変化は見られなかった。

● チューナ
PLEX PX-W3U4(Amazonアフィ)
px4_drv.git(@nns779)という非公式ドライバがあるが、メンテが止まっちゃっているので、forkしたこっち(@tsukumijima)のほうがいいかもしれない。Ubuntu-24.04LTSで試すと、UBSANのオーバラン誤検出でdmesgが汚れて困ったので、パッチ(0001-change-usage-for-variable-array.txt)作った。が、同じようなパッチを作った人がすでにいた(px4_drv_chrdev20240521.patch)

● ICカードリーダ
SCR3310/v2.0(Amazonアフィ)
可能なら、ICカードリーダはPX-W3U4に内蔵のを使ってみたかったが、Windowsで実際に動かしてUSBバスのダンプを取って...みたいなリバースエンジニアリングする気力までは出なかった。

● Mirakurun(チューナサーバ)
docker拾い食いに抵抗がないなら、docker-mirakurun-epgstation.gitが楽だと思う。recpt1を自分でコンパイルして準備し、tuners.ymlとchannels.ymlを整える必要はあるが、逆にそれだけ行えばもう動いてしまう。後述するが、私はEPGStationは自前で立てることにしたので、docker-compose.ymlでそのへんをごまかした。

● EPGStation(録画視聴サーバ)
Ubuntu-24.04LTSのaptで取れるffmpegでも、vaapiとIntelプロプラドライバを整えれば、QSVによるハードウェアエンコードができるということがわかったので、Ubuntuホストのffmpegを使うためにも、EPGStationはdocker板ではなくて自分で立てることにした。とはいえ公式のレポジトリから持ってきて手順通り動かすだけだけど。ffmpegをvaapiのh264で動かすために、config.ymlenc.jsを変更した。QSVを使うとN95の1.5GHzでもh264エンコードは余裕だった。まぁソフトエンコでも-threads対応だから200-300%くらいでリアルタイムでも回るんだけど。改めてN95/N100シリーズってすげぇ。

● サスペンド
いくら省電力とはいえ、何もやっていないときにも動かしっぱなしにするのはなにかもったいない。ということで、スケジュールをチェックしてサスペンドするsuspendd.plのPerlスクリプトを書いた。次の録画予約、3日に1回EPGデータ巡回、重要なプログラム(sshログイン・Sambaアクセス中・recpt1使用中)、をチェックして空いていたらサスペンドする(rtcwake -m mem -s 3600)ようにしてみた。注意点として、EPGStationは公式にはサスペンドをサポートしていないので、起き上がってきたらresettimer(curl -X POST "http://127.0.0.1:8888/api/recording/resettimer")をしてタイマーのイベントドリブンを再スケジュールする必要がある。しなかったらタイマーイベントがずれて録画予約に失敗する。

● その他
マジメに使い倒すならばデータ置き場をHDDにしたりもいいんだけど、まぁ遊びだから、たぶんこのくらいまでにとどめておくことになるんじゃないかなと思う。暇があれば、生のMPEG2-TSからパケットパースしてschedule EITやpf EITをひろってきて番組表を自力で作る、なんてのもいいのかもしれない。

Amazonアフィリンク

鉄道業界が社会や地域へ貢献できなくなっている具体例を示して問題点を指摘する本。地方赤字路線の廃止を主題にしつつも、鉄道存続そのもののみを議論しても意味がなく、交通を介し地域や自治体が自身を今後どのように運営するべきかを考えないといけない、と説いている点が特徴となる。

趣味のジャンルで活動する人が多い鉄道系YouTuberの分野で、社会問題の観点で語るYouTubeチャネルを運営する鐵坊主氏の著作。元旅行代理の経歴から鉄道を切り口に地域や自治体のあり方を考える動画をカナダから投稿する、というなかなか類のない活動を行っている。自治体や会議体の公表する資料を読み解きながらていねいに根拠を積み上げて議論する、という点も著者の強みとなっている。

鉄道事業は固定費が重く、また関東ですら今後人口減を迎えるため、それを踏まえ各社は長期計画を立てて運営していたが、それが新型コロナの登場で短期計画がすべて吹っ飛ぶほどの赤字になり経営が揺れ動いた。このため、各社により温度差はあるものの、どこも人口減を見据えた長期計画を前倒しで始めざるを得なくなった。これが、特にJRで、地方の赤字鉄道路線を維持するのはこれ以上はムリだとして廃線に向けて議論を加速したい動きになっている。方や地元自治体は、従来通りの廃線反対な声を上げるだけの例が未だに多い。議論を単に先延ばしにするだけではダメで、人口減の速度と社会情勢を踏まえた地域交通のあり方を真剣に考えなければいけない、と著者は説いている。

私も素人ながら地域や都市機能と交通とのあり方をおぼろげながら考えることがあったけど、著者のYouTubeチャネルを見始めてから、かなりマジメに考えるようになった。特に、ここ25年ほどは一貫して、(新幹線を除き)鉄道路線の整備よりも高速道路網の整備が優先され続けてきていて、それにより、高速バスがJRの特急に勝つ方面が増えた、という点をきちんと理解できていなかったと反省している。是非はともかく、JR分割民営化により、大都市部と新幹線以外はもう諦めて手を抜くんだという国交省の方針の成れの果てが今なんだと思い知らされた。これでは、未だに「国鉄」の認識と変わらない主張をするような自治体とは議論がかみ合わないわけで。

新聞や銀行と並び、もはや斜陽だと言われることもある鉄道業界の現状を知るうえでの良本。特に、鉄道を主人公に語るのではなくて、自治体や社会のあり方に踏み込んで考えている点がよい。逆に、現在の議論が停滞している状況を一変させるアイディアを語っているわけではない点には、現実的になかなかいい案があるわけではないとはいえ、仕方がないのかもしれない。

Linux memo 2024/05/13 tty share編

● 前置き
画面を動画形式で他の人へ共有するとどうしても遅延に悩まされる。
terminal上での操作を共有したいという場合ならば tty の出力をそのまま共有すればいいのではないか、というアイディアが出てくる。

● 同一ホストで共有する場合
ほぼ下記の記事ですべて語られているけど、
tty script コマンドでLinuxサーバ作業を他者に共有
https://qiita.com/kikudai/items/66ff7155623d635d10c2

- 配信したい人のマシンをA、ターミナルをa、
- 視聴したい人のマシンをB、ターミナルをb、
として、bで閲覧するためのterminalを実行し、ttyコマンドを実行して、その結果「/dev/pts/22」などをメモる。
これを配信者に伝え、aの上で、
- script -fq /dev/pts22
を実行し、aの上でそのまま作業すればよい。終わったら、aでexitする
(bash終了と同時にscriptも終了)
(注意:scriptという名前のコマンドがありそれを使っている)
下記のような記事もあるけど、straceは明らかに過剰で負荷が高いと思われる。
ターミナル画面を勝手に共有して他人の作業を覗いてみる
https://qiita.com/nashiox/items/f9b026b7433fcf984d45

● 同一ホスト別ユーザの場合
難しいことは考えずに、先と同じ方法で同一ユーザでttyをつないだあとに、suなどすればよいと思う。

● 異なるホストの場合
まず、aの別ターミナルとなるa2を開いて下記を実行する。
- mkfifo /tmp/testsharetty
- cat /tmp/testsharetty | nc -l 10333
次に、bで下記を実行する
- nc -N 192.168.123.45 10333
最後に、aで下記を実行する
- script -fq /tmp/testsharetty
mkfifoとnc(netcat)を介することで、TCPごしに相手に見せれる。
serverとclientは入れ替えできると思う。
グローバルに公開していい?認証?それは知らん。。

● 複数人宛に同時に配信したい場合
上の方法で、mkfifoしたunix domain sockerから1回readするごとに、
TCP socket serverにつなぎに来た人全員に1回ずつwriteする、
ということを行うサーバプログラムを作れば良い。
...うん、ちょっとがんばれば作れそうだね(あとは誰か頼む

● あとで再生したい場合
"script"コマンドで取得したログは、in/outのタイミングが記録されておらず、これをterminalに食わせても超高速で流れていくだけとなる。
なので、下記の記事で紹介されている ttyrec ttycast を使うのが素直かと思う。
ターミナル操作をウェブで配信する
https://qiita.com/ohtaman/items/775b3831754336c75208

● その他
帯域が狭い・だけど遅延は減らしたい、みたいな場合は、ssh -C でsshセッション越しが楽だと思う。

Linux memo 2024/03/20 自宅サーバ編

Beelink MINI-S12 Pro(Amazonアフィ)

● 経緯
自宅サーバ用のマシンとして使っていたIntel NUC DN2820FYK(過去の記事)が急に不調になり、どうもハード的に怪しいので、これを機に、少し前に買ったけどほとんど使っていなかったBeelink MINI S12 Proを代わりに当てがることにした。
実はこのIntel NUCマシン壊れるのは2度目で、1度目の2021年3月頃はちょうど近くに全く同じ型番のガワが中古で売られてたので購入しSSDだけ移植してやり過ごしていた。果たして今回は?

● ソフトの設定変更
Beelink MINI S12 Proは、2.5インチの空きベイもあるので、前のマシンで使っていた2.5インチSSDをセットして試しに電源入れてみたらなんとそのまま動いた。Linuxのデーモン類も全部問題なし。EthernetだけがUUID違いで弾かれたので再設定、とはいえ /etc/sysconfig/network-scripts/ の ifcfg-enp1s0 を参考に新しくはえたeth向けにコピーし直した程度。Linuxもgeneric kernelが当たり前になったためか、何も設定しなくても動いてしまい、時代の変化を感じる。
Beelinkといえば、技適とかWindowsのライセンスがとかでグレーと言うかアウトだけど、ライセンスはLinuxにするので問題なし、技適はBluetooth/WiFi使わないので問題ないということにする。Bluetoothは、lsusbによれば、AX201がUSBに生えてきてhci0が作られていたが、down状態なので、このままとする。WiFiは、lspciによれば、AX101D2WがPCIeにつながっているが、dmesgによるとiwlwifiが合致するfirmwareがないとかメッセージを出して動いていないようだったので、このままとする。

● Beelink S12 Proの設定
BIOS更新も一切出さないようなメーカなので、あまりBIOSを変更するのもどうかと思ったけど、下記を変更した。
次の2点はどちらもBeelink MINI S12 Pro N100ベンチマークと改造 - nabeの雑記帳より。
>Advacnced→Power→GT→RC6 Enable。これがオフだとアイドル8W。(アイドル時の消費電力が6W。)
>Chipset→PCH-IO Configuration→State After G3→S0 Stateを設定すると自動電源オンになります。
あと、PL1 PL2を5000(mW)にして消費電力(発熱)を抑えておく。
VT-dやらASPM L0sL1やらRC6やらを触ったけど、実測する限りはほとんど消費電力は変わらなかった。(Linuxでコンソールしか使ってないというのもあると思う)

● ethtoolのautonegの話
2021年1月ごろにTwitterで、autoneg off duplex fullだと問題がある、というような趣旨のつぶやきをした。今回改めて確認してみるに、どうも、autoneg offにするとAutoMDI/MDI-Xも無効になってしまうのが原因かなと思い、
ethtool -s enp1s0 autoneg off mdix on speed 100 duplex full
を試してみたけどこれもダメだった。ただ、
ethtool -s enp1s0 autoneg on speed 100 duplex full
だと問題なかった。これだと、autoneg on でも Advertised link modeが100baseT/Fullになるので、1000Base-Tではなくて100Base-TXでリンクしてくれるようになる。今でもリンクアップアイドルで200-300mWくらいは変わるみたいなので、動かしっぱなしの負荷の低いマシンだと多少は意味があるかもと思う。(相手のハブ側も同様に電力食うだろうし)
いずれにしても、1000Base-Tが当たり前になった現代では autoneg on 固定のままのほうがよいと思っていたほうが良さそう。

2024/05/13追記
Beelink S12 Proではなくて類似スペックの別マシン(TRIGKEY GREEN G4 N95)でのテストだけど、
WiFiやBluetoothはドライバを無効にしてもいまいち消費電力には影響せず、
どちらかというと bluetoothd を止めるのが手っ取り早い(hci0にちょっかいを出さない)模様。
300mWくらい減った。
systemctl stop bluetoothd
systemctl disable bluetoothd
とかをやってみよう。

Linux memo 2023/12/30 glibc errno

Pofixではerrnoはthread safeとされていて、Linux(というかglibc)もthread safeだが、世の中にはそうでないシステムもあるらしく、そのせいでerrnoを使おうとすると「thread safeかどうか確認しろ」と無慈悲な指摘をするヘンテコな解析システムがあり、そいつを分からせてやるために無駄な調査を行うハメになった。

glibcのこのへんを見ると良い。
/csu/errno.c
/csu/errno-loc.c
/stdlib/errno.h

glibcがthread localに対応したのは下記かららしい。裏付けできなかったがおそらくこのタイミングでerrnoも対応したと思われる。
glibc-2.3 (2002-10-02) thread local
https://sourceware.org/legacy-ml/libc-alpha/2002-10/msg00048.html

Linuxがいわゆる昔のLinuxThreadsからネイティブスレッド(NPTL)に変更されたのはLinux-2.6.0からで、Linux-2.6.0は 18 December, 2003 にリリースされている。
https://kernelnewbies.org/LinuxVersions

errnoをgdb上から確認するために__errno_location()を直接呼ぶ方法も参考に。

アイテム

月別 アーカイブ

ウェブページ

Powered by Movable Type 7.9.0