<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>That's Done!</title><link href="https://thatsdone.github.io/junkbox/" rel="alternate"></link><link href="https://thatsdone.github.io/junkbox/feeds/all.atom.xml" rel="self"></link><id>https://thatsdone.github.io/junkbox/</id><updated>2026-05-06T15:45:00+09:00</updated><subtitle>thatsdone's (mostly technical) memorandum</subtitle><entry><title>[en] Linux virtio_can driver</title><link href="https://thatsdone.github.io/junkbox/linux_virtio_can.html" rel="alternate"></link><published>2026-05-06T15:45:00+09:00</published><updated>2026-05-06T15:45:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2026-05-06:/junkbox/linux_virtio_can.html</id><summary type="html">&lt;p&gt;Linux virtio_can driver&lt;/p&gt;</summary><content type="html">&lt;p&gt;I'm working on AGL (Automotive Grade Linux), and now there is a collaboratieve efffort to
establish a reference platform for SDV on top of AGL, so called SoDeV.&lt;/p&gt;
&lt;p&gt;You can find information regarding AGL SoDeV below.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.linuxfoundation.org/press/agl_sodev"&gt;SoDeV announcement from the AGL/Linux Foundation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/automotive-grade-linux/sodev-demo-workspace"&gt;AGL Team Workspace&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;You can find working code of SoDeV integration there.&lt;/li&gt;
&lt;li&gt;The main target is &lt;a href="https://www.renesas.com/en/support/partners/r-car-consortium/r-car-consortium-proactive-partner-list/rtx-sparrow-hawk"&gt;Renesas R-Car V4H Sparrow Hawk SBC&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=2mudbDBmffU"&gt;Accelerating Software-Defined Vehicles: SDV-EG Updates &amp;amp; New AGL SDV Reference&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;A great talk given by Jerry Jiancong Zhao from Panasonic Automotive Systems at the ALS 2025.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SoDeV uses Xen Hypervisor and &lt;a href="https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=virtio"&gt;virtio&lt;/a&gt; mechanism for inter domain communication.&lt;/p&gt;
&lt;p&gt;So far, I was using guest operating system side virtio frontend driver by OpenSynergy team for AGL (based on Yocto 5.x/Scarthgap until 21.0(Unagi release)). Linux kernel version is 6.6.x for Scarthgap.
Recently, I noticed that virtio_can driver build fails for Yocto 6.x which is(/would be) based on
linux 6.12.x.&lt;/p&gt;
&lt;p&gt;After looking into the error logs that I got, I figured out that this comes from a small interface
change of a virtio subsystem utility method, &lt;code&gt;virtio_find_vqs()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can find the patch below, and I hope this makes sense for the community. :)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/thatsdone/junkbox/blob/master/linux/virtio-can-v5.patch"&gt;The original patch (v5) by OpenSynergy team&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lkml.org/lkml/2024/1/8/375"&gt;LKML post&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/thatsdone/junkbox/blob/master/linux/virtio-can-v5.1.patch"&gt;My port of virtio_can(v5) to 6.12.x&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;My work is just porting the Opensynergy teams' great work to Linux kernel 6.18.x. I truely honor OpenSynergy teams' work! License is GPL2 of course.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</content><category term="tech"></category></entry><entry><title>[ja] Cat's Eye Nebulaにまつわる研究進展</title><link href="https://thatsdone.github.io/junkbox/cats_eye_nebula.html" rel="alternate"></link><published>2026-03-08T15:15:00+09:00</published><updated>2026-03-08T15:15:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2026-03-08:/junkbox/cats_eye_nebula.html</id><summary type="html">&lt;p&gt;Cat's Eye星雲にまつわる研究進展&lt;/p&gt;</summary><content type="html">&lt;p&gt;この&lt;a href="https://www.msn.com/ja-jp/news/future/%E3%83%8F%E3%83%83%E3%83%96%E3%83%AB%E3%81%A8%E3%83%A6%E3%83%BC%E3%82%AF%E3%83%AA%E3%83%83%E3%83%89%E3%81%8C%E8%A6%B3%E6%B8%AC%E3%81%97%E3%81%9F-%E3%82%AD%E3%83%A3%E3%83%83%E3%83%84%E3%82%A2%E3%82%A4%E6%98%9F%E9%9B%B2-%E3%81%AE%E3%82%AF%E3%83%AD%E3%83%BC%E3%82%BA%E3%82%A2%E3%83%83%E3%83%97-%E3%83%AF%E3%82%A4%E3%83%89%E3%83%93%E3%83%A5%E3%83%BC/ar-AA1XAusS?ocid=msedgntp&amp;amp;pc=LCTS&amp;amp;cvid=69acab0a15e04ba5bb431c08fe8bb7cf&amp;amp;ei=16"&gt;MSNの記事&lt;/a&gt;が目について、ちょっとぐぐってみて、へー…と思ったのでメモ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://ja.wikipedia.org/wiki/%E3%82%AD%E3%83%A3%E3%83%83%E3%83%84%E3%82%A2%E3%82%A4%E6%98%9F%E9%9B%B2"&gt;キャッツアイ星雲&lt;/a&gt;、
画像自体は昔からよく知られていて、学生の頃にも見た記憶があった。
しかし星雲とはいえ、恒星の爆発に伴って形成された構造で、複雑に絡み合ったガスの構造が
どう形成されたのかは長らく研究対象だったとのこと。&lt;/p&gt;
&lt;p&gt;記事によると、2022頃、当時高校生のRyan Clairmontさんが着想を得てプロに相談して本格的な
研究を実行。高密度ガスのリング構造があることを明らかにして論文にしたとのこと。&lt;/p&gt;
&lt;p&gt;この業績でRyanさんはISEF(International Science and Engineering Fair)の
物理学・天文学部門で1位を獲得。現在はスタンフォードで学生をしている模様。&lt;/p&gt;
&lt;p&gt;論文はたぶんこれ
"&lt;a href="https://academic.oup.com/mnras/article/516/2/2711/6696946"&gt;Morphokinematic modelling of the point-symmetric Cat’s Eye, NGC 6543: Ring-like remnants of a precessing jet&lt;/a&gt;"&lt;/p&gt;
&lt;p&gt;出た当時に&lt;a href="https://sorae.info/astronomy/20221110-ngc-6543.html"&gt;Soraeでも話題になっていた&lt;/a&gt;模様。&lt;/p&gt;
&lt;p&gt;MSNで話題になったのは、最近 Hubble (JWSTではなく)と&lt;a href="https://euclid.caltech.edu/"&gt;Euclid&lt;/a&gt;を使って&lt;a href="https://www.scientificamerican.com/article/nasa-unveils-dazzling-new-images-of-the-cats-eye-nebula/"&gt;非常に精細な画像＋周囲の画像が得られた&lt;/a&gt;
のが発端らしい。&lt;/p&gt;
&lt;p&gt;いやー、自然科学っていいですね :)&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[ja] libvirt notes</title><link href="https://thatsdone.github.io/junkbox/libvirt_notes.html" rel="alternate"></link><published>2026-01-03T13:00:00+09:00</published><updated>2026-01-03T13:00:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2026-01-03:/junkbox/libvirt_notes.html</id><summary type="html">&lt;p&gt;libvirt関連(特にvirt-install)のメモ&lt;/p&gt;</summary><content type="html">&lt;h2&gt;話の発端と何が書いてあるか&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://thatsdone.github.io/junkbox/generic_qemu_notes.html"&gt;Generic qemu qemu notes&lt;/a&gt;でvirtio-canの話を書きましたが、qemu-system-ARCHを直叩きするのではなく、libvirtを使い、かつあまり一般的ではないdeviceを使いたいという話です。&lt;/p&gt;
&lt;p&gt;/usr/bin 以下のシステム標準品を入れ替えてしまってもよいのですが、切り替えて使えるようにしたい場合、
またlibvirt標準でサポートされていないdeviceを使いたい場合、
VM(というかlibvirt用語ではdomain)を定義するにはどうするか？&lt;/p&gt;
&lt;h2&gt;2通りのやりかた&lt;/h2&gt;
&lt;p&gt;ざっくり、以下の2通りのやりかたがあります。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;標準品libvirtでdomain定義した後、virsh edit や virt-xml で書き換える&lt;/li&gt;
&lt;li&gt;virt-installのオプションでがんばる&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;1.はちょっとうざいので2.の方法を模索していました。なんとか最低限やりたいことはできたのでまとめておきます。&lt;/p&gt;
&lt;h2&gt;emulatorの変更&lt;/h2&gt;
&lt;p&gt;上記の記事に書いたように、qemuのmainlineにマージされていないデバイスを使いたいことがあります。
この場合、システム標準の qemu-system-aarch64 や qemu-system-x86_64 とは違うバイナリを使うことになります。&lt;/p&gt;
&lt;p&gt;AIサーチだと、virt-install に &lt;code&gt;--emulator&lt;/code&gt; というオプションがあるよと出てきたのですが、
手元の virt-install だと使えなかったので(or ハルシネーション？)、もう少し調べたところ virt-install の
&lt;code&gt;--boot&lt;/code&gt; オプションに &lt;code&gt;emulator=XXXX&lt;/code&gt; と書けることがわかり、フルパスで指定しました。&lt;/p&gt;
&lt;p&gt;なお、libvirtdのサーチパスを変更する…といった手法でもイケるようです。&lt;/p&gt;
&lt;h2&gt;標準的ではないdeviceを使う&lt;/h2&gt;
&lt;p&gt;qemuレベルだと、CAN device自体については&lt;a href="https://www.qemu.org/docs/master/system/devices/can.html"&gt;公式にマニュアル&lt;/a&gt;があるように、qemu側の仮想deviceについては &lt;code&gt;-object&lt;/code&gt; で定義した上で、対応するqemu側のdriverを指定すればよいです。&lt;/p&gt;
&lt;p&gt;qemu mainlineに入っている KVASER というCANのデバイスを、ホスト側のcan0に接続するには、qemu-system0-XXXに以下のように指定すればよいことがわかります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;-object can-bus,id=canbus0
-device kvaser_pci,canbus=canbus0
-object can-host-socketcan,id=canhost0,if=can0,canbus=canbus0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;これをlibvirtのdomain定義するのは現状無理な模様です。&lt;/p&gt;
&lt;p&gt;ではどうするか？なのですが、libvirtのdomain定義に qemu-system-XXX の command line パラメータを
指定することができるので、これを使いました。&lt;/p&gt;
&lt;p&gt;virt-install の場合は &lt;code&gt;--qemu-commandline&lt;/code&gt; というパラメータに渡します。&lt;/p&gt;
&lt;h2&gt;PCI IDが衝突することがある&lt;/h2&gt;
&lt;p&gt;当初、&lt;code&gt;virt-install&lt;/code&gt; に以下のようなオプションを付けて試行したのですが、virt-instaellはPCI bridgeをたくさん接続してくれる関係で、IDぶつかってエラーになってしまいました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nv"&gt;qemu&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;commandline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-object can-bus,id=canbus2 -device virtio-can-pci,canbus=canbus2 -object can-host-socketcan,id=canhost2,if=vcan2,canbus=canbus2&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;じゃあどうするか？なのですが、&lt;code&gt;virtio-can-pci&lt;/code&gt; の場合は &lt;code&gt;addr&lt;/code&gt; というパラメータがあり、PCIの function IDを指定できることがわかり、lspciの結果とてらしあわせて空きIDを指定することで回避できました。&lt;/p&gt;
&lt;p&gt;私の環境の場合はBus 0の 06 まで埋まっていたので、07.0を使いました。以下の通りです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;qemu&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;commandline&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-object can-bus,id=canbus2 -device virtio-can-pci,canbus=canbus2,addr=07.00 -object can-host-socketcan,id=canhost2,if=vcan2,canbus=canbus2&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;なお、Bus 0は PCI Bridgeなので避けたいと思ったのですが、上記を &lt;code&gt;07:00.0&lt;/code&gt; と書いたところこれもエラー。
(空きのBus IDとdevice IDが両方7なので紛らわしいですね)
そこで、同じく virtio-can-pci で使えることになっている &lt;code&gt;busnr&lt;/code&gt; が使えるかなと思ったのですが、
指定してみたところ「writableではない」という趣旨のエラーが出てしまいました。
コードは未調査ですが、最低限やりたいことはできたのでここまででヨシとすることにしました。&lt;/p&gt;
&lt;p&gt;なお、qemuのdriverごとのoptionは以下で調べられるようです。
以下のvirtio-can-pciを目的のdriverに置き換えてください。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;qemu-system-aarch64&lt;span class="w"&gt; &lt;/span&gt;-device&lt;span class="w"&gt; &lt;/span&gt;virtio-can-pci,help
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;また、組み込まれているdriverの一覧は以下で見られます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;qemu-system-aarch64&lt;span class="w"&gt; &lt;/span&gt;-device&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;気づき(未解決)&lt;/h2&gt;
&lt;p&gt;virt-install の場合、VMを定義するとpower onまでしてくれるのですが、emulatorの変更と &lt;code&gt;--qemu-commandline&lt;/code&gt; の指定を入れたところ、power onしてくれなくなりました。&lt;code&gt;virsh start DOMAIN_NAME&lt;/code&gt;(等)すればよいのですが、
いったん置いてあります。    &lt;/p&gt;
&lt;p&gt;続くかもしれません。&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[ja] Generic qemu notes</title><link href="https://thatsdone.github.io/junkbox/generic_qemu_notes.html" rel="alternate"></link><published>2025-12-07T21:40:00+09:00</published><updated>2025-12-07T21:40:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2025-12-07:/junkbox/generic_qemu_notes.html</id><summary type="html">&lt;p&gt;qemu一般のメモ&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://thatsdone.github.io/junkbox/zephyr_qemu_notes.html"&gt;Zephyr qemu notes&lt;/a&gt;でZephyrでのqemu系targetの話を書きましたが、qemu側の話。&lt;/p&gt;
&lt;h2&gt;virtio-can関連&lt;/h2&gt;
&lt;p&gt;最近ポストしている記事でCANの話が多くあるように、仕事でCANを使っています。
都合でハイパーバイザ上でvirtioベースでCANのトラフィックを流したいという事情があってあれこれ試したメモ。&lt;/p&gt;
&lt;h3&gt;qemu virtio-can backend&lt;/h3&gt;
&lt;p&gt;単純に考えると qemu の仮想デバイスとして作ってやることになります。
OpenSynergyが公開していて、以下が最新だと思われます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/OpenSynergy/qemu/tree/virtio-can-spec-rfc-v3"&gt;https://github.com/OpenSynergy/qemu/tree/virtio-can-spec-rfc-v3&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;上記は公開が2023/4で、ビルドはすなおに通りますが、残念ながらqemuのベースは6.0.1になります。&lt;/p&gt;
&lt;p&gt;なので、qemuのmasterに使えるかなと思ってportしてみたものが以下です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/thatsdone/qemu/tree/virtio-can-port]"&gt;https://github.com/thatsdone/qemu/tree/virtio-can-port&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;'25/12時点で、多少のずれはありますがそのまま適用でき、ビルドもすんなり通りました。&lt;/p&gt;
&lt;p&gt;いずれも公式の既存のCANデバイスのページ&lt;/p&gt;
&lt;p&gt;&lt;a href="[https://www.qemu.org/docs/master/system/devices/can.html]"&gt;https://www.qemu.org/docs/master/system/devices/can.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;の記述を参考に、以下のようにqemu-system-xxxにパラメータを渡してやると
virtio-can deviceを有効化できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;can&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;bus&lt;/span&gt;,&lt;span class="nv"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;canbus0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;virtio&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;can&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;pci&lt;/span&gt;,&lt;span class="nv"&gt;canbus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;canbus0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;can&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;host&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;socketcan&lt;/span&gt;,&lt;span class="nv"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;canhost0&lt;/span&gt;,&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;vcan0&lt;/span&gt;,&lt;span class="nv"&gt;canbus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;canbus0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;上記の例は、ホスト側で vcan を使って vcan0 というデバイスがあるものとし、
これにゲスト側のvirtio-can deviceを接続する指定です。&lt;/p&gt;
&lt;h3&gt;Yet Another virtio-can backend&lt;/h3&gt;
&lt;p&gt;別解としてvhost-deviceを使う方法があります。&lt;/p&gt;
&lt;p&gt;このへんにありますが、まだ試せていません。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;https://crates.io/crates/vhost-device-can&lt;/li&gt;
&lt;li&gt;https://github.com/rust-vmm/vhost-device/tree/main/vhost-device-can&lt;/li&gt;
&lt;/ul&gt;</content><category term="tech"></category></entry><entry><title>[ja] 中国旅行時のTIPS('25/11版)</title><link href="https://thatsdone.github.io/junkbox/china_travel_tips_202511.html" rel="alternate"></link><published>2025-11-15T16:30:00+09:00</published><updated>2025-11-15T16:30:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2025-11-15:/junkbox/china_travel_tips_202511.html</id><summary type="html">&lt;p&gt;中国旅行時のTIPS('25/11版)&lt;/p&gt;</summary><content type="html">&lt;p&gt;最近、中国に出張する機会があり、いろいろ気づきがあったのでメモ。&lt;/p&gt;
&lt;h2&gt;ネット接続&lt;/h2&gt;
&lt;p&gt;中国国内からは、Google等のよく使うサービスが使えません。やりかたは各種あって、ざっくりローミングすればいいのですが、
今回はティーガイア(T-Gaia)という会社の&lt;a href="https://voyageesim.com/"&gt;VOYAGEE eSIM&lt;/a&gt;からeSIMを購入しました。&lt;/p&gt;
&lt;p&gt;現地ではChina Mobileの(たぶん、香港子会社の？)回線で、香港経由のローミングになるため、GoogleやFacebook等、普通にアクセスできました。&lt;/p&gt;
&lt;p&gt;使い勝手は普通の海外用eSIMとほとんどかわりませんが、１点、ローミング中に「データサービスに接続する」設定にする必要があります。&lt;/p&gt;
&lt;h2&gt;決済/支払い&lt;/h2&gt;
&lt;p&gt;今回は現金を使う機会が一度もありませんでした。&lt;/p&gt;
&lt;p&gt;クレジットカードすら使えないことも多いので、AliPayまたはWeChat Payは必須です。&lt;/p&gt;
&lt;p&gt;私はAliPayを使いましたが、以下、いくつか気づきを箇条書きでまとめておきます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;日本国内でもAliPay使えるマークが出ているところは多くありますが、あれは中国からの旅行者専用です。日本のクレジットカードを使ってAliPayのアカウントを作ってあっても、中国でしか使えません。&lt;/li&gt;
&lt;li&gt;AliPayのアカウントを作るとき、本人確認のため、携帯の電話番号だけではなく、パスポートの情報を入力(スキャンでもOK)する必要があります。この際、パスポートの写真と照合のため自撮りするステップがあるので面食らわないようにしましょう。&lt;/li&gt;
&lt;li&gt;中国国内ではデビットカード的に銀行口座に紐づけるのがスタンダードなようですが、外国人はクレジットカードを紐づけられます。決済の使い勝手としては、少額の買い物でも都度クレジットカードで決済する感覚になります。&lt;/li&gt;
&lt;li&gt;クレジットカード情報を登録する時、支払用のパスワード(数字6桁)を作成します。現地で買い物をするたびに必要になるので、ちゃんと覚えておきましょう。&lt;/li&gt;
&lt;li&gt;AliPayの中から、Uber相当のDidi等、各種の別サービスを呼び出して使えるようになっています。「ミニアプリ」と呼ばれています。今回は Didi を使いましたが、別項目で。&lt;/li&gt;
&lt;li&gt;アプリはAndroid版の場合で、日本語を含めて多数の言語が使えます。ただし、日本語は翻訳が微妙なので私は英語で使いました。&lt;ul&gt;
&lt;li&gt;ホーム画面 -&amp;gt; 右下のAccount -&amp;gt; 右上のねじマークアイコン -&amp;gt; General と画面遷移すると言語設定するところがでてきます。&lt;/li&gt;
&lt;li&gt;なお、AliPayから呼び出す「ミニアプリ」については多言語対応状況はモノによります。(後述)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;買い物をするときは以下のどちらかになります。&lt;ol&gt;
&lt;li&gt;「支払い/受け取り(Pay/Receive)」のボタンから自分のQRコードを出して、お店の端末でスキャンする&lt;/li&gt;
&lt;li&gt;「スキャン(Scan)」ボタンから提示されたQRコードをスキャンする&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;タクシー/ライドシェア&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Uberは駆逐され(?)、Didiがデファクトのようです。&lt;/li&gt;
&lt;li&gt;AliPayを入れると、前述の通りAliPayの「ミニアプリ」としてDidiが連携して使えるようになっています。言語設定については、少なくともAliPayのミニアプリの場合は、中国語２種(簡体字と繁体字)以外は英語だけでした。Didi専用のアプリだと違うのかもしれません。(未確認)&lt;/li&gt;
&lt;li&gt;Didiの(ミニ)アプリの使い勝手は、Uberとほぼ同じです。Uberを使ったことのある人であれば悩まずに直観的に使えると思います。&lt;/li&gt;
&lt;li&gt;AliPayのミニアプリの場合だけかもしれませんが、アプリからあがってくるポップアップが中国語のまま翻訳されていないケースがあるようです。私が見たのは、配車を確定する際に、「車両内の安全確認のためにカメラで(動画)撮影するが承諾するか？」という質問が中国語のままでした。(中国出身の同行者がいたので安心して承諾できましたが、怖いところです)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;高速鉄道&lt;/h2&gt;
&lt;p&gt;今回は上海から南京に移動する必要があり、高速鉄道(＝日本で言う新幹線)を使いました。とても便利かつ、乗り心地もよかったです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;全席指定席のため、チケットを予約＆事前購入する必要があります。&lt;/li&gt;
&lt;li&gt;AliPayの"TripAir-Train"からも予約・購入ができます。...が、今回使ったeSIMの回線のせいか、動きがとても遅かったので、Webから&lt;a href="https://trip.com/"&gt;trip.com&lt;/a&gt;を使いました。こちらは普通にクレジットカードが使えます。なお、後述の通り、予約・購入時にパスポート情報を入力する必要があります。&lt;/li&gt;
&lt;li&gt;trip.comはスマホアプリもあって、Webからの予約情報と一体運用でき、現地で列車番号や座席、チケット番号を移動中に確認できるので便利です。&lt;/li&gt;
&lt;li&gt;高速鉄道の改札では、紙のチケットは必要ありません。中国現地の人たちは、日本のマイナカード相当のカードで、外国人はパスポートをスキャンして本人確認＆予約照合が行われます。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;地下鉄とかバスとか&lt;/h2&gt;
&lt;p&gt;...は、今回は結局乗らなかったのでわかりません。
ただ、一般的な買い物のように券売機でQRコードスキャンで行けるのではないかと思われます。&lt;/p&gt;
&lt;h2&gt;カジュアルな食事&lt;/h2&gt;
&lt;p&gt;おいしいものが食べられる、カジュアルが食堂がたくさんあります。&lt;/p&gt;
&lt;p&gt;支払いはAliPayかWeChat Payのみというところがけっこうあります。&lt;/p&gt;
&lt;p&gt;ここまでは前述の通りですが、'25/11時点、電子化がまだ進行中らしく、
メニューの類を置いておらず、QRコードからWebサイトにアクセスして、オーダー＆即時決済が必用というところがけっこうあります。ここで問題は、そのWebサイトが英語にすら対応していないこともけっこうあり、現時点では外国人にあまりやさしくない状況になってしまっているようです。&lt;/p&gt;
&lt;p&gt;これは、例えばカフェの luckin coffee とかでも事情は同じようでした...
が、マクドナルド等は最低限英語だけは対応していました。(が、支払はクレジットカードも受け付けていませんでした...orz)&lt;/p&gt;
&lt;h2&gt;モバイルバッテリー&lt;/h2&gt;
&lt;p&gt;飛行機に持ち込めるモバイルバッテリーには、容量制限があるのはよく知られていると思います。&lt;/p&gt;
&lt;p&gt;今回、同行者がひっかかったのですが、少なくとも国内線に乗る場合、中国のCCC認証を通ったモバイルバッテリーである必要があるようです。例えばAnkerのような中国製のモバイルバッテリーでも、日本で買える輸出モデルだとCCC認証を取得していないケースもあるので要注意とのこと。&lt;/p&gt;
&lt;p&gt;続く..かもしれません。&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[ja] Zephyr qemu notes</title><link href="https://thatsdone.github.io/junkbox/zephyr_qemu_notes.html" rel="alternate"></link><published>2025-11-05T20:25:00+09:00</published><updated>2025-11-05T20:25:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2025-11-05:/junkbox/zephyr_qemu_notes.html</id><summary type="html">&lt;p&gt;Zephyrのqemu固有のメモ&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://thatsdone.github.io/junkbox/zephyr_esp32_notes.html"&gt;Zephyr ESP32 notes&lt;/a&gt;を書いたので、次はqemuのメモをダンプしていきます。&lt;/p&gt;
&lt;p&gt;対象は以下の2つです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;qemu-system-x86_64&lt;/li&gt;
&lt;li&gt;qemu-system-aarch64&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;...が、そのうち増えるかもしれません(笑)&lt;/p&gt;
&lt;h2&gt;話の発端&lt;/h2&gt;
&lt;p&gt;まず、私は数年前から単純にCPUを使いまくるテスト用(というか教育用?)のプログラム(mpmt)を作っています。&lt;/p&gt;
&lt;p&gt;ここにおいてあります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/thatsdone/mpmt"&gt;https://github.com/thatsdone/mpmt&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;取り扱う言語が30を超えたくらいからネタ切れ感がでてきていたのと、
&lt;a href="https://www.automotivelinux.org/"&gt;AGL&lt;/a&gt;に絡みはじめてから
同じLinux Foundation配下のRTOSにZephyrをAGLのSDV Reference PFで使おうよという話、
つまり
&lt;a href="https://lf-automotivelinux.atlassian.net/wiki/x/A4BGFQ"&gt;SoDeV&lt;/a&gt;
プロジェクトに首をつっこみはじめてから、
当時者としてZephyrに興味を持つようになりました。&lt;/p&gt;
&lt;p&gt;それで、言語やそのランタイムだけではなく、RTOSでもmpmtを動かしてみるか…と思い至ったというのが発端です。&lt;/p&gt;
&lt;p&gt;mpmtのZephyr版は
&lt;a href="https://github.com/thatsdone/mpmt/tree/main/zephyr"&gt;このあたり&lt;/a&gt;
を見てみてください。&lt;/p&gt;
&lt;p&gt;さて、以下気づきのメモを列挙していきますが。他の記事と同様に随時更新していきます。&lt;/p&gt;
&lt;h2&gt;ターゲット...というかボード指定？のやりかた&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;west build&lt;/code&gt; する際に &lt;code&gt;-b&lt;/code&gt; に何を指定するか？という話です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;x86_64の場合&lt;ul&gt;
&lt;li&gt;qemu_x86_64&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ARM64の場合&lt;ul&gt;
&lt;li&gt;qemu_kvm_arm64&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下、マニュアル。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;x86/x86_64 qemu target board&lt;ul&gt;
&lt;li&gt;https://docs.zephyrproject.org/latest/boards/qemu/x86/doc/index.html&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ARM64 qemu target board&lt;ul&gt;
&lt;li&gt;https://docs.zephyrproject.org/latest/boards/qemu/kvm_arm64/doc/index.html&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;できあがるバイナリ&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;west build -t run&lt;/code&gt; ではなく、qemu-system-xxx から直接実行したい…とか、libvirtで制御できるようにしたいという場合には気にする必要があります。&lt;/p&gt;
&lt;h3&gt;x86_64の場合&lt;/h3&gt;
&lt;p&gt;x86_64の場合、buildディレクトリの中にバイナリが2つできあがります。&lt;/p&gt;
&lt;p&gt;一方はZephyrのメインプログラムでもう一方はloaderになります。
mpmtのZephyr版のREADMEに書いておきましたがこういう感じです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;kernel: zephyr-qemu-locore.elf&lt;/li&gt;
&lt;li&gt;loader: zephyr-qemu-main.elf&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;aarch64の場合&lt;/h3&gt;
&lt;p&gt;こちらは一般的な組み込み用のボードと同じで1つだけです。
buildディレクトリの中にzephyr.binができあがります。&lt;/p&gt;
&lt;h2&gt;KVMの仮想化支援機能を使いたい&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;west&lt;/code&gt; からqemuに指定のパラメータを渡す方法があるのかもしれませんが、現状は未調査です。
ただ、qemu-system-x86_64等から直接起動する場合は普通に使えます。&lt;/p&gt;
&lt;h2&gt;Zephyrのqemu_x86_64 boardでvirtioを使いたい&lt;/h2&gt;
&lt;p&gt;使えます。
…が、2点ほどハマったのでメモ。(2025/12/31追記)&lt;/p&gt;
&lt;h3&gt;virtio関連デバイスのdts定義がない&lt;/h3&gt;
&lt;p&gt;...というか、実はzephyrのツリーに含まれているのですが、&lt;code&gt;ZEPHYR_ROOT/boards/qemu/qemu_cortex_a53.dts&lt;/code&gt;
に記述がある程度で、qemu_x86_64 や qemu_kvm_arm64 で使おうとすると overlay ファイルを作ってやる
必要があります。&lt;/p&gt;
&lt;p&gt;これに何を参考にすればよいのか悩ましいのですが、 &lt;code&gt;ZEPHYR_ROOT/tests/drivers/build_all/virtio/boards/qemu_x86_64.overlay&lt;/code&gt; がテストに使われているもので、virtio-pci/virtio-net-pci/virtio-console-pci/virtio-entropy まではこれで使えるようです。&lt;/p&gt;
&lt;p&gt;私は自分のアプリの boards ディレクトリの下に上記をコピーして持ってきてビルドできました。
(ただし、後述のprj.confの定義にも落とし穴がある)&lt;/p&gt;
&lt;h3&gt;CONFIG_UART_VIRTIO_CONSOLEが有効にならない？&lt;/h3&gt;
&lt;p&gt;prj.confで、以下の3つすべてを &lt;code&gt;n&lt;/code&gt; に指定してやる必要があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CONFIG_EARLY_CONSOLE&lt;/li&gt;
&lt;li&gt;CONFIG_X86_VERY_EARLY_CONSOLE&lt;/li&gt;
&lt;li&gt;CONFIG_BOOT_BANNER&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;特に3つめは気づかなかったっすorz&lt;/p&gt;
&lt;p&gt;今回は、比較的最近mergeされたらしい virtio-net のドライバを使い、qemu環境で動かそうとしていました。
参考までに prj.conf の差分を付けておきます。VIRTIO関連以外には、qemu環境なので、GPIOやLEDは無効にする必要がありました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;(venv) zephyr:~/zephyrproject/zephyr/samples/net/sockets/http_server$ git diff prj.conf
diff --git a/samples/net/sockets/http_server/prj.conf b/samples/net/sockets/http_server/prj.conf
index 5cfe2a04ad2..8b13bb6e150 100644
--- a/samples/net/sockets/http_server/prj.conf
+++ b/samples/net/sockets/http_server/prj.conf
@@ -26,6 +26,21 @@ CONFIG_NET_STATISTICS=y
 CONFIG_NET_STATISTICS_USER_API=y
 CONFIG_NET_LOG=y

+# for virtio_net
+CONFIG_PCIE=y
+CONFIG_ETH_DRIVER=y
+CONFIG_VIRTIO=y
+CONFIG_VIRTIO_PCI=y
+CONFIG_ETH_VIRTIO_NET=y
+
+CONFIG_PRINTK=y
+CONFIG_EARLY_CONSOLE=n
+CONFIG_BOOT_BANNER=n
+CONFIG_X86_VERY_EARLY_CONSOLE=n
+CONFIG_UART_VIRTIO_CONSOLE=y
+CONFIG_UART_VIRTIO_CONSOLE_F_MULTIPORT=y
+
+
 # JSON
 CONFIG_JSON_LIBRARY=y

@@ -64,8 +79,8 @@ CONFIG_NET_CONFIG_PEER_IPV6_ADDR=&amp;quot;2001:db8::2&amp;quot;
 CONFIG_NET_TCP_TIME_WAIT_DELAY=0

 # Device drivers
-CONFIG_GPIO=y
-CONFIG_LED=y
+#CONFIG_GPIO=y
+#CONFIG_LED=y

 # Network debug config
 CONFIG_NET_SOCKETS_LOG_LEVEL_DBG=n
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;続きます。&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[ja] Zephyr ESP32 notes</title><link href="https://thatsdone.github.io/junkbox/zephyr_esp32_notes.html" rel="alternate"></link><published>2025-11-03T00:10:00+09:00</published><updated>2025-11-03T00:10:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2025-11-03:/junkbox/zephyr_esp32_notes.html</id><summary type="html">&lt;p&gt;ZephyrのESP32固有のメモ&lt;/p&gt;</summary><content type="html">&lt;p&gt;直近で書いた
&lt;a href="https://thatsdone.github.io/junkbox/hello_zephyr.html"&gt;Zephyrをはじめました&lt;/a&gt;
と
&lt;a href="https://thatsdone.github.io/junkbox/zephyr_generic_notes.html"&gt;Zephyrの一般的な使い方メモ(ボード非依存)&lt;/a&gt;
の記事の後、とりあえずESP32からいきます。&lt;/p&gt;
&lt;h2&gt;前提&lt;/h2&gt;
&lt;p&gt;私はEspressifのESP32-WROVER-E というボードを使っています。
CPUはTensilica XtensaアーキテクチャのLX6というだいぶ古いものです。
Zephyrのboardページだと&lt;a href="https://docs.zephyrproject.org/latest/boards/espressif/esp32_devkitc/doc/index.html"&gt;ここ&lt;/a&gt;にあるものに対応します。&lt;/p&gt;
&lt;p&gt;以下、シリーズによってはあてはまらない情報があるかもしれませんが、御承知おきを。&lt;/p&gt;
&lt;h2&gt;ESP32のCANコントローラ(TWAI)を使いたい&lt;/h2&gt;
&lt;p&gt;可能です。&lt;/p&gt;
&lt;p&gt;ただし、少なくとも v4.2.0-4096-g1c1598601b5c 時点では、disabledにされています。
具体的に言うと以下のあたり。(2025/11/02時点)&lt;/p&gt;
&lt;p&gt;https://github.com/zephyrproject-rtos/zephyr/blob/main/dts/xtensa/espressif/esp32/esp32_common.dtsi#L438&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mi"&gt;431&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;twai&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;can&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="mf"&gt;3f&lt;/span&gt;&lt;span class="n"&gt;f6b000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;432&lt;/span&gt;&lt;span class="w"&gt;                         &lt;/span&gt;&lt;span class="n"&gt;compatible&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;espressif,esp32-twai&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;433&lt;/span&gt;&lt;span class="w"&gt;                         &lt;/span&gt;&lt;span class="n"&gt;reg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;0x3ff6b000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DT_SIZE_K&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;434&lt;/span&gt;&lt;span class="w"&gt;                         &lt;/span&gt;&lt;span class="n"&gt;interrupts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TWAI_INTR_SOURCE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IRQ_DEFAULT_PRIORITY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;435&lt;/span&gt;&lt;span class="w"&gt;                         &lt;/span&gt;&lt;span class="n"&gt;interrupt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;intc&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;436&lt;/span&gt;&lt;span class="w"&gt;                         &lt;/span&gt;&lt;span class="n"&gt;clocks&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;clock&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ESP32_TWAI_MODULE&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;437&lt;/span&gt;&lt;span class="w"&gt;                         &lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;disabled&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;★&lt;/span&gt;&lt;span class="n"&gt;disabledになっている&lt;/span&gt;&lt;span class="err"&gt;★&lt;/span&gt;
&lt;span class="mi"&gt;438&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;このため、overlayファイルを作ってオーバーライドしてあげる必要があります。
やり方は&lt;a href="https://thatsdone.github.io/junkbox/zephyr_generic_notes.html"&gt;前の記事&lt;/a&gt;を参照してください。&lt;/p&gt;
&lt;h2&gt;ESP32でCAN通信をしたい&lt;/h2&gt;
&lt;p&gt;可能です。&lt;/p&gt;
&lt;p&gt;ただし、ESP32はCANのコントローラしか内蔵していないので、CANトランシーバーを接続してあげる必要があります。&lt;/p&gt;
&lt;p&gt;私は、MicrochipのCAN-FD対応のトランシーバーのMCP2562FDを使い、
&lt;a href="https://ameblo.jp/fc2miha/entry-12833773100.html"&gt;この記事&lt;/a&gt;で紹介されている回路を組み、対向側としてRaspberry Pi Zero W + DSP SH-C31AおよびRenesas R-Car V4Hを搭載したSBCの
&lt;a href="https://www.renesas.com/en/support/partners/r-car-consortium/r-car-consortium-proactive-partner-list/rtx-sparrow-hawk"&gt;Sparrow Hawk&lt;/a&gt;
で動作確認しました。
MCP2562FDは&lt;a href="https://akizukidenshi.com/catalog/g/g114383/"&gt;秋月で200円(当時)&lt;/a&gt;でした。&lt;/p&gt;
&lt;p&gt;2025/10/20に大阪で開催されたZephyr Project Meetup: Osaka, Japanで話した
&lt;a href="https://speakerdeck.com/thatsdone/esp32-de-canwozephyrdeyatutemita"&gt;ネタ&lt;/a&gt;
はこの話をしています。&lt;/p&gt;
&lt;p&gt;会場で「普通はMicrochipのトランシーバを使うのか？」という質問を受けましたが、
CANは枯れた規格なので、基本的には何でも動くのではないかと思います。NXPのチップとか。動作電圧とかは注意ですが...&lt;/p&gt;
&lt;h2&gt;CANデバイスの状態を確認したい&lt;/h2&gt;
&lt;p&gt;微妙です。(...だと思います(4.2.0時点))&lt;/p&gt;
&lt;p&gt;prj.confでCONFIG_CAN_SHELLを有効化(&lt;code&gt;=y&lt;/code&gt;)すると使えるようになる
shellのCANサポート機能を使い、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;uart:~$ can show DEVICE_ID
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;等とやるとトランシーバーの状態まで表示できます。
使えるDEVICE_IDは、省略して &lt;code&gt;can show&lt;/code&gt; とやると一覧表示されます。&lt;/p&gt;
&lt;p&gt;以下は can show DEVICE_IDしてみた時のログの例になりますが、
外付けのCAN transceiverの場合は、ESP32とは関係なく、もうひと手間加えてあげないと、
Zephyr側で認識してくれないように思います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;west&lt;span class="w"&gt; &lt;/span&gt;espressif&lt;span class="w"&gt; &lt;/span&gt;monitor
&lt;span class="o"&gt;(&lt;/span&gt;snip&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;:00:00.175,000&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;dbg&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;can_sja1000:&lt;span class="w"&gt; &lt;/span&gt;can_sja1000_init:&lt;span class="w"&gt; &lt;/span&gt;initial&lt;span class="w"&gt; &lt;/span&gt;sample&lt;span class="w"&gt; &lt;/span&gt;point&lt;span class="w"&gt; &lt;/span&gt;error:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
***&lt;span class="w"&gt; &lt;/span&gt;Booting&lt;span class="w"&gt; &lt;/span&gt;Zephyr&lt;span class="w"&gt; &lt;/span&gt;OS&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;v4.2.0-4096-g1c1598601b5c&lt;span class="w"&gt; &lt;/span&gt;***
&lt;span class="o"&gt;(&lt;/span&gt;snip&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;いきなり余談ですが...&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ESP32の場合は westの拡張が入っていて &lt;code&gt;west espressif monitor&lt;/code&gt; とかできるので便利です&lt;/li&gt;
&lt;li&gt;上記をみるとESP32が内蔵するCANコントローラはNXPのSJA1000互換のIPを使っているものと想像できます。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;以下、状態表示してみた結果。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nl"&gt;uart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;can&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;can&lt;/span&gt;&lt;span class="mf"&gt;@3ff&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="n"&gt;b000&lt;/span&gt;
&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clock&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;40000000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Hz&lt;/span&gt;
&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bitrate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bps&lt;/span&gt;
&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="nl"&gt;capabilities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;normal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;loopback&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;shot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;triple&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sampling&lt;/span&gt;
&lt;span class="nl"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;normal&lt;/span&gt;
&lt;span class="nl"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;ここのstate:はCANコントローラの状態です。&lt;code&gt;error-&lt;/code&gt;というprefixが気になるのですが、コードを眺める限りは、これで正常に初期化できているということのようです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;rx errors:       0
tx errors:       0
timing:          sjw 1..4, prop_seg 0..0, phase_seg1 1..16, phase_seg2 1..8, prescaler 1..64
transceiver:     passive/none
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;次にここ。transceiver: が &lt;code&gt;passive/none&lt;/code&gt; という状態になっていて、トランシーバの状態が取れない模様...うん？&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;statistics&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;bit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;bit0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;bit1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;stuff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;crc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;ack&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;rx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;overruns&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;しかし、このまま送信処理をしてみると、以下のように無事に送信処理が終わっている!?&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nl"&gt;uart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;can&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;can&lt;/span&gt;&lt;span class="mf"&gt;@3ff&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="n"&gt;b000&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;234&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;56&lt;/span&gt;
&lt;span class="n"&gt;enqueuing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CAN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;standard&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CAN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x234&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RTR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CAN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BRS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DLC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;CAN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;successfully&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sent&lt;/span&gt;
&lt;span class="nl"&gt;uart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;このログを採取した際、CANバスの対向側にRaspberry Pi Zero W+DSD SH-C31Aをつないでおり、実際にデータが流れていることを確認しています。&lt;/p&gt;
&lt;p&gt;それで、上記transceiverの表示のところは、ソースの該当部分を眺めると、deviceに対応する管理構造体がない(＝pointerがNULL)だとこういう表示になるようです。&lt;/p&gt;
&lt;p&gt;と、いうことは...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;dtsで何かtransceiver用の記述をしてあげないといけない？&lt;/li&gt;
&lt;li&gt;後述のCAN Busの状態をGPIOで制御したい場合と同様に、GPIO用のpin定義のついでに)deviceも書かないといけない？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;...とか想像できますが、まだ裏がとれていません。&lt;/p&gt;
&lt;p&gt;あとは、statistics: のところ、数字が入ってくれるのかどうか、まだ確認できていません。&lt;/p&gt;
&lt;p&gt;うーん...&lt;/p&gt;
&lt;h2&gt;CAN Busの状態を制御したい(BUS Stopさせたり戻したりとか)&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;can_transceiver_enable()&lt;/code&gt; というAPIを使って可能(...なはず)です。
CANコントローラへの指示ではなく、トランシーバのSTBY(だったり、チップによってはSだったりしますが...)GPIOでピンの値を制御することになります。(はずです)&lt;/p&gt;
&lt;p&gt;...とはいえ上記に書いたように、何かおまじないが必用...と思われます。&lt;/p&gt;
&lt;p&gt;以下、参考。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CAN transceiverまわりの説明&lt;ul&gt;
&lt;li&gt;https://docs.zephyrproject.org/latest/hardware/peripherals/can/transceiver.html&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CAN transceiver APIの説明&lt;ul&gt;
&lt;li&gt;https://docs.zephyrproject.org/latest/doxygen/html/group__can__transceiver.html&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;ESP32の複数コアを使いたい&lt;/h2&gt;
&lt;p&gt;可能です。&lt;/p&gt;
&lt;p&gt;ESP32の場合は、普通のSMPではなく、
&lt;a href="https://docs.zephyrproject.org/latest/boards/espressif/common/soc-esp32-features.html#asymmetric-multiprocessing-amp"&gt;AMP(Asymmetric Multi-processing)&lt;/a&gt;
と呼ばれる使い方になるようです。
ビルドの際に、先頭のコア用のプログラムはprocpu、
2番目(以降?)のコアがappcpuという名前でターゲット指定することになります。
sysbuildでブートローダにmcubootを指定し、2番目のコア(前述のappcpu)用のプログラムは &lt;code&gt;remote&lt;/code&gt; というディレクトリにわけて作ることになるようですが、識者によると、ここでも「黒魔術」っぽさがある模様...gkbr&lt;/p&gt;
&lt;p&gt;複数コアの間の通信や同期には
&lt;a href="https://docs.zephyrproject.org/latest/hardware/peripherals/ipm.html"&gt;IPM: Inter-Processor Mailbox&lt;/a&gt;
という仕組みが使えるようになっています。
IPMを使ったプログラミングの具体例は、zephyr公式のサンプルにも含まれています。ESP32用のものは&lt;a href="https://github.com/zephyrproject-rtos/zephyr/tree/main/samples/drivers/ipm/ipm_esp32"&gt;ここ&lt;/a&gt;にあります。&lt;/p&gt;
&lt;p&gt;なお、threadを使うだけでは1コアしか使われないことに注意が必要です。(たぶん)&lt;/p&gt;
&lt;h2&gt;TODO&lt;/h2&gt;
&lt;p&gt;以下のような確認を行いながら更新してく予定。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;multi-threadを使いたい&lt;/li&gt;
&lt;li&gt;ESP32のWiFiを使いたい&lt;/li&gt;
&lt;li&gt;ESP32でhttp_serverを動かしたい&lt;/li&gt;
&lt;li&gt;gdbでリモート(?)デバッグしたい&lt;/li&gt;
&lt;li&gt;ESP32にセンサ(I2CとかSPIとか)をつなぎたい&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;</content><category term="tech"></category></entry><entry><title>[ja] Zephyr generic notes</title><link href="https://thatsdone.github.io/junkbox/zephyr_generic_notes.html" rel="alternate"></link><published>2025-11-02T13:25:00+09:00</published><updated>2025-11-02T13:25:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2025-11-02:/junkbox/zephyr_generic_notes.html</id><summary type="html">&lt;p&gt;Zephyrの一般的な使い方メモ(ボード非依存)&lt;/p&gt;</summary><content type="html">&lt;p&gt;Zephyrをはじめてみて、有識者のみなさんにいろいろ教えを受けつつ気づいたこと、
特にボード非依存のメモをまとめる場所にします。(＝断続的に更新していきます)&lt;/p&gt;
&lt;p&gt;ボード依存の話は別記事で。現状、以下の子たちくらいを予定しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ESP32 (初代無印、Xtensa LX6のDevkitC)&lt;/li&gt;
&lt;li&gt;Raspberry Pi (5とZero W)&lt;/li&gt;
&lt;li&gt;qemu系 (x86_64とaarch64)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.zephyrproject.org/latest/boards/xen/xenvm/doc/index.html"&gt;xenvm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;自分のアプリをどこにおけばいいのか？&lt;/h2&gt;
&lt;p&gt;答：どこでもかまいません。&lt;/p&gt;
&lt;p&gt;補足：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一次情報&lt;ul&gt;
&lt;li&gt;&lt;a href="https://zephyrproject.org/how-to-build-your-zephyr-app-in-a-standalone-folder/"&gt;How to build your Zephyr app in a standalone folder&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;特に SOME_WHEHERE/zephyrproject/zephyr の下に置く必要はありません。&lt;/li&gt;
&lt;li&gt;SOMEWHERE/zephyrproject/zephyr/zephyr-env.sh という環境設定用のファイルがありますので、これをsourceしてください。&lt;/li&gt;
&lt;li&gt;自分のアプリのディレクトリの中で &lt;code&gt;west build -p -b YOUR_TARGET_BOARD .&lt;/code&gt; とすればOKです。&lt;ul&gt;
&lt;li&gt;最後の &lt;code&gt;.&lt;/code&gt; (ピリオド＝カレントディレクトリを指定)を忘れないでください&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ビルドされた生成物は、上記自分のアプリのディレクトリの中に build というディレクトリが作成されて格納されます。&lt;ul&gt;
&lt;li&gt;未確認すが、自分のアプリのディレクトリとは違うところで west コマンドを起動すると、カレントに build ができるかもしれません&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;DTSをoverlayしたい場合のファイル名や配置場所は？&lt;/h2&gt;
&lt;p&gt;答：自分のアプリのディレクトリの中に所定のファイル名で、所定の名前のディレクトリを作って格納してください。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/thatsdone/zephyr-canapp"&gt;私の事例&lt;/a&gt;では、ESP32のdevice treeはzephyr/boards/espressif以下にボードごとに格納されていました。ただ、CANコントローラのTWAIはdisableだったので、okにオーバーライドする必要がありました。こういう場合にどうするか？です&lt;/p&gt;
&lt;p&gt;典型的には YOUR_APP_DIR/boards/BOARDNAME.overlay になります。&lt;/p&gt;
&lt;p&gt;補足：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一次情報はこのへんにあります。&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.zephyrproject.org/latest/develop/application/index.html"&gt;Application Development&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ディレクトリの名前は board か soc になりますが、ボードごとになるほうが多いように思います。また、アプリケーション固有であれば application.overlay でもかまいません。(...が、アプリ固有でDTSいじる必要ってどのくらいあるんですかねぇ？)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;sampleについている sample.yaml は要るのか？&lt;/h2&gt;
&lt;p&gt;答：不要&lt;/p&gt;
&lt;p&gt;自分のアプリを公開するだけなら上記の通り不要です。&lt;/p&gt;
&lt;p&gt;ただし、zephyr公式distributionへのマージを目指すようであれば必要になります。&lt;/p&gt;
&lt;h2&gt;WSL2で使いたい&lt;/h2&gt;
&lt;p&gt;答：私はWSL2の Ubuntu 24.04環境で問題なく使えています。&lt;/p&gt;
&lt;h2&gt;WSL2でUSBデバイスを使えるの？&lt;/h2&gt;
&lt;p&gt;答：使えます。GUI操作でUSBデバイスの付け替えができる &lt;a href="https://github.com/dorssel/usbipd-win"&gt;usbipd-win&lt;/a&gt; がとても便利です。&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[ja] Hello Zephyr</title><link href="https://thatsdone.github.io/junkbox/hello_zephyr.html" rel="alternate"></link><published>2025-10-25T18:10:00+09:00</published><updated>2025-10-25T18:10:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2025-10-25:/junkbox/hello_zephyr.html</id><summary type="html">&lt;p&gt;Zephyrはじめました&lt;/p&gt;</summary><content type="html">&lt;p&gt;今年('25)の5月くらいまでさかのぼりますが、RTOSの&lt;a href="https://www.zephyrproject.org/"&gt;Zephyr&lt;/a&gt;をさわりはじめました。&lt;/p&gt;
&lt;p&gt;しばらく前から趣味で作っている&lt;a href="https://github.com/thatsdone/mpmt/"&gt;CPU負荷発生器&lt;/a&gt;で
新言語のネタがなくなってきたのと、
やんごとなき事情(?)で関わっている&lt;a href="https://www.automotivelinux.org/"&gt;AGL&lt;/a&gt;の議論の中で興味を持ったのがきっかけです。&lt;/p&gt;
&lt;h2&gt;CPU負荷発生器(mpmt)のZephyr版を作ってみる&lt;/h2&gt;
&lt;p&gt;まず、とりあえずはCPU負荷発生器のmpmtのZephyr版を作ってみました。&lt;/p&gt;
&lt;p&gt;README.mdは&lt;a href="https://github.com/thatsdone/mpmt/tree/main/zephyr"&gt;こんな感じ&lt;/a&gt;です。
x86_64とarm64のそれぞれやってみました。&lt;/p&gt;
&lt;p&gt;kernel threadを使って、指定したcore数を使い切っているなというところまで確認できて、
いったん満足してしまいました(苦笑)&lt;/p&gt;
&lt;h2&gt;CAN通信してみる&lt;/h2&gt;
&lt;p&gt;CPU負荷発生器を作ってみたあと、しばらく別件で忙しくなってお休みしていたのですが、
AGL方面でZephyrが動くマイコンでCAN通信できることを確認しておこうという話があり、担当することにしました。&lt;/p&gt;
&lt;p&gt;お題は、コロナがはじまったころに出来心で買ったまま放置していたEspressifのESP32を使っています。&lt;/p&gt;
&lt;p&gt;中間成果を先日('25/10/20)大阪で開催されたZephyr Project Meetup: Japan, Osakaというイベントで話してきました。
イベントが&lt;a href="https://connpass.com/event/368403/"&gt;これ&lt;/a&gt;で、
話した小ネタが&lt;a href="https://speakerdeck.com/thatsdone/esp32-de-canwozephyrdeyatutemita"&gt;これ&lt;/a&gt;です。&lt;/p&gt;
&lt;p&gt;ESP32とRaspberry Pi Zero W、
および&lt;a href="https://www.renesas.com/en/support/partners/r-car-consortium/r-car-consortium-proactive-partner-list/rtx-sparrow-hawk"&gt;Renesas R-Car Sparrow Hawk&lt;/a&gt;の2種類のSBCと、
対向でCAN通信できるところまで確認しています。&lt;/p&gt;
&lt;h2&gt;今後&lt;/h2&gt;
&lt;p&gt;上記の小ネタ発表資料にも書きましたが、以下のようなことを考えています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AGL付属のCAN負荷発生機の移植&lt;/li&gt;
&lt;li&gt;Zephyr virtio-can driver (FE/BE)開発のお手伝い&lt;/li&gt;
&lt;li&gt;UDSライブラリの開発&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そのほか、ESP32はIoTマイコンとしては比較的ポピュラーな位置づけかなと思うのですが、
クラウドというかデータセンタ用のサーバでの開発とくらべていろいろ違いがあるな…
という気付きがあったのでぼちぼちまとめていきたいと思います。&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[ja] Linux Kernel Build TIPs</title><link href="https://thatsdone.github.io/junkbox/linux_kernel_build_tips.html" rel="alternate"></link><published>2024-11-20T18:10:00+09:00</published><updated>2024-11-20T18:10:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2024-11-20:/junkbox/linux_kernel_build_tips.html</id><summary type="html">&lt;p&gt;Linux Kernel Build時のハマリポイント&lt;/p&gt;</summary><content type="html">&lt;p&gt;ある意味、先月の&lt;a href="https://thatsdone.github.io/junkbox/manage_grub_default.html"&gt;この記事&lt;/a&gt;の続き。&lt;/p&gt;
&lt;p&gt;6.12がリリースされたので、PREEMPT_RTとsched_extを試そうとしていて、必要なCONFIGを有効にするのに
少し見落としがあったのでメモ。&lt;/p&gt;
&lt;p&gt;※'25/04/06: この記事を書いた当時に6.12で遊び、その後6.13、6.14ときて、RUSTでも気づいたことがあったので追記。&lt;/p&gt;
&lt;h2&gt;前提&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;ビルド環境: Ubuntu 24.04.1(amd64)&lt;/li&gt;
&lt;li&gt;ツール類: 基本的にUbuntu bundle版&lt;ul&gt;
&lt;li&gt;ただし、後述のRust関連だけ、upstreamから持ってきている&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;PREEMPT_RTの有効化&lt;/h2&gt;
&lt;p&gt;長らく開発が続いてきて、とうとう&lt;a href="https://www.managedserver.eu/preempt_rt-real-time-linux-and-finally-part-of-the-linux-kernel/"&gt;6.12でmerge&lt;/a&gt;されて話題になっていたReal-Time機能のPREEMPT_RTを使ってみたいと思ったのが発端。&lt;/p&gt;
&lt;p&gt;ビルドにあたって、&lt;code&gt;make menuconfig&lt;/code&gt;では、冒頭の"General Setup"の中で、
"BPF Subsystem"の下に出てくる"Preemption Model"...ではなく、
"Fully Preemptive Kernel (Real-Time)" を選択する。(6.14の場合)&lt;/p&gt;
&lt;p&gt;選べる詳細条件の確認は kernel/Kconfig.preempt を参照。&lt;/p&gt;
&lt;h2&gt;PREEMPT_RTで遊ぶには&lt;/h2&gt;
&lt;p&gt;realtime taskを動かせばよいのだが、
例えば&lt;a href="https://wiki.linuxfoundation.org/realtime/documentation/howto/tools/rt-tests"&gt;rt-tests&lt;/a&gt;に含まれる&lt;a href="https://wiki.linuxfoundation.org/realtime/documentation/howto/tools/cyclictest/start"&gt;cyclictest&lt;/a&gt;とかがよくつかわれるようだ。&lt;/p&gt;
&lt;h2&gt;sched_ext(CONFIG_SCHED_CLASS_EXT)の有効化&lt;/h2&gt;
&lt;p&gt;sched_extを使うと、eBPFでオレスケジューラを書いたりすることができる。&lt;/p&gt;
&lt;p&gt;ビルドにあたって、&lt;code&gt;make menuconfig&lt;/code&gt;では、PREEMPT_RTと同じく "General setup"の中で、"Preemption Model"の2つ下に出てくる"Extensible Scheduling Class"が該当する。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ハマりポイント&lt;/strong&gt;として、上記の項目がでてこないことがあるのだが、私の場合は&lt;strong&gt;paholeがインストールされていなかった&lt;/strong&gt;のが原因だった。&lt;code&gt;sudo apt install pahole&lt;/code&gt; した後で&lt;code&gt;make menuconfig&lt;/code&gt;すると選べるようになる。&lt;/p&gt;
&lt;p&gt;同じく選べるための詳細条件の確認は kernel/Kconfig.preempt を参照。&lt;/p&gt;
&lt;h2&gt;sched_extで遊ぶには&lt;/h2&gt;
&lt;p&gt;Linux kernelの tools/sched_ext にサンプルが一式ついている。README.mdに書いてある通りの使い方で素直に動く。&lt;/p&gt;
&lt;p&gt;ビルドして起動したkernelで、無事にsched_extが有効になっているかどうかは sysfs 経由で確認できる。
&lt;code&gt;/sys/kernel/sched_ext&lt;/code&gt; が存在し、stateの中身で enabled/disabledがわかる。
以下は初期状態(=disabled)で、これから設定して使う。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-al&lt;span class="w"&gt; &lt;/span&gt;/sys/kernel/sched_ext
total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
drwxr-xr-x&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Mar&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;08&lt;/span&gt;:43&lt;span class="w"&gt; &lt;/span&gt;.
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;18&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Mar&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;08&lt;/span&gt;:10&lt;span class="w"&gt; &lt;/span&gt;..
-r--r--r--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Mar&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;08&lt;/span&gt;:25&lt;span class="w"&gt; &lt;/span&gt;enable_seq
-r--r--r--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Mar&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;08&lt;/span&gt;:25&lt;span class="w"&gt; &lt;/span&gt;hotplug_seq
-r--r--r--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Mar&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;08&lt;/span&gt;:25&lt;span class="w"&gt; &lt;/span&gt;nr_rejected
-r--r--r--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Mar&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;08&lt;/span&gt;:25&lt;span class="w"&gt; &lt;/span&gt;state
-r--r--r--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Mar&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;08&lt;/span&gt;:25&lt;span class="w"&gt; &lt;/span&gt;switch_all
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt;   &lt;/span&gt;/sys/kernel/sched_ext/state
disabled
$
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;以下、参考リンク&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.kernel.org/doc/html/next/scheduler/sched-ext.html"&gt;https://www.kernel.org/doc/html/next/scheduler/sched-ext.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sched-ext/scx"&gt;https://github.com/sched-ext/scx&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Rustで遊ぶには&lt;/h2&gt;
&lt;p&gt;私は仕事で機能安全が求められるような組み込みとセンタ側の両方に足を突っ込んでいるのだが、機能安全界隈でもRustが話題になっている関係もあって、遅ればせながら(kernelでも)Rustで遊んでみることにした。&lt;/p&gt;
&lt;p&gt;以下、.configに必要な設定を入れるまでの道のり。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ツールチェーン関連&lt;/li&gt;
&lt;li&gt;rustコンパイラ/LLVM&lt;ul&gt;
&lt;li&gt;もちろんツールチェーンが必要になる。以下で配っているstable用のものを使うのが安全だと思う。&lt;/li&gt;
&lt;li&gt;https://mirrors.edge.kernel.org/pub/tools/llvm/rust/&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;bindgen&lt;ul&gt;
&lt;li&gt;x86_64では、当時利用していた llvm-19.1.7-rust-1.85.0-x86_64 付属の bindgenでは不具合があって必要な項目が出てこず選択できなかったため、下記のbindgenのreleaseから 0.71.1 を持ってきて入れ替えて使った&lt;ul&gt;
&lt;li&gt;https://github.com/rust-lang/rust-bindgen/wreleases&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;arm64では、llvm-19.1.7-rust-1.86.0-aarch64 (rustのversionが0.01違うのに注意)にはそもそもbindgenが含まれていなかった。Ubuntu 24.04付属の bindgen は0.66系で古く、同じく不具合を起こすため、上記repositoryをcloneの上 &lt;code&gt;cargo install bindgen-cli&lt;/code&gt; して 0.71.1 (aarch64)を入れた。(PATHの更新に注意)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CONFIG_MODVERSIONS&lt;ul&gt;
&lt;li&gt;少なくとも6.14の時点では、Rustによるkernel moduleを使いたい場合はloadable kernelのバージョニングを無効にする必要がある&lt;/li&gt;
&lt;li&gt;"Enable loadable module support" -&amp;gt; "Module versioning Support" のチェックをはずす&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CONFIG_RUST&lt;ul&gt;
&lt;li&gt;"General setup" -&amp;gt;  "Rust support" (6.14時点では一番下から２番目)をチェック&lt;/li&gt;
&lt;li&gt;"Rust support"が出てこない場合、前述のツールチェーンが要件を満たしてない場合か、CONFIG_MODVERSIONS等の依存config設定に不整合がある場合がある。その他の条件を確認するには init/Kconfig の "config RUST" のところを参照のこと。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CONFIG_SAMPLES_RUST&lt;ul&gt;
&lt;li&gt;"General setup" -&amp;gt; "Kernel hacking" -&amp;gt; "Sample kernel code" -&amp;gt; "Rust samples" にチェックをつけると samples/rust 以下のサンプルがビルドされる。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Ubuntuの /boot/config-* を流用する場合の注意&lt;/h2&gt;
&lt;p&gt;私は普段はUbuntuの上で生活している。この関係で新しいkernelを試す時もUbuntuの上になる。&lt;/p&gt;
&lt;p&gt;そうすると、.config もあまりベースと違うと動くはずのものが動かなくなったりするため、/boot/config-* を流用
することが多い。&lt;/p&gt;
&lt;p&gt;この場合の注意として、以下の２つのキーを無効にする(""を設定)必要がある。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SYSTEM_TRUSTED_KEYS&lt;/li&gt;
&lt;li&gt;CONFIG_SYSTEM_REVOCATION_KEYS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://askubuntu.com/questions/1329538/compiling-kernel-5-11-11-and-later"&gt;参考記事&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;なお、上記の参考記事によると make menuconfig してできあがった .config を書き換えればよいようなコメントがついているのだが、少なくとも6.14の場合はもういちど make menuconfig する必要があった。(設定はなにもいじらないがとにかく保存して終了)&lt;/p&gt;
&lt;h2&gt;kernelビルドに必要なパッケージ&lt;/h2&gt;
&lt;p&gt;私は、開発環境用にUbuntuでサーバを作る場合、とりあえず build-essentialとdevscriptsを入れる。
kernelをビルドする際にこれでも足りないものを列挙しておく。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;libncurses-dev&lt;/li&gt;
&lt;li&gt;flex&lt;/li&gt;
&lt;li&gt;bison&lt;/li&gt;
&lt;li&gt;libelf-dev&lt;/li&gt;
&lt;li&gt;libssl-dev&lt;/li&gt;
&lt;li&gt;pahole (前述の通り)&lt;/li&gt;
&lt;li&gt;Rust/LLVMのツールチェーン (前述の通り)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;そのほか&lt;/h2&gt;
&lt;p&gt;もっとあったような気がするので別途追記/更新予定。&lt;/p&gt;
&lt;p&gt;eBPFで気持ちよく遊ぶ都合でCONFIG_DEBUG_INFO_BTFも有効にしたのだが、これはSCXで求められるんだっけな...(To be updated)&lt;/p&gt;
&lt;h2&gt;HISTORY&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;'24/11/20 初出&lt;/li&gt;
&lt;li&gt;'25/04/06 Rust関連の記述を追記&lt;/li&gt;
&lt;li&gt;'25/04/13 Ubuntuの config-* を流用する場合の注意と必要パッケージを追記&lt;/li&gt;
&lt;/ul&gt;</content><category term="tech"></category></entry><entry><title>[ja] How to manage GRUB default kernel</title><link href="https://thatsdone.github.io/junkbox/manage_grub_default.html" rel="alternate"></link><published>2024-10-14T16:52:00+09:00</published><updated>2024-10-14T16:52:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2024-10-14:/junkbox/manage_grub_default.html</id><summary type="html">&lt;p&gt;GRUBのbootに使われるkernelを管理する&lt;/p&gt;</summary><content type="html">&lt;p&gt;最近、かなり久しぶりにvanilla kernelをビルドする機会があり、
kernelを切り替えて使いたい場合のGRUBの設定で気づいたことがあったのでメモ。&lt;/p&gt;
&lt;p&gt;最近...といっても、20.04くらいからだろうか。submenu というものが導入され、昔のノウハウが効かなくなっている模様。&lt;/p&gt;
&lt;p&gt;2024/10/14時点での情報。&lt;/p&gt;
&lt;h2&gt;Ubuntu 24.04 LTS時点での答&lt;/h2&gt;
&lt;p&gt;以下の手順でdefaultでbootに使われるkernelを切り替え可能。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;/etc/default/grub の GRUB_DEFAULT に saved を設定する&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GRUB_DEFAULT=0&lt;/code&gt; → &lt;code&gt;GRUB_DEFAULT=saved&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Ubuntuだと普通は0になっているので、ここの修正が必要ということ&lt;/li&gt;
&lt;li&gt;なお、記事によっては、/etc/default/grub に &lt;code&gt;GRUB_SAVEDEFAULT=true&lt;/code&gt; を設定するべしという説明がある。これを入れると、私の場合は、後述の grub-reboot コマンドによる一時的な切り替えが効かなくなった。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;grub-set-default で、'SUBMENU_ID&amp;gt;MENUENTRY_ID' の形式で指定する&lt;ul&gt;
&lt;li&gt;SUBMENU_ID は &lt;code&gt;sudo grep submenu /boot/grub/grub.cfg&lt;/code&gt; で調べる&lt;/li&gt;
&lt;li&gt;MENUENTRY_ID は &lt;code&gt;sudo grep menuentry /boot/grub/grub.cfg&lt;/code&gt; で調べる&lt;/li&gt;
&lt;li&gt;例: &lt;code&gt;# sudo grub-set-default 'gnulinux-advanced-69cecedb-4058-4b83-8507-cca6498f4099&amp;gt;gnulinux-6.8.0-45-generic-advanced-69cecedb-4058-4b83-8507-cca6498f4099'&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;# update-grub&lt;/code&gt; する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;# reboot&lt;/code&gt; する&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;これで指定したkernelがdefaultに切り替わる。&lt;/p&gt;
&lt;h2&gt;一時的に次にbootするkernelを切り替える場合&lt;/h2&gt;
&lt;p&gt;kernelそのものをいじっている場合など、次のboot時のみ一時的に切り替えたい等の場合は、&lt;code&gt;grub-reboot&lt;/code&gt; コマンドが使える。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;/etc/default/grub の GRUB_DEFAULT が saved になっていることを確認する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;# grub-reboot 'SUBMENU_ID&amp;gt;MENUENTRY_ID'&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;# update-grub&lt;/code&gt; する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;# reboot&lt;/code&gt; する&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;もう一度rebootすると、元のdefault kernelで起動される。&lt;/p&gt;
&lt;h2&gt;サンプル /boot/grub/grub.cfg&lt;/h2&gt;
&lt;p&gt;以下は私の、Ubuntu 22.04 から 24.04へ do-release-upgrade した環境の /boot/grub/grub.cfg の例。&lt;/p&gt;
&lt;p&gt;162行目の &lt;code&gt;$menuentry_id_option&lt;/code&gt; の後ろの &lt;code&gt;gnulinux-advanced-32227d3a-e56d-453c-b030-d3c44576fa3f'&lt;/code&gt; が上記のSUBMENU_IDの例。&lt;/p&gt;
&lt;p&gt;この環境では、そのままだと 163行目の 'Ubuntu, with Linux 6.8.0-45-generic' が使われるのだが、
190行目の &lt;code&gt;'gnulinux-5.15.0-122-generic-advanced-32227d3a-e56d-453c-b030-d3c44576fa3f'&lt;/code&gt; を使って
 &lt;code&gt;# grub-set-default 'SUBMENU_ID&amp;gt;MENUENTRY_ID'&lt;/code&gt; すればよい。&lt;/p&gt;
&lt;p&gt;ポイントは、私の場合は以下の2点だった。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;SUBMENU_ID と MENUENTRY_IDの間は &lt;code&gt;&amp;gt;&lt;/code&gt; でスペースを空けずにつなぐ&lt;/li&gt;
&lt;li&gt;&lt;code&gt;'&lt;/code&gt; でquoteするのが安全&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mi"&gt;162&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;submenu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Advanced options for Ubuntu&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;menuentry_id_option&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;gnulinux-advanced-32227d3a-e56d-453c-b030-d3c44576fa3f&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;163&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;menuentry&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Ubuntu, with Linux 6.8.0-45-generic&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ubuntu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gnu&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;linux&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gnu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;menuentry_id_option&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;gnulinux-6.8.0-45-    generic-advanced-32227d3a-e56d-453c-b030-d3c44576fa3f&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;164&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;recordfail&lt;/span&gt;
&lt;span class="mi"&gt;165&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;load_video&lt;/span&gt;
&lt;span class="mi"&gt;166&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;gfxmode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;linux_gfx_mode&lt;/span&gt;
&lt;span class="mi"&gt;167&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;insmod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gzio&lt;/span&gt;
&lt;span class="mi"&gt;168&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;grub_platform&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xxen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;insmod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xzio&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;insmod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lzop&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fi&lt;/span&gt;
&lt;span class="mi"&gt;169&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;insmod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;part_msdos&lt;/span&gt;
&lt;span class="mi"&gt;170&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;insmod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ext2&lt;/span&gt;
&lt;span class="mi"&gt;171&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;floppy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;32227&lt;/span&gt;&lt;span class="n"&gt;d3a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e56d&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;453&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;030&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;d3c44576fa3f&lt;/span&gt;
&lt;span class="mi"&gt;172&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Loading Linux 6.8.0-45-generic ...&amp;#39;&lt;/span&gt;
&lt;span class="mi"&gt;173&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;linux&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;boot&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;vmlinuz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;6.8&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;generic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32227&lt;/span&gt;&lt;span class="n"&gt;d3a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e5&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;453&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;b030&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;d3c44576fa3f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ro&lt;/span&gt;
&lt;span class="mi"&gt;174&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Loading initial ramdisk ...&amp;#39;&lt;/span&gt;
&lt;span class="mi"&gt;175&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;initrd&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;boot&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;initrd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;6.8&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;generic&lt;/span&gt;
&lt;span class="mi"&gt;176&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;snip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mi"&gt;190&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;menuentry&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Ubuntu, with Linux 5.15.0-122-generic&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ubuntu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;lass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gnu&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;linux&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gnu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;menuentry_id_option&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;gnulinux-5.15.0-    122-generic-advanced-32227d3a-e56d-453c-b030-d3c44576fa3f&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;191&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;recordfail&lt;/span&gt;
&lt;span class="mi"&gt;192&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;load_video&lt;/span&gt;
&lt;span class="mi"&gt;193&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;gfxmode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;linux_gfx_mode&lt;/span&gt;
&lt;span class="mi"&gt;194&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;insmod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gzio&lt;/span&gt;
&lt;span class="mi"&gt;195&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;grub_platform&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xxen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;insmod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xzio&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;insmod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lzop&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fi&lt;/span&gt;
&lt;span class="mi"&gt;196&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;insmod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;part_msdos&lt;/span&gt;
&lt;span class="mi"&gt;197&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;insmod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ext2&lt;/span&gt;
&lt;span class="mi"&gt;198&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;floppy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;32227&lt;/span&gt;&lt;span class="n"&gt;d3a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e56d&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;453&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;030&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;d3c44576fa3f&lt;/span&gt;
&lt;span class="mi"&gt;199&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Loading Linux 5.15.0-122-generic ...&amp;#39;&lt;/span&gt;
&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;linux&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;boot&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;vmlinuz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;5.15&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;122&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;generic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32227&lt;/span&gt;&lt;span class="n"&gt;d3a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;e56d&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;453&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;b030&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;d3c44576fa3f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ro&lt;/span&gt;
&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Loading initial ramdisk ...&amp;#39;&lt;/span&gt;
&lt;span class="mi"&gt;202&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;initrd&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;boot&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;initrd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;5.15&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;122&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;generic&lt;/span&gt;
&lt;span class="mi"&gt;203&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Xenを入れる場合&lt;/h2&gt;
&lt;p&gt;(2025/04/26追記)&lt;/p&gt;
&lt;p&gt;最近、事情でxen-system-(amd64|arm64)を使う必要が発生した。
UbuntuでXenを使う場合、Ubuntu 24.04だとうまくdom0を起動できない…という話もあって、このメモはUbuntu 22.04が前提になるが、
この件は24.04でXenが動くようにしたとしても構造上、共通だと思われる。&lt;/p&gt;
&lt;p&gt;発生する問題は、xen-system-amd64(等)を入れると、grub-set-defaultやgrub-rebootでの切り替えが効かなくなる。&lt;/p&gt;
&lt;p&gt;これは、xen-system-(amd64|arm64)を入れると &lt;code&gt;/etc/default/grub.d/xen.cfg&lt;/code&gt;　が追加され、こんな処理を追加しているためである。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-Ev&lt;span class="w"&gt; &lt;/span&gt;^&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="c1"&gt;#\|$\)  /etc/default/grub.d/xen.cfg&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Including Xen overrides from /etc/default/grub.d/xen.cfg&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$XEN_OVERRIDE_GRUB_DEFAULT&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;WARNING: GRUB_DEFAULT changed to boot into Xen by default!&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;         Edit /etc/default/grub.d/xen.cfg to avoid this warning.&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;XEN_OVERRIDE_GRUB_DEFAULT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$XEN_OVERRIDE_GRUB_DEFAULT&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;GRUB_DEFAULT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;gettext&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%s, with Xen hypervisor&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$GRUB_DISTRIBUTOR&lt;/span&gt;&lt;span class="s2"&gt; GNU/Linux&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;私は /etc/default/grub に&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gh"&gt;#&lt;/span&gt; view /etc/default/grub
(snip)
  6 XEN_OVERRIDE_GRUB_DEFAULT=0 　★これ
  7 #GRUB_DEFAULT=0
  8 GRUB_DEFAULT=saved
(snip)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;という行を追加することで対応したが、上記の処理を見てわかる通り、"1" 以外なら何でもよい。&lt;/p&gt;
&lt;p&gt;最初見落としていたのだが、update-grubする時に以下のようなWARNINGが出ていて、ちゃんとメッセージを読めよという話なのだった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;(snip)
Including Xen overrides from /etc/default/grub.d/xen.cfg
WARNING: GRUB_DEFAULT changed to boot into Xen by default!
         Edit /etc/default/grub.d/xen.cfg to avoid this warning.
Generating grub configuration   file    ...
(snip)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Grubで前に起動したシステムを記憶する&lt;ul&gt;
&lt;li&gt;https://www.terakin.com/ja/blog/archives/129&lt;/li&gt;
&lt;li&gt;/etc/default/grub に GRUB_SAVEDEFAULT=true が必要という説明がある。Windowsとのdual boot環境で、Linuxが普段使いだがWindows Updateでrebootを繰り返す...といった場合はこの記事に従うのがよいようだ。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;How to get grub2 to remember last choice?&lt;ul&gt;
&lt;li&gt;https://askubuntu.com/questions/148662/how-to-get-grub2-to-remember-last-choice&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Setting the desired kernel in GRUB menu&lt;ul&gt;
&lt;li&gt;https://askubuntu.com/questions/1526087/setting-the-desired-kernel-in-grub-menu&lt;/li&gt;
&lt;li&gt;/etc/grub.d/40_custom/ にファイルを作るやりかた&lt;/li&gt;
&lt;li&gt;Windows等とdual以上のboot環境にしたい場合に使うみたいだ&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;How do you change and set the default Kernel in Ubuntu Machine?&lt;ul&gt;
&lt;li&gt;https://mnzel.medium.com/how-do-you-change-and-set-the-default-kernel-in-ubuntu-machine-7ad1107e1b6f&lt;/li&gt;
&lt;li&gt;自分としてはコレがアタリだった&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</content><category term="tech"></category></entry><entry><title>[ja] L2 over SSH</title><link href="https://thatsdone.github.io/junkbox/l2_over_ssh.html" rel="alternate"></link><published>2023-09-26T19:00:00+09:00</published><updated>2023-09-26T19:00:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2023-09-26:/junkbox/l2_over_ssh.html</id><summary type="html">&lt;p&gt;ssh で L2 tunnelする&lt;/p&gt;</summary><content type="html">&lt;p&gt;これまでqiitaやらblogspotに記事を書いてきた記事をここに集約するシリーズ。&lt;/p&gt;
&lt;p&gt;今日は、なんと10年前(!)にblogspotに書いた&lt;a href="https://thatsdone-j.blogspot.com/2013/01/l2-over-ssh.html"&gt;記事&lt;/a&gt;。
同僚と「sshって通すとなんでもできちゃうよ…」と話していて、思い出しました。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;このところ ssh tunnel ネタが多いが、実は ssh を使って port forwarding だけではなく、L3トンネルや L2‘トンネルを作れるのはそんなに知られていないように思う。実際、自分も Software Design 2012/10月号の、川本(@togakushi)さんの記事「SSH力をつけよう！」を読むまで知らなかった。&lt;/p&gt;
&lt;p&gt;余談だが、この記事は本当にすばらしい。chef 特集につられて買った号だったのだが、編集部の気合いを感じた一冊だった。&lt;/p&gt;
&lt;p&gt;まず、L3トンネルのやり方から。
port forwarding とは違い、今度はオプションに -L ではなく -w を使う。
例えば&lt;/p&gt;
&lt;p&gt;$ ssh -w 0:0   root@remote_host&lt;/p&gt;
&lt;p&gt;とすれば、ローカルとリモートの双方に tun0 という tunnel device (tun) が作成され、
-w の指定値は、&lt;/p&gt;
&lt;p&gt;$ ssh -w any:any   root@remote_host&lt;/p&gt;
&lt;p&gt;のように、any:any とすれば、tun1 とか tun2 とか、ローカルリモートそれぞれで tunnel device 番号の空きの若いものから自動的に採番してくれる。&lt;/p&gt;
&lt;p&gt;こうして作成した tunX にそれぞれ適切に IP address を割り当てれば IP レベル(L3 レベル)で通信できるようになる。&lt;/p&gt;
&lt;p&gt;ところで、この仮想化の時代、L3トンネルが張れるなら、L2 トンネルも張れないのか？と思うのが、人情だと思う。Software Design の記事では、スペースの関係か触れられていないのだが、実は、以下のように ssh のオプション指定によって、tunnnel device (tunX)だけでなく、Encapsulation が Ethernet に見えるような L2 tunnel、つまり tap も作成できる。&lt;/p&gt;
&lt;p&gt;$ ssh -w any:any  -o Tunnel=ethernet  root@remote_host&lt;/p&gt;
&lt;p&gt;tap を作成する場合もやはり -w は必要で、指定値は tun の時と同じように使われる。
つまり、tap1 なり tap9 なりと（空いていれば)好きな番号の tap device を作れる。
(1/17追記)
なお、/etc/ssh/sshd_config や /etc/ssh/ssh_config に TunnelPermit や Tunnel 等の指定値が明示的に記述されていると強制的に tun になってしまうことがあるので注意のこと。&lt;/p&gt;
&lt;p&gt;さて、実はここからが本題である。
下図のようにHOST1 と HOST2 があるとして、この２台の間は、proxy なり、NATなり、(多段)port forwarding なりの何らかの手段で ssh 接続可能だとする。(多段)port forwarding については前にも書いたので参考まで。&lt;/p&gt;
&lt;p&gt;図の赤い線で結んだssh 接続の間には proxy があっても NATがあってもよい。とにかく、HOST1とHOST2の間でssh接続し、上で説明したオプションを指定して tap を接続してしまうことによって、仮想的に１枚のL2面を作れたことになる。（通信品質についてはいわずもがななので、そこはつっこまないように)&lt;/p&gt;
&lt;p&gt;さらに図のように、作成した tap をbridge で VMの仮想NICに接続してしまえば、踏み台の向こうの環境で動いているVMに対して、L2レベルで接続できるので、例えば HOST2 から HOST1 上のVMに対してDHCPでアドレスを払いだす…等といったことも可能である。
(HOST2の構成が図とはちょっと違うのだが)実際やってみたら、問題なく動くし、やろうと思えば３ノード以上でフルメッシュ構成にするのも可能である。(ループが発生しないように若干注意が必要だが...)&lt;/p&gt;
&lt;p&gt;&lt;img src ="images/ssh-l2-tunnel.png" alt="ssh-l2-tunnel.png" style="width:640px;"/&gt;&lt;/p&gt;
&lt;p&gt;世の中では、VXLAN だの STT だの NVGRE といった L2 over L3 技術や、SPB やら TRILL (やそれらの拡張)といった L2 over L2 技術で百花繚乱状態だが、こういう poor man's solution もあるよということで（笑)&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[ja] pythonからetcdを使いたい</title><link href="https://thatsdone.github.io/junkbox/python_etcd3linux_hook_systemcall_again.html" rel="alternate"></link><published>2023-09-09T21:00:00+09:00</published><updated>2023-09-09T21:00:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2023-09-09:/junkbox/python_etcd3linux_hook_systemcall_again.html</id><summary type="html">&lt;p&gt;pythonからetcdを使いたい&lt;/p&gt;</summary><content type="html">&lt;p&gt;今回は、これまでqiitaやらblogspotに記事を書いてきた記事をここに集約するシリーズではなく今年になってから気づいた話。&lt;/p&gt;
&lt;p&gt;Kubernetesの制御データを置くのにetcdを使っていることもあって、etcdをデータベースにして分散制御するというのはよくある話だと思います。&lt;/p&gt;
&lt;p&gt;Pythonの場合、&lt;a href="https://pypi.org/"&gt;Pypi&lt;/a&gt;で探してみると、元々...というか、etcd 2.x時代くらいまではこれが&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pypi &lt;a href="https://pypi.org/project/etcd/"&gt;https://pypi.org/project/etcd/&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;ソース &lt;a href="https://github.com/dsoprea/PythonEtcdClient"&gt;https://github.com/dsoprea/PythonEtcdClient&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;使われていたようですが、残念ながら(?)2014年でリリースが止まっており、現在はこちらがつかわれているようです。フルスクラッチで作り直しているようですね。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pypi &lt;a href="https://pypi.org/project/etcd3/"&gt;https://pypi.org/project/etcd3/&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;ソース &lt;a href="https://github.com/kragniz/python-etcd3/"&gt;https://github.com/kragniz/python-etcd3/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ドキュメント &lt;a href="https://python-etcd3.readthedocs.io/en/latest/"&gt;https://python-etcd3.readthedocs.io/en/latest/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pypiのページにもサンプルが載っていますが、素直で使いやすい仕様で作られているように思います。&lt;/p&gt;
&lt;p&gt;さて、私は、3ノードのetcdサーバのどれか１台が倒れても、もろもろ処理継続できる実験をしたかったのでした。&lt;/p&gt;
&lt;p&gt;それで当初は、readthedocsのmanualにある&lt;a href="https://python-etcd3.readthedocs.io/en/latest/usage.html#api"&gt;etcd3.Etcd3Clientの仕様&lt;/a&gt;を眺めながら、「あれ？3ノードにコネクション張ってFail Overさせたい時ってどうすればいいんじゃ？」とひとしきり試行錯誤の後「もしかしてサポートされてない？」とコードを読み始めたところ、
&lt;a href="https://github.com/kragniz/python-etcd3/blob/master/etcd3/client.py#L145"&gt;MultiEndpointEtcd3Client()&lt;/a&gt;を使えばいいことがわかりました。&lt;/p&gt;
&lt;p&gt;練習用に作ってみたやつ(本記事執筆時点でまだTo Be Updated)が&lt;a href="https://github.com/thatsdone/junkbox/blob/master/python/etcd3-multiclient.py"&gt;ここ&lt;/a&gt;においてありますが、以下のような感じで etcdサーバ1台ずつ Endpoint classを作った上でリストにし、&lt;code&gt;MultiEndpointEtcd3Client()&lt;/code&gt; に &lt;code&gt;endpoint=&lt;/code&gt; で渡してあげればよいようです。
最初、stringで '192.168.1.101:2379' と書いてリストにしていて動かなかったので、あれれ？と思ったのですが、やっぱりソースを眺めていて気づきました(笑)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;snip&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;39&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;eps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;[]
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;args&lt;/span&gt;.&lt;span class="nv"&gt;endpoints&lt;/span&gt;:
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ep&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;args&lt;/span&gt;.&lt;span class="nv"&gt;endpoints&lt;/span&gt;:
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nv"&gt;eps&lt;/span&gt;.&lt;span class="nv"&gt;append&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;etcd3&lt;/span&gt;.&lt;span class="nv"&gt;Endpoint&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;ep&lt;/span&gt;.&lt;span class="nv"&gt;split&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;:&amp;#39;&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;[&lt;span class="mi"&gt;0&lt;/span&gt;],&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;int&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;ep&lt;/span&gt;.&lt;span class="nv"&gt;spl&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;it&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;:&amp;#39;&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;[&lt;span class="mi"&gt;1&lt;/span&gt;]&lt;span class="ss"&gt;)&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;secure&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;False&lt;/span&gt;&lt;span class="ss"&gt;))&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;43&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;:
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;print&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Specify -e / --endpoints&amp;#39;&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;sys&lt;/span&gt;.&lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="ss"&gt;()&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;46&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;etcd3&lt;/span&gt;.&lt;span class="nv"&gt;MultiEndpointEtcd3Client&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;endpoints&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;eps&lt;/span&gt;,
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="w"&gt;                                             &lt;/span&gt;&lt;span class="nb"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;args&lt;/span&gt;.&lt;span class="nb"&gt;timeout&lt;/span&gt;,
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="w"&gt;                                             &lt;/span&gt;&lt;span class="nv"&gt;failover&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;True&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;snip&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;ちなこのライブラリ、etcdに対する単純なkey/valueのCRUDだけではなく、lock やtransactionも使えるようになっています。
便利ですね :)&lt;/p&gt;
&lt;p&gt;なお、ある意味&lt;strong&gt;これが一番重用な話&lt;/strong&gt;になりますが、現状Pypiからインストールできる最新版の 0.2.0 は2020/04/01にリリースされたもので、&lt;strong&gt;古い&lt;/strong&gt;です。
&lt;code&gt;MultiEndpointEtcd3Client()&lt;/code&gt; も含まれていません。使いたい場合は、ソースからインストールする必要があります。&lt;/p&gt;
&lt;p&gt;そろそろ次のリリース出したほうがいいんじゃないの？と&lt;a href="https://github.com/kragniz/python-etcd3/issues/2197"&gt;issue&lt;/a&gt;も切ってみて、賛同の声もほどほどあるようなのですが、さてどうなりますか...&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[ja] Linuxでsystem callをhookしたい</title><link href="https://thatsdone.github.io/junkbox/linux_hook_systemcall_again.html" rel="alternate"></link><published>2023-09-03T11:00:00+09:00</published><updated>2023-09-03T11:00:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2023-09-03:/junkbox/linux_hook_systemcall_again.html</id><summary type="html">&lt;p&gt;Linuxでsystem callをhookしたいときの注意(その2)&lt;/p&gt;</summary><content type="html">&lt;p&gt;これまでqiitaやらblogspotに記事を書いてきた記事をここに集約するシリーズ。&lt;/p&gt;
&lt;p&gt;今日は2017年にqiitaに書いた&lt;a href="https://qiita.com/thatsdone/items/23cba711af84c5b916ec"&gt;記事&lt;/a&gt;。
前にここに移植した&lt;a href="https://thatsdone.github.io/junkbox/gnu_ld_no_as_needed_and_as_needed_option.html"&gt;この記事&lt;/a&gt;の続きです。&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;イントロ&lt;/h1&gt;
&lt;p&gt;2013年の3月頃にこんな記事を書いたのを思い出したのだが、最近事情でまた動かしてみたら気づいたことがあったのでメモ。&lt;/p&gt;
&lt;p&gt;「&lt;a href="https://thatsdone.github.io/junkbox/gnu_ld_no_as_needed_and_as_needed_option.html"&gt;GNU ld の--no-as-neededと--as-neededオプションについて&lt;/a&gt;」&lt;/p&gt;
&lt;p&gt;最初によくわかっている方向けの言い訳^H^H^H説明をしておくと、上記はLD_PRELOADを使って hook を行う場合に準備する shared object を作る際に使用するリンカ(GNU ld)の挙動がUbuntu 12.04 前後で若干変更され、ld の option 指定に注意が必要になったという話だった。当時は上記記事の例に書いた通りに動いていたのだが、どうも今は少し事情が変わっているらしいという話である。&lt;/p&gt;
&lt;p&gt;まず、やりたいことはこの記事のタイトルの通りである。各種事情により、system call (やlibrary関数)の処理を入り口で横取り(hook)して動きを変えたいことがある。私がこれまで経験した中では、こんな用途があった。
以下、すべて「元のプログラムには手を加えない」という前提である。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;socket API で通信するアプリケーションを、InfiniBand のSDPプロトコルを使って、内部通信処理を横取りして高速化したい。&lt;/li&gt;
&lt;li&gt;アプリケーションが作成するTCPコネクションのオプションを、接続先によって変更したい。&lt;/li&gt;
&lt;li&gt;外部から提供されたライブラリの挙動に問題があることがわかったが、ソースがないため改修することもできない。問題を起こす関数の処理を横取りして正しいものに差し換えたい。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;このような場合、後述するようなshared object (拡張子が .so なファイル。動的リンクライブラリと呼ばれることもある)を作っておいて、プログラム実行時に環境変数 LD_PRELOAD で指定してやると、やりたいことを実現できる。&lt;/p&gt;
&lt;p&gt;文章で説明してもわかりにくいと思うので、絵を描いてみた。
以下の図の左側のように動いていたプログラム(application1)の動きを、実行時に右側のように変えるということである。&lt;/p&gt;
&lt;p&gt;&lt;img src ="images/LD_PRELOAD1.png" alt="LD_PRELOAD1.png" style="width:640px;"/&gt;&lt;/p&gt;
&lt;p&gt;上図のapplication1 は見ての通り、libFOOBAR.so というライブラリ(shared object)の中の funcA()という関数を使う。(実際のところ、libc.so でもかまわない) やりたいのは、図の右のように、application1 のfuncA()呼び出しを HOOK.so の中の funcA()にすり替え、HOOK.so 版の funcA()の中から前後に必要な処理を行った上で元々の libFOOBAR.so 版の funcA()を呼び出すということである。&lt;/p&gt;
&lt;h1&gt;hook用shared objectの実際の処理&lt;/h1&gt;
&lt;p&gt;以下、shared object (上図では HOOK.so)でどんなことをするのか説明する。&lt;/p&gt;
&lt;h2&gt;構造&lt;/h2&gt;
&lt;p&gt;hook用shared objectは、大きく以下の3つの要素から構成される。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;初期化ルーチン(constructor)&lt;/li&gt;
&lt;li&gt;hook関数&lt;/li&gt;
&lt;li&gt;終了ルーチン(destructor)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;初期化ルーチン(constructor)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;main() 関数が呼ばれる前に実行される。&lt;/li&gt;
&lt;li&gt;hook関数で使うために横取り対象関数のポインタを検索して保存しておくことが多い。&lt;/li&gt;
&lt;li&gt;検索には、dynamic link loader の dlsym() を使う。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;hook関数&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;横取りした後の処理を記述する。&lt;/li&gt;
&lt;li&gt;横取りする関数とまったく同じ名前と型定義で記述する。&lt;/li&gt;
&lt;li&gt;適当な前処理を行った後で、前述の初期化ルーチンで保存しておいた関数ポインタを使って再び元の関数を呼び出す使い方が多い。たとえば、kernel に渡す前に適当な小細工をしたい場合や、条件に合致しない場合の fallback ルートとしての役割である。図は、このパターンの例である。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;終了ルーチン(destructor)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;main() 関数からreturn (or exit) した後に実行される。&lt;/li&gt;
&lt;li&gt;初期化ルーチンやhook関数で確保した資源の解放など。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;ビルド方法&lt;/h2&gt;
&lt;p&gt;通常の単独実行可能なプログラムとは違い、shared object を作るためのリンカ・オプションを使う。
こんな感じである。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;gcc&lt;span class="w"&gt;  &lt;/span&gt;-Wall&lt;span class="w"&gt; &lt;/span&gt;-D_GNU_SOURCE&lt;span class="w"&gt; &lt;/span&gt;-fPIC&lt;span class="w"&gt;  &lt;/span&gt;-Wl,&lt;span class="s1"&gt;&amp;#39;--no-as-needed&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-shared&lt;span class="w"&gt; &lt;/span&gt;-ldl&lt;span class="w"&gt; &lt;/span&gt;hook.c&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;hook.so
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://thatsdone.github.io/junkbox/gnu_ld_no_as_needed_and_as_needed_option.html"&gt;前の記事&lt;/a&gt;のポイントは、
1. &lt;code&gt;--no-as-needed&lt;/code&gt; というオプションが必要になったこと。
2. &lt;code&gt;-ldl``` オプションは&lt;/code&gt;--no-as-needed` の後ろになければならないこと。
の2点だった。&lt;/p&gt;
&lt;h2&gt;プログラム例&lt;/h2&gt;
&lt;p&gt;サンプルは以下にあるものをみてほしい。&lt;/p&gt;
&lt;p&gt;https://github.com/thatsdone/junkbox/tree/master/c/hook&lt;/p&gt;
&lt;p&gt;write(2)をhookして、本物の write(2)を呼ぶ前に適当なバナーを出しているだけなことがわかると思う。&lt;/p&gt;
&lt;h2&gt;使い方/実行例&lt;/h2&gt;
&lt;p&gt;プログラム実行時に、今作ったhook用のshared objectを LD_PRELOAD で指定して実行してやる。
こんな感じである。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;xenial0&lt;/span&gt;&lt;span class="o"&gt;:~/&lt;/span&gt;&lt;span class="n"&gt;hook$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;call_write&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;fcntl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;unistd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hello, World!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;xenial0&lt;/span&gt;&lt;span class="o"&gt;:~/&lt;/span&gt;&lt;span class="n"&gt;hook$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LD_PRELOAD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;hook&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;so&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;call_write&lt;/span&gt;
&lt;span class="nl"&gt;init_hook&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;constructor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;called&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x7f903d9ca6d0&lt;/span&gt;
&lt;span class="nl"&gt;write&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hook&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="n"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;World&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="nl"&gt;fini_hook&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;destructor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;called&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;xenial0&lt;/span&gt;&lt;span class="o"&gt;:~/&lt;/span&gt;&lt;span class="n"&gt;hook$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;"Hello, World!" の前に "write: hook!" というバナーが出ているのがわかる。&lt;/p&gt;
&lt;h1&gt;現在ではどうか？&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://thatsdone.github.io/junkbox/gnu_ld_no_as_needed_and_as_needed_option.html"&gt;上述の記事&lt;/a&gt;では、/bin/ls に hook.so を使い、ls の結果にヘッダを出す例を書いた。
しかし、最近また動かしてみたところ、少なくとも Ubuntu Xenial の /bin/ls では write(2)をhookできないことがわかった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;xenial0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~/&lt;/span&gt;&lt;span class="n"&gt;hook&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ls&lt;/span&gt;
&lt;span class="n"&gt;call_syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;call_write&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;hook&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;hook&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;so&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;call_syscall&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;
&lt;span class="n"&gt;call_write&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;hook2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;Makefile&lt;/span&gt;

&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;xenial0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~/&lt;/span&gt;&lt;span class="n"&gt;hook&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LD_PRELOAD&lt;/span&gt;&lt;span class="o"&gt;=./&lt;/span&gt;&lt;span class="n"&gt;hook&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;so&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ls&lt;/span&gt;
&lt;span class="n"&gt;init_hook&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;constructor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;called&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x7f4bdece36d0&lt;/span&gt;
&lt;span class="n"&gt;call_syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;call_write&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;hook&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;hook&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;so&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;call_syscall&lt;/span&gt;
&lt;span class="n"&gt;call_write&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;hook2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;Makefile&lt;/span&gt;
&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;xenial0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~/&lt;/span&gt;&lt;span class="n"&gt;hook&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;"init_hook: constructor called! ...." の後にもう1行バナーが出るはずなのだがおかしい。
実際、strace してみると、確かにwrite(2)が呼ばれているではないか...なんで？&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="nv"&gt;@xenial0&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~/&lt;/span&gt;&lt;span class="n"&gt;hook&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;strace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ewrite&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ls&lt;/span&gt;
&lt;span class="k"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;call_syscall\tcall_write    hook2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;...,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="n"&gt;call_syscall&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;call_write&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;hook2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;hook&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;so&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;44&lt;/span&gt;
&lt;span class="k"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;call_syscall.c\tcall_write.c  hoo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;...,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="n"&gt;call_syscall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;call_write&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;hook&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;Makefile&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;47&lt;/span&gt;
&lt;span class="o"&gt;+++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;exited&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+++&lt;/span&gt;
&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="nv"&gt;@xenial0&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~/&lt;/span&gt;&lt;span class="n"&gt;hook&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;...というわけで、ちょっと調べてみた結果が以下である。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;/bin/ls は、write(2)を直接使わず、fwrite(3)を使う。&lt;/li&gt;
&lt;li&gt;fwrite(3)は、write(2)を直接使わず、syscall(2)を使う!?&lt;/li&gt;
&lt;li&gt;strace は syscall(SYS_write,...) とやった場合も write(2)を呼んだと表示する。&lt;/li&gt;
&lt;li&gt;この方法で syscall(2)もhookできる。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;余談があと2つある。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;上のlsの例ではdestructor が出すメッセージが出ていない。
実はこれは&lt;a href="https://thatsdone.github.io/junkbox/gnu_ld_no_as_needed_and_as_needed_option.html"&gt;前の記事&lt;/a&gt;を書いたときから問題なのだったorz
真相は、strace してみるとわかるが、ls の main() 関数が return (or exit) する前に標準出力(fd=1)をclose(2)しているからである。&lt;/li&gt;
&lt;li&gt;サンプルの hook.c は printf(3) を使っているので、この中で write(2)が呼ばれて、write(2)のhookが2回出るはずなのではないか？と思うかもしれない。fwrite(3)と同じようにsyscall(2)が使われている可能性もあるが、write(2)が使われていたとしても、printf(3)とwrite(2)は同じバイナリ(libc.so)にふくまれており、既に参照先が解決されているため、LD_PRELOADの枠組みでは横取りできないのである。(systemtap みたいなことをすれば話は別)&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;まとめ&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;バイナリをいじらずに system call やライブラリ関数の呼び出しを hook することができる。&lt;/li&gt;
&lt;li&gt;作法にのっとった shared object を作っておいてプログラム実行時に環境変数 LD_PRELOAD で指定してやる(昔からある)方法は、今でも有効。&lt;/li&gt;
&lt;li&gt;しかし限界もある上に、バイナリ側の実装が変わるとうまく動かないこともあるので注意が必要。&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;links&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;拙作のサンプル&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/thatsdone/junkbox/tree/master/c/hook"&gt;https://github.com/thatsdone/junkbox/tree/master/c/hook&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Hacker News で見つけた、若干空中戦気味の議論(笑)&lt;ul&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=2973221"&gt;https://news.ycombinator.com/item?id=2973221&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;本稿と類似の記事(英語)&lt;ul&gt;
&lt;li&gt;&lt;a href="http://samanbarghi.com/blog/2014/09/05/how-to-wrap-a-system-call-libc-function-in-linux/"&gt;http://samanbarghi.com/blog/2014/09/05/how-to-wrap-a-system-call-libc-function-in-linux/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rafalcieslak.wordpress.com/2013/04/02/dynamic-linker-tricks-using-ld_preload-to-cheat-inject-features-and-investigate-programs/"&gt;https://rafalcieslak.wordpress.com/2013/04/02/dynamic-linker-tricks-using-ld_preload-to-cheat-inject-features-and-investigate-programs/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;masami256 さんによる system call を kernel 側で置き換える話&lt;ul&gt;
&lt;li&gt;&lt;a href="http://kernhack.hatenablog.com/entry/2014/12/05/000346"&gt;http://kernhack.hatenablog.com/entry/2014/12/05/000346&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;syscall(2)のマニュアル&lt;ul&gt;
&lt;li&gt;&lt;a href="http://man7.org/linux/man-pages/man2/syscall.2.html"&gt;http://man7.org/linux/man-pages/man2/syscall.2.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</content><category term="tech"></category></entry><entry><title>[ja] なんちゃってPrometheus ExporterでGPU利用率を採取する</title><link href="https://thatsdone.github.io/junkbox/simple_prometheus_exporter.html" rel="alternate"></link><published>2023-09-02T20:30:00+09:00</published><updated>2023-09-02T20:30:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2023-09-02:/junkbox/simple_prometheus_exporter.html</id><summary type="html">&lt;p&gt;なんちゃってPrometheus ExporterでGPU利用率を採取する&lt;/p&gt;</summary><content type="html">&lt;p&gt;今回はだいぶ前に作ったものの話。&lt;/p&gt;
&lt;p&gt;話は2020年にさかのぼります。
当時、vSphereで動くGPU関連製品を使った検証をしていました。
GPUはNVIDIA製ですが、検証対象の製品自体は独立系のものでした。&lt;/p&gt;
&lt;p&gt;CPU等の他のmetricsについてはPrometheusで一元収集していたので、自然な流れで当該GPUの利用率もPrometheusで収集できないのかと思いました。…が、独自仕様の製品を買ってくれと言われ、しかもいいお値段だったので、それなら自分で作ればいいじゃんと考えたのでした(笑)&lt;/p&gt;
&lt;p&gt;まず、その製品はESXi Shell上でnvidia-smiが使えるようになっていました。&lt;/p&gt;
&lt;p&gt;よく知られているように、nvidia-smiを内部から呼び出してGPUのmetricsを返すExporterは複数存在し、私は&lt;a href="https://github.com/chhibber/pgme"&gt;PGME&lt;/a&gt;を使っていました。
PGMEは、一般的なPrometheus Exporterと同様にGo言語で書かれており、GoのバイナリということはもしかしたらESXi Shellで動くか？と思って動かしてみたらSEGVしてしまいました...orz&lt;/p&gt;
&lt;p&gt;さて、どうするか？&lt;/p&gt;
&lt;p&gt;ESXi ShellはミニマムなLinux Distributionなわけで、確認したところ Python3 も入っていました。&lt;/p&gt;
&lt;p&gt;また、Python には標準で &lt;a href="https://docs.python.org/3/library/http.server.html"&gt;http.server&lt;/a&gt;がついてきます。&lt;/p&gt;
&lt;p&gt;…ということは、PGMEと同等の処理処理を、http.serverのGET method処理ルーチンで動かしてやればいいじゃん…と思い至って作ってみたものが以下においてあります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/thatsdone/PyPGME"&gt;https://github.com/thatsdone/PyPGME&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;眺めるとわかるのですが、do_GET() の中で nvidia-smi を呼び出し、結果をparseして、PGME互換のmetricsに整形して返しているだけです。&lt;/p&gt;
&lt;p&gt;なお、起動引数はこんな感じで&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;'-p' : Listen port (default: 19101)&lt;/li&gt;
&lt;li&gt;'-b' : Bind address (default: 0.0.0.0)&lt;/li&gt;
&lt;li&gt;'-e' : Extended Attribute&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最後の'-e'は、オリジナルのPGMEには存在しません。後述のmetrics採取例のように、電力関連の pgme_power_draw と pgme_power_limit を追加出力できるように(後から)しました。&lt;/p&gt;
&lt;p&gt;他の目的のPrometheus Exporterが欲しくなった時のひな形としても使えるので、けっこう重宝しています(笑)&lt;/p&gt;
&lt;p&gt;metrics採取例(IPはダミー、PyPGME.py 起動時には -p 9101と -e を指定)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;http://192.168.1.1:9101/metrics
&lt;span class="c1"&gt;# TYPE temperature_gpu gauge&lt;/span&gt;
&lt;span class="c1"&gt;# HELP temperature.gpu of nvidia-smi&lt;/span&gt;
temperature_gpu&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;gpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Tesla P100-PCIE-16GB[0]&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt;
&lt;span class="c1"&gt;# TYPE utilization_gpu gauge&lt;/span&gt;
&lt;span class="c1"&gt;# HELP utilization.gpu of nvidia-smi&lt;/span&gt;
utilization_gpu&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;gpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Tesla P100-PCIE-16GB[0]&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="c1"&gt;# TYPE utilization_memory gauge&lt;/span&gt;
&lt;span class="c1"&gt;# HELP utilization.memory of nvidia-smi&lt;/span&gt;
utilization_memory&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;gpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Tesla P100-PCIE-16GB[0]&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="c1"&gt;# TYPE memory_total gauge&lt;/span&gt;
&lt;span class="c1"&gt;# HELP memory.total of nvidia-smi&lt;/span&gt;
memory_total&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;gpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Tesla P100-PCIE-16GB[0]&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16384&lt;/span&gt;
&lt;span class="c1"&gt;# TYPE memory_free gauge&lt;/span&gt;
&lt;span class="c1"&gt;# HELP memory.free of nvidia-smi&lt;/span&gt;
memory_free&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;gpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Tesla P100-PCIE-16GB[0]&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16280&lt;/span&gt;
&lt;span class="c1"&gt;# TYPE memory_used gauge&lt;/span&gt;
&lt;span class="c1"&gt;# HELP memory.used of nvidia-smi&lt;/span&gt;
memory_used&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;gpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Tesla P100-PCIE-16GB[0]&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="c1"&gt;# TYPE pgme_power_draw gauge&lt;/span&gt;
&lt;span class="c1"&gt;# HELP power.draw of nvidia-smi&lt;/span&gt;
pgme_power_draw&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;gpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Tesla P100-PCIE-16GB[0]&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;25&lt;/span&gt;.63
&lt;span class="c1"&gt;# TYPE pgme_power_limit gauge&lt;/span&gt;
&lt;span class="c1"&gt;# HELP power.limit of nvidia-smi&lt;/span&gt;
pgme_power_limit&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;gpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Tesla P100-PCIE-16GB[0]&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;250&lt;/span&gt;.00
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;GPUが2023年にもなってP100なのは愛嬌ということで(笑)&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[ja] GNU ld の--no-as-neededと--as-neededオプションについて</title><link href="https://thatsdone.github.io/junkbox/gnu_ld_no_as_needed_and_as_needed_option.html" rel="alternate"></link><published>2023-08-30T17:20:00+09:00</published><updated>2023-08-30T17:20:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2023-08-30:/junkbox/gnu_ld_no_as_needed_and_as_needed_option.html</id><summary type="html">&lt;p&gt;Linuxでsystem callをhookしたいときの注意&lt;/p&gt;</summary><content type="html">&lt;p&gt;これまでqiitaやらblogspotに記事を書いてきた記事をここに集約するシリーズ。&lt;/p&gt;
&lt;p&gt;今日は2013年(!?)にqiitaに書いた&lt;a href="http://thatsdone-j.blogspot.jp/2013/03/gnu-ld-as-needed-and-no-as-needed.html"&gt;記事&lt;/a&gt;になります。
これには続きがあるのですが、また別途。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;GNU ld の挙動で気が付いたことがあったのでメモ。&lt;/p&gt;
&lt;p&gt;例によって少し前置きが長くなるが、端的にいえば、system call 等の他人が提供する関数呼び出しをフックして、処理を横取りしたくなることがたまにある。&lt;/p&gt;
&lt;p&gt;例えば、system call の write(2) をフックしたいなら、以下のようなプログラムを書くことになる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#include &amp;lt;dlfcn.h&amp;gt;  /* これが必要 */&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#include &amp;lt;unistd.h&amp;gt; /* 今回hookしたい write(2)が定義されている */&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#include &amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#include &amp;lt;errno.h&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;↓&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hook&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;したい関数、この場合は&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;と同じようにする。&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ssize_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nb nb-Type"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb nb-Type"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;↓&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="err"&gt;実行の前に呼ばれる初期化ルーチン&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__attribute__&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb nb-Type"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;init_hook&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ssize_t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nb nb-Type"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb nb-Type"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;size_t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="n"&gt;dlsym&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RTLD_NEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;write&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;: constructor called! %p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__func__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;↓&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="err"&gt;から抜けた後に呼ばれる終了ルーチン&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__attribute__&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;destructor&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb nb-Type"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fini_hook&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;: destructor called!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__func__&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;↓&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;の処理を横取りするルーチン&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ssize_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb nb-Type"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb nb-Type"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb nb-Type"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;/*&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;like&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;here&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;: hook!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__func__&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb nb-Type"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;/*&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;like&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;here&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;これを、hook.c として保存しておき、hook.so という名前の shared object を作成する。この際、初期化ルーチンの中で、オリジナルの write(2)のエントリを探すのに使っている dlsym(3)のために、-ldl オプション(と -D_GNU_SOURCE)が必要になる。&lt;/p&gt;
&lt;p&gt;$gcc  -D_GNU_SOURCE  -fPIC -shared -ldl hook.c -o hook.so&lt;/p&gt;
&lt;p&gt;ぐぐると日本語の解説もいくつか出てくるので参照してほしいのだが、上記のようにして shared object 作り、プログラムの実行時に LD_PRELOAD 環境変数で読み混ませてやれば目的を達することができる。&lt;/p&gt;
&lt;p&gt;…はずだった。これまでは。&lt;/p&gt;
&lt;p&gt;しかし、上記を(少なくとも) Ubuntu 12.10 上で作成して、実行してみると&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;  $ env LD_PRELOAD=./hook.so cat /tmp/foo
  cat: symbol lookup error: ./hook.so: undefined symbol: dlsym
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;…と、エラーになってしまう。
オリジナルの write(2)を探すのに使っていて、-ldl でちゃんと指定しているはずの dlsym()が見つからないとか言っている。&lt;/p&gt;
&lt;p&gt;なんで？
…ということで確認してみると、当然リンクされているはずの libdl.so がリンクされていない！&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;  $ ldd hook.so
          linux-vdso.so.1 =&amp;gt;  (0x00007fff8edba000)
          libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007f06d3745000)
          /lib64/ld-linux-x86-64.so.2 (0x00007f06d3d1a000)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;どういうことなの？
…と、ぐぐっていて出てきた以下のトピックを読んで初めて知ったのだが、&lt;/p&gt;
&lt;p&gt;http://os.inf.tu-dresden.de/pipermail/l4-hackers/2011/005078.html&lt;/p&gt;
&lt;p&gt;実は、少なくとも現行の Ubuntu ではリンカ (GNU ld) の挙動が変更されており、以下のように、--no-as-needed というオプションを指定しないといけないことが分かった。
（脱線するが、L4のMLって、まだ普通に生きているのだなぁ...と、遠い目になったのはひみつ）&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;  $ gcc -D_GNU_SOURCE -Wl,&amp;#39;--no-as-needed&amp;#39; -fPIC -shared -ldl hook.c -o hook.so
  $ ldd hook.so
          linux-vdso.so.1 =&amp;gt;  (0x00007fff5494d000)
          libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f2d72be2000)
          libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2d72823000)
          /lib64/ld-linux-x86-64.so.2 (0x00007f2d72ffc000)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;赤字部分のように、今度は意図の通り、リンクされている。&lt;/p&gt;
&lt;p&gt;現行のデフォルトの挙動は'--no-as-needed'の逆の'--as-needed'で、これは、リンカ(ld)に -ldl 等と渡された shared object の一覧の中から、プログラムの中で実際に使われているシンボルが入っている shared object のみ実際にリンクするという意味になるようだ。&lt;/p&gt;
&lt;p&gt;でも、ちゃんと使っているじゃん？…と思うかもしれない。
これについては、ソースレベルでは(まだ)未確認なのだが、今回の場合は、_init ルーチンの中で dlsym() を使っており、'--as-needed' の場合に探索される範囲から外れているから…というのが真相らしい。&lt;/p&gt;
&lt;p&gt;さて、ここでもうひとつ注意がある。'--no-as-needed' をコマンドラインのどの順番で指定するかには意味がある。この例では -ldl の前に指定する必要がある。
実際、-ldl の後ろに指定して shared object を作ってみると&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;  $ gcc  -g -Wall -D_GNU_SOURCE -fPIC -shared -ldl -Wl,&amp;#39;--no-as-needed&amp;#39; hook.c -o hook.so
  $ ldd hook.so
          linux-vdso.so.1 =&amp;gt;  (0x00007fffea666000)
          libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb722dc8000)
          /lib64/ld-linux-x86-64.so.2 (0x00007fb72339d000)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;の通り、また libdl.so がリンクされなってしまうので注意のこと。&lt;/p&gt;
&lt;p&gt;ちなみに、以下は man ld からの引用なのだが、赤字のところが　--no-as-neededの場合は逆になる…ということのようだ。
そんなの気がつかねーよ...orz&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;LD(1)                        GNU Development Tools                       LD(1)

NAME
       ld - The GNU linker

SYNOPSIS
       ld [options] objfile ...

DESCRIPTION
  (snip)
       --as-needed
       --no-as-needed
           This option affects ELF DT_NEEDED tags for dynamic libraries
           mentioned on the command line after the --as-needed option.
           Normally the linker will add a DT_NEEDED tag for each dynamic
           library mentioned on the command line, regardless of whether the
           library is actually needed or not.  --as-needed causes a DT_NEEDED
           tag to only be emitted for a library that satisfies an undefined
           symbol reference from a regular object file or, if the library is
           not found in the DT_NEEDED lists of other libraries linked up to
           that point, an undefined symbol reference from another dynamic
           library.  --no-as-needed restores the default behaviour.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;最後に、今回作った hook.so を実際に使ってみるとどうなるかも載せておく。&lt;/p&gt;
&lt;p&gt;write(2) を使うできるだけ単純なプログラムということで、cat を使って&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;/tmp/bar
FOO
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;というファイルを表示してみると、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;env&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;LD_PRELOAD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./hook.so&lt;span class="w"&gt;  &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;/tmp/bar
init_hook:&lt;span class="w"&gt; &lt;/span&gt;constructor&lt;span class="w"&gt; &lt;/span&gt;called!&lt;span class="w"&gt; &lt;/span&gt;0x7fd48f0228f0
write:&lt;span class="w"&gt; &lt;/span&gt;hook!
FOO

$
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;ということで、冒頭のサンプルに書いてある通り、実際の write(2)が走る前に "write: hook!" と自分で追加した処理が実行されていることがわかる。&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[ja] MySQL版pgbenchについて</title><link href="https://thatsdone.github.io/junkbox/pgbench_for_mysql.html" rel="alternate"></link><published>2023-08-27T17:00:00+09:00</published><updated>2023-08-27T17:00:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2023-08-27:/junkbox/pgbench_for_mysql.html</id><summary type="html">&lt;p&gt;MySQL版pgbenchについて&lt;/p&gt;</summary><content type="html">&lt;p&gt;これまでqiitaやらblogspotに記事を書いてきた記事をここに集約するシリーズ。&lt;/p&gt;
&lt;p&gt;今日は2017年にqiitaに書いた&lt;a href="https://qiita.com/thatsdone/items/78eeeb31f567ce6c05b0"&gt;記事&lt;/a&gt;から。&lt;/p&gt;
&lt;p&gt;とはいえ、2013年2月(10年以上前！)に書いた記事の残TODOの自分へのリマインドなので、そんなに沈めていたのか…と目が遠くなります。(苦笑)&lt;/p&gt;
&lt;p&gt;MySQL版のpgbench(ざっくり、TPC-B likeなコンパクトなベンチマーク)って、需要はありそうな気もするのですが、そうでもないんですかねぇ。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;(これは、自分にプレッシャーをかけるためのメモです)&lt;/p&gt;
&lt;p&gt;2013年の2月にこんな記事を書いたのを思い出した。&lt;/p&gt;
&lt;p&gt;「&lt;a href="https://thatsdone-j.blogspot.jp/2013/02/mysql-pgbench.html"&gt;MySQL版の pgbench ってないの？&lt;/a&gt;」&lt;/p&gt;
&lt;p&gt;当時、MySQLに軽く負荷をかけてみる必要が発生し、sysbench 付属のアレだともともとSQLレベルのdeadlockが発生する性質のものなので、当時やりたかったことには使えず、PostgreSQLのpgbenchみたいなお手軽なやつがないかなー…と思って探したら MySQLユーザー会の有志の方が昔(2004年!?)移植したものを発見し、2013年当時でも1行手直しするだけで動いたという話だった。&lt;/p&gt;
&lt;p&gt;そして、続編がこれである。&lt;/p&gt;
&lt;p&gt;「&lt;a href="https://thatsdone-j.blogspot.jp/2013/03/python-mysqlbench.html"&gt;python 版 mysqlbench&lt;/a&gt;」&lt;/p&gt;
&lt;p&gt;これは、当時 python の修行がてら上記の MySQL版pgbench(言語はC言語)を Python に移植しようと思ったのだった。&lt;/p&gt;
&lt;p&gt;実は、上記がおいてある git repository には、さらに sqlalchemy を使って移植し(ようとし)たものも置いてあったりする。&lt;/p&gt;
&lt;p&gt;仕掛中のまま放り出してあったのだが、この際ちゃんとまとめようよ &amp;gt; 自分&lt;/p&gt;
&lt;p&gt;…というわけで、逃げられなくなった...w&lt;/p&gt;
&lt;p&gt;(オチは(まだ)ありません(笑))&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[ja] OpenStack Nova のスケジューラを作ってみた (NumProjectsFilter)</title><link href="https://thatsdone.github.io/junkbox/openstack_nova_scheduler.html" rel="alternate"></link><published>2023-08-23T23:59:00+09:00</published><updated>2023-08-23T23:59:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2023-08-23:/junkbox/openstack_nova_scheduler.html</id><summary type="html">&lt;p&gt;自前OpenStack Novaのschedulerの作り方のサンプル&lt;/p&gt;</summary><content type="html">&lt;p&gt;これまで、qiitaやらblogspotに記事を書いてきたのですが、ここに集約しておこうと思います。&lt;/p&gt;
&lt;p&gt;まず、2017年にqiitaに書いた&lt;a href="https://qiita.com/thatsdone/items/9ee090577f3e11ff4f26"&gt;記事&lt;/a&gt;です。
ネタとしてはそのまま今でも使えると思います。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;今年の9月の話なので、もうだいぶ前の話になるのだが、そういえば OpenStack Nova のスケジューラを作ってみたので、記録として残しておきたい。&lt;/p&gt;
&lt;p&gt;(この記事はOpenStack Advent Calendar 2017参加エントリ...ではありません(笑))&lt;/p&gt;
&lt;h1&gt;発端&lt;/h1&gt;
&lt;p&gt;発端は某所でこんな議論をしていたことだった。
OpenStackでつくった基盤があって、その上にいろいろサービスを収容するのだが、運用を真面目に考えていると、当然何かの故障時に影響をどれだけ抑え込めるかも検討することになる。&lt;/p&gt;
&lt;p&gt;まず、「サービス」の運営主体というものを考えてみると、管理会計上も組織編制上も独立になっていることが多い。この主体を、OpenStack の Project にマッピングするのはとても自然な考え方だと思う。&lt;/p&gt;
&lt;p&gt;ここで、「故障」の話に戻る。
この時の議論では、compute が 1 台故障で落ちた時に「影響を受けるサービスの数」に制約をつけられないか？というのが発端だった。この記事を読むような人はよく承知の通り、OpenStack Nova では以下の公式ドキュメントにあるように、様々な FilterScheduler が提供されている。これらをくみあわせればなんとかならないだろうかと、考えた&lt;/p&gt;
&lt;p&gt;&lt;a href="https://docs.openstack.org/nova/pike/user/filter-scheduler.html"&gt;https://docs.openstack.org/nova/pike/user/filter-scheduler.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;...のだが、NumInstancesFilter のように、ある compute (あるいは host aggregate)の上で作成可能なVM数に制約をつけるFilterはあっても、「ある compute の上でVMを作成可能な Project (にマッピングされたサービス)の数に制約をつける」ことはできないのだった。(実はうまい組み合わせがあって、見落としているだけなのかもしれないが、当時同僚と考えた検討した結果は「無理じゃね？」だった)&lt;/p&gt;
&lt;p&gt;そういうわけで、「ないなら作ってみればいいじゃん」と思った結果がここに置いてある。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/openstack/nova/compare/master...thatsdone:feature/num-prj-filter"&gt;https://github.com/openstack/nova/compare/master...thatsdone:feature/num-prj-filter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;以下、仕様、設計と実装について説明する。&lt;/p&gt;
&lt;h1&gt;仕様&lt;/h1&gt;
&lt;p&gt;以下のパラメータを追加した。&lt;/p&gt;
&lt;h2&gt;max_projects_per_host&lt;/h2&gt;
&lt;p&gt;意味は「computeノードあたりのVM作成可能プロジェクト数の上限」である。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;nova.conf に指定して、システム全体で一意に指定する方法と、&lt;/li&gt;
&lt;li&gt;host_aggregate の metadata に指定して aggregate 単位で指定する方法&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;を用意した。デフォルトは50(projects)とし、普通の運用では不用意にこのFilterが有効になってしまっていても無視できるくらい大きくした。&lt;/p&gt;
&lt;h1&gt;設計と実装&lt;/h1&gt;
&lt;p&gt;設計自体は、実は公式ドキュメントに "Writing Your Own Filter" というセクションがあるくらいで、 &lt;/p&gt;
&lt;p&gt;&lt;a href="https://docs.openstack.org/nova/pike/user/filter-scheduler.html#writing-your-own-filter"&gt;https://docs.openstack.org/nova/pike/user/filter-scheduler.html#writing-your-own-filter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;インターフェースははっきりしており、特に難しいことはない。
敢えて言えば、中から使う機能のI/Fだろうか。特に、DBから情報をひっぱってくる場合にどのDB APIを使うべきなのか、類似コードを探しながら検討を行った。&lt;/p&gt;
&lt;p&gt;実装だが、仕様が NumInstancesFilter ととても近いため、num_instances_filter.pyをベースにした。しかも、(練習用という意味あいもあったので...という言い訳)比較的 Naive な作りである。(笑)
規模としても、既存ファイルの修正が1つ（パラメータ処理部分）と、新規ファイルが2つ(このFilterの実装本体とテストコード)だけである。&lt;/p&gt;
&lt;p&gt;以下、本体部分を見てみよう。&lt;/p&gt;
&lt;p&gt;FilterSchedulerの場合、以下にある &lt;code&gt;host_passes()&lt;/code&gt; というメソッドが、今、選択対象候補になっているホストごとに呼び出され、各Filterのcriteriaに基づいて True (VM配置可能)またはFalse(VM配置不可能)を返すようになっている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;host_passes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;host_state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;spec_obj&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;max_projects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_get_max_projects_per_host&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host_state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;spec_obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;DEBUG: NumProjects filter called. &amp;quot;&lt;/span&gt;
                  &lt;span class="s2"&gt;&amp;quot;spec_obj=&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39; host_state=&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;spec_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;host_state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;DEBUG: host_state.host=&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39; project_id=&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="n"&gt;host_state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;spec_obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_admin_context&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;host&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;host_state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;deleted&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;instances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InstanceList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_by_filters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;まず、ここで指定されたホスト上で実行中のVMの一覧を取り出している。
実は、必要なのは project_id の一覧の集合だけなのだが、あまり低いレベルのDB APIを呼ぶのもよろしくないので、ここではオーバーヘッドは承知で上記のI/Fを使っている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;DEBUG: instances=&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;projects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;DEBUG: uuid=&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39;, project_id=&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;uuid&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;project_id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="n"&gt;projects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;project_id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;次に、さきほど得られたVM一覧から project_id を取り出し、set 型にの変数に格納している。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;spec_obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;project_id&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# FIXME(thatsdone):&lt;/span&gt;
            &lt;span class="c1"&gt;# This &amp;#39;True&amp;#39; allows to run multiple VMs on a sigle host.&lt;/span&gt;
            &lt;span class="n"&gt;passes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;max_projects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;passes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;passes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;最後に、
1. 要求元のユーザの project_id が、今つくった set 型の変数の中にあれば通過
2. なければ、VM実行中のproject数が閾値を超えているかチェック
という順番で判定を行っている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;passes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%(host_state)s&lt;/span&gt;&lt;span class="s2"&gt; fails num_projects check: &amp;quot;&lt;/span&gt;
                      &lt;span class="s2"&gt;&amp;quot;Max projects per host is set to &lt;/span&gt;&lt;span class="si"&gt;%(max_projects)s&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;host_state&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;host_state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="s1"&gt;&amp;#39;max_projects&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;max_projects&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;passes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;これだけである。&lt;/p&gt;
&lt;p&gt;新機能追加も、この程度であればたいして難しくないというのがわかると思う。&lt;/p&gt;
&lt;h2&gt;課題&lt;/h2&gt;
&lt;p&gt;この実装で、一応やりたいことは実現できる。ただし、いくつか問題も抱えているので記しておく。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;DBアクセスの負荷への影響&lt;ul&gt;
&lt;li&gt;ホストごとに、Instance 型でVM一覧を取り出していること&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;あるホストで、1つのプロジェクトのVMが2つ以上実行されうる&lt;ul&gt;
&lt;li&gt;あるサービスへの影響も最小化したいというのは自然な要求だからである。ただしこれは、他のFilterで解決すべき問題かもしれない。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;これをどうするのか？&lt;/h1&gt;
&lt;p&gt;もろもろの背景事情もあり、今のところは upstream に提案するつもりはない。
...が、英語で記事くらい書いてみてもいいかもしれない。&lt;/p&gt;
&lt;h1&gt;まとめ&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;OpenStack Nova の FilterScheduler に新しいFilterを追加する例を紹介した。&lt;/li&gt;
&lt;li&gt;仕様を決めるにあたって、どういう motivation だったのかを説明した。&lt;/li&gt;
&lt;li&gt;まあ私もなんとなく生きていますよ...ということで(笑)&lt;/li&gt;
&lt;li&gt;Happy Hacking!!&lt;/li&gt;
&lt;/ul&gt;</content><category term="tech"></category></entry><entry><title>[ja] Variations of Merry Christmas, Mr. Lawrence (Forbidden Colours)</title><link href="https://thatsdone.github.io/junkbox/merry_christmas_mr_lawrence.html" rel="alternate"></link><published>2022-06-19T23:59:00+09:00</published><updated>2022-06-19T23:59:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2022-06-19:/junkbox/merry_christmas_mr_lawrence.html</id><summary type="html">&lt;p&gt;Merry Christmas, Mr. Lawrence / Forbidden Colours&lt;/p&gt;</summary><content type="html">&lt;p&gt;実は「戦場のメリークリスマス」、ロケをやっていた頃にNHK FMで「サウンドストリート」という
番組がありました。当時、坂本龍一も担当曜日があったのですが、現地のラロトンガ島から製作・作曲現場の
生の雰囲気を伝えてくれていたのでした。&lt;/p&gt;
&lt;p&gt;あの頃から大好きです。&lt;/p&gt;
&lt;p&gt;さて、この曲、いろんな人がカバー、演奏しているわけですが、気に入ったものの一覧を書き出してみました。
(断続的に更新しています)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;オリジナル -- 坂本龍一 &amp;amp; David Sylvian&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=4KgLZ8b2ODE"&gt;Trio 2011 World Tour - Merry Christmas Mr.Lawrence (London)&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Piano - Ryuichi Sakamoto, Live&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=x1YkHJJi-tc"&gt;Sylvian &amp;amp; Sakamoto - Forbidden Colours&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;The very original.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=qezTmpJpHXI"&gt;Forbidden Colours by David Sylvian&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;David Sylvian's album.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;オリジナル -- ライブほか&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=DByOF2jU91c"&gt;戦場のメリークリスマス ／ 坂本龍一　矢野顕子&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;1983~1984位の映像らしい。フランスのTOKYO MELODYというテレビ番組(?)由来らしい。しかし、よくこんな映像が残っていたな...&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=cXS-uq-rrok"&gt;Ryuichi Sakamoto - Merry Christmas Mr. Lawrence (Live 1987)&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;1987年NHKホールでのライブ。古筝(Guzheng)はJiang Xiao-Qing&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ピアノ&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=We-lRQdBR80"&gt;【Lv.100】Merry Christmas, Mr. Lawrence&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;ストリートピアノで有名なけいちゃんのコンサートでの演奏。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=a5JtcBqXAdA"&gt;【Merry Christmas, Mr. Lawrence 】Concert in Ukraine&lt;/a&gt; &lt;ul&gt;
&lt;li&gt;中村天平さんによる、Ukrainaでの演奏。2019年なので戦争前。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=LQCfUARdxSc"&gt;Ryuichi Sakamoto – Merry Christmas, Mr. Lawrence (Piano Cover)&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;いわゆるハラミちゃんw&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=hZ6v3hLrnR4"&gt;I played “Merry Christmas Mr. Lawrence” at a station in Japan and many people stopped to listen.&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;日本在住のJacobさん。アレンジ多め。&lt;a href="https://www.youtube.com/watch?v=vLzw_unnyec"&gt;スタジオ録音の別演奏&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=zvXs5Fh6Gwo"&gt;【都庁ピアノ】都庁展望室が静まり返る？！美しすぎる戦場のメリークリスマス【Merry Christmas,Mr.Lawrence/あさぴ（朝香智子）】&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;あさぴさん。想いがのっている演奏&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=I8nrG6V0FDs"&gt;【都庁ピアノ】「戦場のメリークリスマス」を弾いてみた Merry Christmas, Mr. Lawrence piano by.Ryota Kikuchi&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;菊池亮太さんはヨーロッパの境界での追悼演奏ほか、たくさんバリエーションがある。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=4V-bxb7hnRg"&gt;戦場のメリークリスマス Merry Christmas, Mr Lawrence / Ryuichi Sakamoto #坂本龍一 Covered by #KanakoHara #はらかなこ&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;YMO好きで知られるはらかなこさん。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=LA5sRw8lGxA"&gt;元自衛官、この曲への想いが熱すぎる【戦場のメリークリスマス/坂本龍一】ストリートピアノ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=6_8qo7z9qUE"&gt;Ryuich Sakamoto / Merry Christmas Mr.Lawrence / Jazz&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Jazzだとこんな感じになるのか...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=xhMiVewaBIc"&gt;【2台ピアノ】「戦場のメリークリスマス」をアメリカ人と日本人が合奏してみた【よみぃ×Jacob Koller】Merry Christmas Mr.Lawrence&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;ピアノ連弾というのもある。というか個性的すぎる二人での連弾では(笑)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=UE8HZAFNblo"&gt;'Merry Christmas Mr Lawrence' Steinway Piano Cover by Japanese Otaku. Yomii (Ryuichi Sakamoto)&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;上記連弾の片方の人。ちょっと変わったアレンジ&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=jiaSK52e1Os"&gt;Merry Christmas Mr. Lawrence - Ryuichi sakamoto 4hands piano(by RayKana)&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;同じくピアノ連弾。ご夫婦らしい。しっとりした中からの盛り上がりがなかなかよい。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=imK_mq7BCR4"&gt;戦場のメリークリスマス2010 Merry Christmas Mr.LAWRENCE Smooth Jazz Version&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Another Jazzバージョン&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=XyE27AKnkHA"&gt;戦場のメリークリスマス (Merry Christmas Mr. Lawrence) - 坂本龍一 - Austin Nash Park&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;カナダ出身で現在は京都在住のピアニストの&lt;a href="https://www.austinnashpark.com/"&gt;Austin Nash Park&lt;/a&gt;さん。世界の一流ホテルでのパフォーマーというバックグラウンドのためか、派手すぎない味があると思う&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=IRJlpVoc-nQ"&gt;テクノポリス、ライディーン&lt;/a&gt;もすばらしい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=3OiOzjPWbhE"&gt;merry christmas mr lawrence but soulful&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;ソウルピアノ？これもすごい...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=6Q8-06dOdK4"&gt;Ryuichi Sakamoto - Merry Christmas Mr Lawrence Orchestral Version&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;イギリスのピアニスト/作曲家のLukas Kingさん。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=yDT-9KvGbp8"&gt;戦場のメリークリスマス / 坂本龍一 【ピアノ】&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;元は&lt;a href="https://www.youtube.com/watch?v=7ZZFxzorUIU"&gt;Flower dance / 転調 ver.&lt;/a&gt;からやってきて発見したのですが、間のとりかたというか、ためというか…が独特ですね。しかしerenaさん、中３ですか..&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=nOKjop8QkQg"&gt;GKO - Merry Christmas, Mr. Lawrence&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;この演奏は東京らしいけど、アメリカの人かな？何者なんだろう？他にも何本かある模様&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ピアノ+ハーモニカ&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=QNKRauDCdDE"&gt;Merry Christmas Mr. Lawrence - Cateen &amp;amp; Cy Leo&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.harmonica.uk/pages/cy-leo"&gt;Cy Leo&lt;/a&gt;さんは香港出身のハーモニカ奏者らしい &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=Gp19tqK-H4s"&gt;I played "Merry Christmas Mr. Lawrence" with a world-class harmonica player I met on the street.&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;2021/12/23 広島の原爆ドーム前での演奏。ピアノのJacobさんは日本在住で日本語ペラペラ。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ストリングス＋ピアノ&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=gA0vuBEnjE0"&gt;Ryuichi Sakamoto | Merry Christmas Mr Lawrence (with the TSUNAMI VIOLIN)&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;TSUNAMI VIOLINってなんだ？と思ったら、東日本大震災支援だった...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=s9GkxMjGhF4"&gt;Sakamoto I Merry Christmas, Mr. Lawrence I Morphing Chamber Orchestra&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;バイオリン、ビオラ、チェロ、コントラバス、ハープの構成。"As a tribute, we are releasing a new interpretation of Merry Christmas, Mr. Lawrence." と書いている通り、ちょっと新しいかもしれない。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=9qRFRwYSYN4"&gt;Merry Christmas Mr. Lawrence《聖誕快樂，勞倫斯先生》｜大提琴演奏版｜LuNaMusic&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;ピアノ伴奏のチェロ。台湾の人らしい。日本のアニメ系ポピュラーも好きな模様&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=bajxf2DQxfc"&gt;《Merry Christmas, Mr. Lawrence》坂本龍一電影 主題曲 《Forbidden Colours》大提琴版本Cello cover 『cover by YoYo Cello』&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;同じくピアノ伴奏のチェロ。この人も台湾の人のようだ。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=SNWBf8WfR4Q"&gt;BOSSA CELLI - Merry Christmas Mr Lawrence(Ryuichi Sakamoto Cover)&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;シンガポールのチェロカルテット。チェロも４本いるとすごいなー&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=28bZUU_mTxg"&gt;坂本龍一『戦場のメリークリスマス』Merry Christmas Mr.Lawrence / Ryuichi Sakamoto (Violin) LIVE at 2023.10.21【弓代星空】&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;バイオリン、ピアノ、チェロ。バイオリンの歌いっぷりがすごい。ぱっと見、宝塚っぽいな？と思ったけど、男性だった(苦笑)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=A7Y8BT-CXEc"&gt;【映画『戦場のメリークリスマス』】Merry Christmas, Mr. Lawrence / 坂本龍一【ヴァイオリン】&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;ひかえめなんだけど、なかなかよい。ピアニスト側からの映像もあった。&lt;a href="https://www.youtube.com/watch?v=R-zkjNgiMkA"&gt;戦場のメリークリスマス / Merry Christmas, Mr. Lawrence - 坂本龍一 / Ryuichi Sakamoto【ヴァイオリン&amp;amp;ピアノ】&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=zwT5L1DPhpg"&gt;「戦場のメリークリスマス」坂本龍一　ヴァイオリンソロ演奏　戦後80年献奏①&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;しずかな演奏なのだけど、献奏ということで想いが載った演奏。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=smxXE8Olomg"&gt;【ピアノ＆チェロカバー】戦場のメリークリスマス　　坂本龍一&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;この演奏、ピアノもチェロもかっこいいなー :)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=dgY4tjUh7rU"&gt;"Merry Christmas Mr. Lawrence" Piano and Violin Duet by MAiSA and Jacob Koller&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;さすがこの２人だけあって、ピアノもヴァイオリンもかっこいい:)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ギター&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=Fx3nCzBTZaI"&gt;Kotaro Oshio Merry Christmas Mr Lawrence Live cực chất&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;やはりギターは押尾コータローの印象が強いかなぁ&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=sKfuqNW-uGE"&gt;REAL DUO / Forbidden Colours Ryuichi Sakamoto - Luciano Damiani, mandolino Michele Libraro ch.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ZA-NjYpRn34"&gt;Kaori Muraji - 村治佳織 - Merry Christmas,Mr Lawrence - Ryuichi Sakamoto's&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=z14Zu0933BU"&gt;Merry Christmas Mr Lawrence (戦場のﾒﾘｰｸﾘｽﾏｽ) - Ryuichi Sakamoto arr. by Hirokazu Sato&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Singapore出身のクラッシックギタリスト&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=tNV_nA8IPPg"&gt;Merry Christmas Mr. Lawrence - Ryuichi Sakamoto Played by Christopher Rodrigues&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;クラッシックギター。ブラジルの人らしい。中盤からラテン風？の色が出てくる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=3Uvb5NfgqMc"&gt;Merry Christmas Mr Lawrence / Ryuichi Sakamoto arr.by Hirokazu Sato | 戦場のメリークリスマス 坂本龍一　 演奏：高田英里佳&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;クラッシックギター。間のとりかたに情感が載っているように思う&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=JPQC-zo_CgU"&gt;Ryuichi Sakamoto | Merry Christmas Mr Lawrence | Guitar&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;クラッシックギター。情熱が載った演奏。一つ上の演奏と楽譜は同じとのことなんだけど、ここまで変わるものか。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;[Merry Christmas Mr. Lawrence / Daisuke Minamizawa (acoustic guitar solo)(https://www.youtube.com/watch?v=Y36Zd9LjUiA)&lt;ul&gt;
&lt;li&gt;わりと広く出まわっているHirokazu Satoさんの楽譜とは違うアレンジ。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ウクレレ&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=8aXnjo46bYs"&gt;Merry Christmas, Mr. Lawrence – Ukulele Cover by Feng E&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;この熱量はすごい...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ハープ&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=u8QUDAQiw4E"&gt;Merry Christmas Mr. Lawrence - Ryuichi Sakamoto - Harp Cover&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;シロフォン&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=HzlLs0UYFHM"&gt;Pius Cheung - Merry Christmas Mr. Lawrence by Ryuichi Sakamoto&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Pius Cheng、すばらしい...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=YlZ5nKeaPzk"&gt;Kazukos Duo - Merry Christmas Mr. Lawrence / Ryuichi Sakamoto&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ソプラノサックス&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=jnoGiLDGneY"&gt;Merry Christmas Mr Lawrence (Sakamoto, Arr. Metcalfe)&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Beautiful Soprano Saxophone lead.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ハンドベル＆パーカッション&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=405N61fzqQc"&gt;MERRY CHRISTMAS MR LAWRENCE (Handbells &amp;amp; Percussion)&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;これ、練習大変だろうなぁ...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ボーカル&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=LuiVdct2E8I"&gt;Paul Potts Ryuichi Sakamoto "Merry Christamas, Mr Lawrence" (Forbidden Colours)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=u56Ca9SE7eY"&gt;Utada - "Merry Christmas Mr. Lawrence - FYI" on TV (2009)&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Trekkie(StarTrekファン)なら、「えっ？」と思ったのではないでしょうか。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=GLCDOTcaASE"&gt;Julienne Taylor - Forbidden Colours (Sylvian / Sakamoto) with lyrics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ギター+フルート+ボーカル&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=1OkiZ016jT0"&gt;Forbidden Colours - Merry Christmas Mr Lawrence (R. Sakamoto) INDACO acustica&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;フルート&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=36dMwxVns8c"&gt;【13Flutes +】戦場のメリークリスマス/坂本龍一 Merry Christmas, Mr. Lawrence【pic~bass】&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=GN0uo7gy4iQ"&gt;Rydeenを一人で何多重もやっている人&lt;/a&gt;もいたけど、フルートの一人多重録音。シンバルっぽい音は息で出しているのかな？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ハンドパン&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=3uTarPoqGZ0"&gt;Merry Christmas Mr.Lawrence, Jam&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;つい最近存在に気が付いたお気に入り。Handpan, Violin and keyboardのJam session。このviolin、すばらしい...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;バンドネオン&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=Q1_pNZcz00c"&gt;Ryuichi Sakamoto – Merry Christmas Mr. Lawrence (Bandonegro Live in Japan 2025)&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;バンドネオンはアコーディオンの一種。ピアノ、バイオリン、コントラバスとのカルテット。しかし、このバンドネオンかっこいいな...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;和楽器&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ZszxJxuORI4"&gt;和楽器のプロが戦場のメリークリスマス弾いてみた！ーJapanese traditional musical instruments ensemble "MAHORA"&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;和楽器バンドではないです&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;二胡&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=OcCkzk-jUUA"&gt;戦場のメリークリスマス - 坂本龍一 ｜ 二胡 演奏［RYUICHI SAKAMOTO - MERRY CHRISTMAS Mr.LAWRENCE on the Erhu］&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;二胡の二重奏 w/インスト。坂本龍一本人の演奏で、中国の伝統楽器の奏者と演奏しているやつがあったと思うけど、あれはラストエンペラーだったかな。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;そのほか&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=4u4HpMNFzHU"&gt;Ryuichi Sakamoto - Merry Christmas Mr. Lawreance (Dachs Uplifting Trance Remichs)&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;トランス。ドイツの人？と思ったら、どうも日本人らしい。1:30位からトランスらしくなるってことなのかしら？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=LM7XqJxDZ9c"&gt;Merry Christmas Mr. Lawrence - Electric Youth Remodel | A Tribute to Ryuichi Sakamoto&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;これはどう分類すればいいのかしら。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=pGwQKFbvo1M"&gt;Merry Christmas Mr. Lawrence&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;MAKSIMさんはピアノの人らしい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=9sCw79Tf29w"&gt;Kraftwerk - Merry Christmas Mr. Lawrence / Geigerzähler / Radioaktivität&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Kraftwerkの2025年のライブ。冒頭が戦メリ&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=pK-yPEetKUc"&gt;Merry Christmas Mr. Lawrence (lo-fi Beat)&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;lo-fi beat？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=6ZUuP24c9KE"&gt;Ryuichi Sakamoto - Merry Christmas Mr. Lawrence (Apr1x Remix)&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;このremixはなんていうスタイルって呼べばいいんだ？Melodic House &amp;amp; Technoとか？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=VmL_-pvM9rE"&gt;戦場のメリークリスマス　トランスカバー(HEART OF ASIA)&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Trace Remix。これは日本製かな？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=J6sVf2I6v8g"&gt;Ain't Nobody Know-ish Merry Christmas, Mr. Lawrence&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;星野源の"Ain't Nobody Know"との短いリミックス。30秒くらいと短いんだけど、フルコーラス作ってくれればいいのに&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=jGRoMo9flQY"&gt;Merry Christmas, Mr. Lawrence Ft. Frankie Yip (Keyboard and Bamboo Flute)&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;中国の伝統楽器の「笛子(Dizi)」とピアノによる演奏。独特な音色な笛と思ったら「吹き口の隣にある穴に「笛膜（てきまく）」という竹の薄い膜を貼り付けている」ためらしい。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ダンス&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=NLp5RW0E7gY"&gt;RYUICHI SAKAMOTO - Merry Christmas Mr.Lawrence Dance Film&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;演奏ではなくダンス。音楽は&lt;a href="https://www.youtube.com/watch?v=SM7ByWF1ZKw"&gt;これ&lt;/a&gt;を使っているらしい。&lt;/li&gt;
&lt;li&gt;&lt;a href="https://commmonsmart.com/en/products/rzcm-59189"&gt;アルバム情報&lt;/a&gt;によるとチェロはJakis Morelenbaum、バイオリンは Judy Kang とのこと。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=bai_sZnqF5A"&gt;Stefan Obermaier - Merry Christmas, Mr. Lawrence (Sakamoto)&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;ダンスというかインプロビゼーション？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</content><category term="music"></category></entry><entry><title>[ja] Object Storageのベンチマークについて(COSBench編)</title><link href="https://thatsdone.github.io/junkbox/object_storage_benchmark_cosbench.html" rel="alternate"></link><published>2021-10-01T18:00:00+09:00</published><updated>2021-10-01T18:00:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2021-10-01:/junkbox/object_storage_benchmark_cosbench.html</id><summary type="html">&lt;p&gt;Object Storage Benchmark(COSBench)&lt;/p&gt;</summary><content type="html">&lt;p&gt;最近、AWS S3のようなObject Storageの性能評価をせねばならん…という事情があり、
「そういえば、COSBenchってかなり昔からあるよなー」と思いつつ、最近あれこれ調べていました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/intel-cloud/cosbench/"&gt;COSBenchのリポジトリ&lt;/a&gt;
とか、
&lt;a href="https://www.semanticscholar.org/paper/COSBench%3A-A-Benchmark-Tool-for-Cloud-Object-Storage-Zheng-Chen/84665515d4dd5946743684e2f7236babb0901d10"&gt;論文&lt;/a&gt;
とか、
COSBenchの構造等の詳細は
&lt;a href="https://www.snia.org/sites/default/files/files2/files2/SDC2013/presentations/Cloud/YaguangWang__COSBench_Final.pdf"&gt;開発者による2013年のSNIA SDCの講演の資料&lt;/a&gt;
を見てもいいかもしれません。&lt;/p&gt;
&lt;p&gt;上記のCOSBenchのリポジトリを眺めてみると、2018年でcommitが止まっているので
死んでいるのかなー？と思いつつ、ちょっと調べてみたところ、
やはり「COSBenchを使って〇〇を評価してみた」というような記事は日本語の記事もそれなりに出てくる
のですが、2014~2016年くらいのものがほとんどです。&lt;/p&gt;
&lt;p&gt;それでも、2019年にはSNIAの講演
&lt;a href="https://www.snia.org/educational-library/object-storage-workload-testing-tools-2019"&gt;Object Storage Workload Testing Tools&lt;/a&gt;
でRedHatのエンジニアが使いどころを紹介しているほか、2021年にはTencentが自社Object Storageサービスの性能チューニングのベストプラクティスの一環で&lt;a href="https://intl.cloud.tencent.com/document/product/436/38298"&gt;Working with COSBench&lt;/a&gt;
という記事を出しているようで、まだ買われているようです。&lt;/p&gt;
&lt;p&gt;さて、本題は'21/10初頭時点でのリポジトリ…というか、コードの状態の話。
(前置きのほうが長かったかも(苦笑))&lt;/p&gt;
&lt;p&gt;ちょっと動かしてみた後、独自APIのObject Storageのドライバを追加しようかとビルドも試してみて気づいたことをいくつか。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04だと素直に動かない&lt;ul&gt;
&lt;li&gt;release版だと0.4.0.0まで戻せば動く&lt;ul&gt;
&lt;li&gt;使っているeclipse.equinox.launcherが古いせい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;EclipseのGUIから作ったままの設定情報があちこちに残っている&lt;/li&gt;
&lt;li&gt;ライブラリの類を全部抱え込んでいる&lt;/li&gt;
&lt;li&gt;テストがない&lt;/li&gt;
&lt;li&gt;EclipseのGUIからビルドする前提のつくりで、CI/CDに向いていない(mavenにしたい)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などなど&lt;/p&gt;
&lt;p&gt;前半に並べたものは既に issue に報告&amp;amp;PRしたりしています。&lt;a href="https://github.com/intel-cloud/cosbench/issues"&gt;こんなかんじ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;それぞれ、こんな問題があって、どう解決すべき…とか、つらつら書こうと思いますが...続きます。&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[en/ja] Resuming Again/(ふたたび)再開します</title><link href="https://thatsdone.github.io/junkbox/resuming_again.html" rel="alternate"></link><published>2021-09-23T17:30:00+09:00</published><updated>2021-09-23T17:30:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2021-09-23:/junkbox/resuming_again.html</id><summary type="html">&lt;p&gt;resuming this page again&lt;/p&gt;</summary><content type="html">&lt;p&gt;It's been one and a half year since I posted the last article.&lt;/p&gt;
&lt;p&gt;As the last post was on Feb. 15, 2020, I guess I could not afford to make time for fun things
because of physical stress because of COVID-19 and increased meetings.&lt;/p&gt;
&lt;p&gt;This year, I have already made presentations twice, and I'm writing including those topics.
Maybe I write on Japanese Light-Novels. Haha..&lt;/p&gt;
&lt;p&gt;意図して停止していたつもりはなかったのですが、気づいたら前回更新してから約1.5年も経っていました。&lt;/p&gt;
&lt;p&gt;前の投稿が2020/02/15なので、思えばコロナで在宅がデフォにってしばらくの間、腰痛がひどくて正直毎日生活しているだけで苦痛だったのと、在宅生活に体が慣れた後は出退勤の移動コストがなくなってずっと仕事(というか、会議(笑))の量が増えまくって余裕がなくなっていたせいかもしれません。&lt;/p&gt;
&lt;p&gt;今年は、既に2度ほど外部登壇しているので、そんな話もまじえてつらつら書いていこうと思います。
ラノベの話題も混ざるかもしれません(笑)&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>[ja] JSONをParquestに保存するのにApache Arrowを使ってみる</title><link href="https://thatsdone.github.io/junkbox/storing_json_to_parquet_by_apache_arrow.html" rel="alternate"></link><published>2020-02-15T21:00:00+09:00</published><updated>2020-02-15T21:00:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2020-02-15:/junkbox/storing_json_to_parquet_by_apache_arrow.html</id><summary type="html">&lt;p&gt;Apache Arrowを使ってJSONをParquestに保存してみる(Python)&lt;/p&gt;</summary><content type="html">&lt;p&gt;事情で表記のようなことを考える必要があり、Parquetをちょっと調べています。&lt;/p&gt;
&lt;p&gt;とりあえず、使いたい言語がPythonだったこと、Pandas等とも連携できることを考えて、Apache ArrowのPython bindingを使ってみることにしました。&lt;/p&gt;
&lt;h2&gt;参考情報&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://parquet.apache.org/documentation/latest/"&gt;Apache Parquet 公式サイトのHigh Level Document&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;物理pフォーマット(の概要)の解説も出ています。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arrow.apache.org/docs/index.html"&gt;Apache Arrow ドキュメント&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.classmethod.jp/business/bigdata/20190614-apache-arrow-parquet/"&gt;Apache Arrow(PyArrow)を使って簡単かつ高速にParquetファイルに変換する&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Athena の CTAS (Create Table AS)では、デフォルトではParquetで保存されるらしい。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.amedama.jp/entry/2017/10/10/135331"&gt;Python: Apache Parquet フォーマットを扱ってみる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@rajnishtiwari2010/conversion-of-json-to-parquet-format-using-apache-parquet-in-java-b694a0a7487d"&gt;Conversion of JSON to parquet format using Apache Parquet in JAVA&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Javaの場合&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;インストール&lt;/h2&gt;
&lt;p&gt;大人の事情でCentOS7系で動作確認したかったので、Pythonは(未だに)2.7系を使っています(苦笑)&lt;/p&gt;
&lt;p&gt;Apache Arrow自体は新しいものを使いたかったので、virtualenv を使って以下のようにお手軽に作成しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;virtualenv&lt;span class="w"&gt; &lt;/span&gt;venvs/arrow
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;venvs/arrow/bin/activate
$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;pyarrow
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;とりあえずやってみたこと&lt;/h2&gt;
&lt;p&gt;以下のようなテストデータを作って&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;key1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;key2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;value2-1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;key3&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;value3-1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;value3-1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;以下のようなプログラムで試しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pyarrow.parquet&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;pq&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pyarrow&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pajson&lt;/span&gt;

&lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pajson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;test.json&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;==================write table&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;pq&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;test.parquet&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;==================using parquet.read_schema&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pq&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_schema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;test.parquet&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;実行するとこんな感じになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;test.py
&lt;span class="o"&gt;==================&lt;/span&gt;write&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;table&lt;/span&gt;
&lt;span class="o"&gt;==================&lt;/span&gt;using&lt;span class="w"&gt; &lt;/span&gt;parquet.read_schema
key1:&lt;span class="w"&gt; &lt;/span&gt;int64
key2:&lt;span class="w"&gt; &lt;/span&gt;string
key3:&lt;span class="w"&gt; &lt;/span&gt;list&amp;lt;item:&lt;span class="w"&gt; &lt;/span&gt;string&amp;gt;
&lt;span class="w"&gt;  &lt;/span&gt;child&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;item:&lt;span class="w"&gt; &lt;/span&gt;string
metadata
--------
OrderedDict&lt;span class="o"&gt;([(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ARROW:schema&amp;#39;&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/////wgBAAAQAAAAAAAKAAwABgAFAAgACgAAAAABAwAMAAAACAAIAAAABAAIAAAABAAAAAMAAACcAAAAXAAAAAQAAACA////AAABDEAAAAAQAAAABAAAAAEAAAAIAAAAsP///6D///8AAAEFFAAAAAwAAAAEAAAAAAAAAMz///8EAAAAaXRlbQAAAAAEAAAAa2V5MwAAAADU////AAABBRgAAAAQAAAABAAAAAAAAAAEAAQABAAAAAQAAABrZXkyAAAAABAAFAAIAAYABwAMAAAAEAAQAAAAAAABAiQAAAAUAAAABAAAAAAAAAAIAAwACAAHAAgAAAAAAAABQAAAAAQAAABrZXkxAAAAAAAAAAA=&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;)])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;後述の通り、先にスキーマを作らなくても動くのかどうか確認したかったのですが、入力に従ったスキーマが作成されているようです。&lt;/p&gt;
&lt;p&gt;余談ですが、1レコードしかないので、サイズはこんな感じになりますね(苦笑)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;du&lt;span class="w"&gt; &lt;/span&gt;-b&lt;span class="w"&gt; &lt;/span&gt;test.json&lt;span class="w"&gt; &lt;/span&gt;test.parquet
&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;test.json
&lt;span class="m"&gt;232&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;test.parquet
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;TODO&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;圧縮を試す&lt;/li&gt;
&lt;li&gt;複数レコード格納する&lt;ul&gt;
&lt;li&gt;後述のトップレベル名無し配列の件も調べる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;事前にスキーマを定義した場合と動的に作成させた場合の違いの確認&lt;/li&gt;
&lt;li&gt;スキーマにないelementが現れた場合の挙動の確認&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;TIPS(というか気づいたことのメモ)&lt;/h2&gt;
&lt;h3&gt;スキーマは事前に準備しなくても動く&lt;/h3&gt;
&lt;p&gt;確かに動くのですが、これで最適なのか、確認要。(TBD)&lt;/p&gt;
&lt;h3&gt;pyarrow.json では Objectのネストはできない&lt;/h3&gt;
&lt;p&gt;以下の例では "key4"の値はさらにObject(Pythonではdcit)になっていますが、これは&lt;code&gt;pyarrow.json.read_json()&lt;/code&gt;に食わせるとエラーになるようです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;key1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;key2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;value2-1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;key3&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;value3-1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;value3-1&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;key4&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;key41&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;key42&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;value42&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;JSONで許されているトップレベルの名無しArrayは通らない&lt;/h3&gt;
&lt;p&gt;JSONの規格上、以下のようなデータは許されているのですが、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;key1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;key2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;value2-1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;key3&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;value3-1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;value3-1&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;key1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;key2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;value2-2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;key3&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;value3-2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;value3-2&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;しかし、こんな感じでエラーになります。
これは、Arrayの要素を1つに減らしても同じです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;test.py
Traceback&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;most&lt;span class="w"&gt; &lt;/span&gt;recent&lt;span class="w"&gt; &lt;/span&gt;call&lt;span class="w"&gt; &lt;/span&gt;last&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="w"&gt;  &lt;/span&gt;File&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;test.py&amp;quot;&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;line&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;module&amp;gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pajson.read_json&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;test3.json&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;File&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;pyarrow/_json.pyx&amp;quot;&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;line&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;193&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pyarrow._json.read_json
&lt;span class="w"&gt;  &lt;/span&gt;File&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;pyarrow/error.pxi&amp;quot;&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;line&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;84&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pyarrow.lib.check_status
pyarrow.lib.ArrowInvalid:&lt;span class="w"&gt; &lt;/span&gt;JSON&lt;span class="w"&gt; &lt;/span&gt;parse&lt;span class="w"&gt; &lt;/span&gt;error:&lt;span class="w"&gt; &lt;/span&gt;Column&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;changed&lt;span class="w"&gt; &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;object&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;array&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;row&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;続きます。&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[ja] Jupyter Notebook Dynamic Plot</title><link href="https://thatsdone.github.io/junkbox/jupyter_notebook_dynamic_plot.html" rel="alternate"></link><published>2020-02-13T23:00:00+09:00</published><updated>2020-02-13T23:00:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2020-02-13:/junkbox/jupyter_notebook_dynamic_plot.html</id><summary type="html">&lt;p&gt;Jupyter Notebookで動くグラフを描画したい&lt;/p&gt;</summary><content type="html">&lt;p&gt;Jupyter Notebookを使っていて、どんどんあたらしい結果が出てくる場合等、描画結果を動的に更新したいと思って調べたメモ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/39658717/plot-dynamically-changing-graph-using-matplotlib-in-jupyter-notebook"&gt;Plot dynamically changing graph using matplotlib in Jupyter Notebook&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;このやりとりによると、自前でやる方法もいろいろあるようだが、matplotlib の animation を使うのが一番基本なのかな。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=rkBPgTL-D3Y"&gt;Developing Advanced Plots with Matplotlib : Interactive  Plots in the Jupyter Notebook | packtpub.com&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;ipywidgets　を入れて使う方法。すごく詳しいライブ解説。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://towardsdatascience.com/interactive-visualizations-in-jupyter-notebook-3be02ab2b8cd"&gt;Interactive Visualizations In Jupyter Notebook&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Plotly と ipywidgets　を入れる方法。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/matplotlib/matplotlib/issues/9606"&gt;Attempt to create a dynamically changing plot in console and notebook&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;こんな matplotlib の issueを見つけたのだが、まだopen状態のようだ...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</content><category term="tech"></category></entry><entry><title>[ja] Light Novels (3)</title><link href="https://thatsdone.github.io/junkbox/book_light_novel3.html" rel="alternate"></link><published>2020-02-12T23:30:00+09:00</published><updated>2020-02-12T23:30:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2020-02-12:/junkbox/book_light_novel3.html</id><summary type="html">&lt;p&gt;Exceptionally Interesting Ideas - ラノベ話(その３) - その発想はなかったわー&lt;/p&gt;</summary><content type="html">&lt;p&gt;前にも書いた&lt;a href="https://thatsdone.github.io/junkbox/book_light_novel1.html"&gt;ラノベ話&lt;/a&gt;の続き。&lt;/p&gt;
&lt;p&gt;異世界ファンタジーものは、これでもか…と似たような話がてんこ盛りなわけですが、それでも「その発想はなかったわー」というのがけっこうあったりします。そういうものをいくつか。(再掲も含みます)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054885338663"&gt;モニカの奇妙な相棒　～　最強スキルは、俺自身！？　～&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;私が一番好きな話です。前にも挙げたのですが、タイトルが変更になっています。転生ものですが、普通は主人公本人に転生するところ、転生先のファンタジー世界のキャラクタ(主人公)が持つ「インテリジェント・スキル」に転生するのです。作品世界も壮大で、面白いです。…が、この発想はなかったわー(笑)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054886574351"&gt;勇者→魔王→勇者→魔王の順で転生してきた勇者、疲れたので役目を放棄する&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;主人公のまわり自体はチート&amp;amp;ハーレムな感じでよくあるパターンですが、タイトルの通り、勇者→魔王→勇者→魔王と４回転生した後で、女神様にもう一回勇者に転生してくれと言われてキレたあげく、女神様を倒そうとするところから話が始まります。いや、その発想はなかったわー。(笑)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054884156287"&gt;まりんこ！～立ち塞がる敵はすべて倒す！ 不屈の悪役令嬢は異世界を海兵隊と駆け抜ける～&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;この話も前に&lt;a href="https://thatsdone.github.io/junkbox/book_light_novel2.html"&gt;単独で取り上げている&lt;/a&gt;のですが、ファンタジー世界の登場人物に、なぜか日本のラノベ文化の知識があるアメリカ海兵隊の人が転生し、侯爵令嬢にブートキャンプをほどこすと。いや、この発想もなかったわー(笑)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054893547168"&gt;「九人目」の荷物持ちの手記&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;異世界ファンタジーの作品ではパーティーを組んだ「八英雄」とかよく出てくるのですが、そのパーティーに動向していた「奴隷」だった主人公の手記という体裁。しかも、八英雄たる8名それぞれの暗部を告発するという。いや、この発想もなかったわー(笑)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;なお、ありそうでない話の例としてこんな話もあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054883808252"&gt;異世界転生したけど日本語が通じなかった&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;タイトルの通り、異世界に転生はするけれど、なぜか現地の言語がわかる…という鉄板なパターンに逆らい、この作品世界では、転生した主人公が現地の言語を勉強するところから始まります。現地の言語は作者さんのオリジナルで(たぶん)、本当に新しい言語を作り上げています。読むのが結構たいへんですが、話が進行していくにしたがって、「えっ？そんな世界観だったの？」と驚きが待っています。パロディな姉妹編もあります(笑)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また、面白い話を見つけたら更新しようと思います。&lt;/p&gt;</content><category term="novel"></category></entry><entry><title>[ja] Kubernetes Patterns</title><link href="https://thatsdone.github.io/junkbox/book_kubernetes_patterns.html" rel="alternate"></link><published>2020-02-11T21:00:00+09:00</published><updated>2020-02-11T21:00:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2020-02-11:/junkbox/book_kubernetes_patterns.html</id><summary type="html">&lt;p&gt;Kubernetes Patterns - Reusable Elements for Designing Cloud-Native Applications&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://www.amazon.co.jp/Performance-Tools-Addison-Wesley-Professional-Computing/dp/0136554822/"&gt;BPF本&lt;/a&gt;の話も書きかけなのですが、そういえば同僚がSan Diego でもらってきた本の中に&lt;a href="https://www.amazon.co.jp/dp/1492050288"&gt;Kubernetes Patterns: Reusable Elements for Designing Cloud-Native Applications&lt;/a&gt;もありました。&lt;/p&gt;
&lt;p&gt;同じく章構成はこんな感じになっています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    1. Introduction

Part I : Foundation Patterns
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;まずは基本パターン…というよりは、見てわかる通り、k8s を使いこなすにあたって押さえておくべき基本概念ですね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    2 Predcitable Dememands
    3 Declarative Deployments
    4 Health Probe
    5 Managed Lifecycle
    6 Automated Placement

Part II : Behavioral Patterns
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;プログラムやサービスの挙動に応じたパターン分類。だいたい名が体を表しているように思いますが、ぱっと見て11のStateful Serviceと13のSelf Awarenessの違いって何よ？と思ったのですが、Self Awarenessのほうは、コンテナが自分が動ているpodを意識する必要があるようなケースのためのものです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Batch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Job&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Periodic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Job&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Daemon&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Service&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Singleton&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Service&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Stateful&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Service&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Service&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Discovery&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Awareness&lt;/span&gt;

&lt;span class="nx"&gt;Part&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;III&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Structural&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Patterns&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Part IIIはプログラムやサービスの構造に基づいたパターン分類。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    14 Init Container
    15 Side Car
    16 Adapter
    17 Ambasaddor

Part IV : Configuration Patterns
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;プログラムやサービスの設定情報をどう持ってまわるか？に基づいたパターン分類。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    18 EnvVar Configuration
    19 Confiuration Resource
    20 Immutable Configuration
    21 Configuration Template

Part V : Advanced Patterns
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;進んだトピック。22のControllerと23のOperatorは、いわゆる kubernetes のController/Operatorの解説、24はkubernetesによってアプリケーションをスケールさせる方法、最後の25はここまでの話題とは少し毛色が変わってkubernetes clusterの中でイメージを維持管理する方法論です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    22 Controller
    23 Operator
    24 Elastic Scale
    25 Image Builder

    Aferword
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;まとめ。&lt;/p&gt;
&lt;p&gt;さて、ここまでざっと本の構造を眺めただけなので、ちゃんと読まなくては(笑)&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[ja] BPF Performance Tools - Brendan Gregg</title><link href="https://thatsdone.github.io/junkbox/book_bpf_performance_tools.html" rel="alternate"></link><published>2020-01-29T22:30:00+09:00</published><updated>2020-01-29T22:30:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2020-01-29:/junkbox/book_bpf_performance_tools.html</id><summary type="html">&lt;p&gt;Linux System and Application Observability by BPF&lt;/p&gt;</summary><content type="html">&lt;p&gt;海外出張しているうちに、Brendan Gregg の "&lt;a href="https://www.amazon.co.jp/Performance-Tools-Addison-Wesley-Professional-Computing/dp/0136554822/"&gt;BPF Performance Tools&lt;/a&gt;" が届いていました。:)&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.co.jp/dp/0133390098"&gt;前著&lt;/a&gt;の&lt;a href="https://thatsdone.github.io/junkbox/methodologies_of_systems_performance.html"&gt;まとめ&lt;/a&gt;を書いている最中ではあるのですが、こっちもまとめようかと思います。(つまり、やっぱり書きかけ…)&lt;/p&gt;
&lt;h2&gt;本書の構成&lt;/h2&gt;
&lt;p&gt;まず、目次の章レベルの構成は以下のような感じになっています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Part I : Technologies
    1 Introduction
    2 Technology Background
    3 Performance Analysis
    4 BCC
    5 bpftrace
Part II : Using BPF Tools
    6 CPUs
    7 Memory
    8 Filesystems
    9 Disk I/O
    10 Networking
    11 Security
    12 Laguages
    13 Applications
    14 Kernel
    15 Containers
    16 Hypervisors
Part III : Additional Topics
    17 Other BPF Performance Tools
    18 Tips, Tricks and Common Problems
Part IV : Appendixes
    A BPF Trace One-Liners
    B BPF Trace Cheat Sheet
    C BCC Tool Development
    D C BPF
    E BPF Instructions
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Part Iで大事なのは3章の3.2節"Performance Methodologies"でしょうか。この3.2節に相当する内容は、前著では2章すべてをあててかなり包括的に性能解析の考え方を説明していたのですが、本書では必要最小限のかなりコンパクトな量におさえています。
Part Iではそのほか、1章で全体像、2章でBPFそのものと関連コンポーネントの紹介、4章で"BCC" (BPF Compiler Collection)と題してBPF関連の開発ツールについての紹介、5章が一番よく使われるツールで"bpftool"の詳しい解説になっています。&lt;/p&gt;
&lt;p&gt;Part IIは、前著でいうと5章以降の、"Application"や"CPU"といった具体的な切り口に即したBPF関連ツールの使い方の紹介です。なお、15章のContainersと16章のHypervisorsは、前著にも含まれないトピック自体新しい内容なので、最初は全体を流す人も読んだほうがいいかもしれません。(というか私もそうします(笑))&lt;/p&gt;
&lt;p&gt;Part IIIの17章は "Other BPF Performance Tools" とはなっているのですが、Prometheus等のモニタリングツールとの組みあわせや、kubernetes との連携話もあり、読み飛ばせません。また、18章も "Tips, Tricks and Common Problems" というタイトルが示すように、実用上おさえておきたい勘所が載っているようです。&lt;/p&gt;
&lt;p&gt;ところで、ここまであたかも読了したような書きぶりですが、読みながらメモっています。
なので、当分は更新が続くと思います。&lt;/p&gt;
&lt;h2&gt;留意事項:Ubuntu 18.04(Bionic)でのインストール&lt;/h2&gt;
&lt;p&gt;本書も&lt;a href="https://www.amazon.co.jp/dp/477419607X"&gt;武内さんの本&lt;/a&gt;と同じように「試して理解」するのが重要だと思いますが、現時点でUbuntuで使いたい人に、インストールで一点留意事項があります。&lt;/p&gt;
&lt;p&gt;まず、インストール方法は4.3節の"BCC Installation"で各種distroでのインストール方法が解説されています。&lt;/p&gt;
&lt;p&gt;Ubuntuの場合はuniverseにbpfcc-toolsというパッケージ名で入っているのでこれを入れてもよいのですが、特に 18.04(Bionic)付属のものは古いので、できれば新しいものを使いたいところです。4.3.2 節のUbuntu用の説明では、https://repo.iovisor.org/ の apt-line が紹介されているのですが、'20/2時点でメンテナンスが止まっているようです。&lt;/p&gt;
&lt;p&gt;調べてみたところ、Colin Ian Kingさんがメンテしているppaから最新版が入れられるようなので、どうしても自前でビルドしたい人以外はこちらを使うとよいでしょう。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://launchpad.net/~colin-king/+archive/ubuntu/bpftrace-backports"&gt;https://launchpad.net/~colin-king/+archive/ubuntu/bpftrace-backports&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;以下の手順でインストールできます。(bpftraceも一緒に入れてください)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;add-apt-repository&lt;span class="w"&gt; &lt;/span&gt;ppa:colin-king/bpftrace-backports
sudo&lt;span class="w"&gt; &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;update

sudo&lt;span class="w"&gt; &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;bpfcc-tools&lt;span class="w"&gt; &lt;/span&gt;bpftrace
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;性能分析の方法論&lt;/h2&gt;
&lt;p&gt;一番大事なところ(だと私は思う)、性能分析の方法論は3.2節で解説されています。&lt;/p&gt;
&lt;p&gt;具体的には以下の通りですが、1) 問題を定義する、2) 段階的詳細化、3) 構造の理解の上でリソースの状態の分析…と、もっともな内容になっています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;3.2.1節 Workload Characterization&lt;/li&gt;
&lt;li&gt;3.2.2節 Drill-Analysis&lt;/li&gt;
&lt;li&gt;3.2.3節 USE Method&lt;/li&gt;
&lt;li&gt;3.2.4節 Checklists&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;チェックリストで定型化するのはサポート部隊等でよく取られる手段ですが、直後の3.3節ではLinuxの場合に1分でできるチェックリストの実例ということで以下のようなコマンドが挙がっています。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;uptime&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dmesg | tail&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vmstat 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mpstat -P ALL 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pidstat 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;iostat -xz 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;free -m&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sar -n DEV 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sar -n TCP,ETCP 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;top&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;本書で詳細に解説される bpfcc-tools 付属の各種スクリプトやツールで同等のことはできるのですが、
上記は大体どんな環境にも入っていますし、併用するのも有益でしょう…という記述もあります。&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[ja] Methodologies of Systems Performance - Brendan Gregg</title><link href="https://thatsdone.github.io/junkbox/book_methodologies_of_systems_performance.html" rel="alternate"></link><published>2020-01-14T00:01:00+09:00</published><updated>2020-01-14T00:01:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2020-01-14:/junkbox/book_methodologies_of_systems_performance.html</id><summary type="html">&lt;p&gt;Methodologies of Peformance Analysis&lt;/p&gt;</summary><content type="html">&lt;p&gt;Brendan Gregg の "&lt;a href="https://www.amazon.co.jp/dp/0133390098"&gt;Systems Performance: Enterprise and the Cloud&lt;/a&gt;" という本があります。
(翻訳は&lt;a href="https://www.amazon.co.jp/dp/4873117909/"&gt;こちら&lt;/a&gt;) 言わずと知れた DTrace の作者が書いた本で、
全体的な考え方から、CPU・メモリ…等と、具体的な観点ごとに包括的かつ詳細に解説されているので非常によい本です。
軽い勉強会みたいなやつで使おうと思って、まずは方法論(Methodology)が書いてある2章のまとめを作っています。
…が、書いてみたら、結局、目次を追っていくのが一番いいのかなー…という結論に（笑）&lt;/p&gt;
&lt;p&gt;なお、昨年末に"&lt;a href="https://www.amazon.co.jp/dp/0136554822/"&gt;BPF Performance Tools&lt;/a&gt;"という新しい本も出ていて買ったのですが、
私は発送待ち状態です。いつ日本に来るんでしょうか？(苦笑)
まあ、eBPF/XDPについては&lt;a href="https://www.amazon.co.jp/Linux-Observability-Bpf-Programming-Performance/dp/1492050202/"&gt;これ&lt;/a&gt;
も読んだので、まあぼちぼちでいいっちゃいいのですが。(笑)&lt;/p&gt;
&lt;h1&gt;一番大事なところ - 方法論の章(2章)の構成&lt;/h1&gt;
&lt;p&gt;方法論(Methodology)は2章になります。
この章だけでけっこうな分量になるので、まずは全体を俯瞰するという意味で、目次構成を眺めるだけでも意味があるでしょう。
目次の構成をそのまま引用しながらまとめていきます。少し長いですが、落ち着いて眺めてみると頭が整理できると思います。&lt;/p&gt;
&lt;p&gt;なお、著者本人は、冒頭でこの章をざっくりまとめると以下の３点であると書いています。
2.5節の具体的な方法論と、これらを使うときに使う具体的な Metric の２点が大事なのであって、
他はみんなこの２点を使うための背景知識なのだというわけです。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Background&lt;/li&gt;
&lt;li&gt;Methodology&lt;/li&gt;
&lt;li&gt;Metrics&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;以下、２章の目次にしたがって見ていきます。(ただし、まだ書きかけ)&lt;/p&gt;
&lt;h2&gt;2. Methodology ★一番大事な章★&lt;/h2&gt;
&lt;h3&gt;2.1 Terminology ＃ まずは用語定義&lt;/h3&gt;
&lt;h3&gt;2.2 Models ＃ モデル&lt;/h3&gt;
&lt;h4&gt;2.2.1 Systems Under Test&lt;/h4&gt;
&lt;p&gt;評価・分析するシステム自体のモデル化しておく。いわゆるSUT。&lt;/p&gt;
&lt;h4&gt;2.2.2 Queueing System&lt;/h4&gt;
&lt;p&gt;待ち行列理論 = 数理モデルの基本&lt;/p&gt;
&lt;p&gt;ちなみにこんな本もありますね。&lt;a href="https://www.amazon.co.jp/Performance-Modeling-Design-Computer-Systems/dp/1107027500"&gt;Performance Modeling and Design of Computer Systems: Queueing Theory in Action&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;2.3 Concepts ＃ 基本概念&lt;/h3&gt;
&lt;p&gt;この節、個人的には項目の選択とか並びが ad hoc すぎるのではないか？という感がありますが、それは別途整理するとして、並んでいる順番に見ていきます。&lt;/p&gt;
&lt;h4&gt;2.3.1 Latency&lt;/h4&gt;
&lt;p&gt;一言で「通信遅延」と言っても、測定する場所によって、例えばコネクション接続+データ転送+処理時間…等分解されるのに注意。&lt;/p&gt;
&lt;h4&gt;2.3.2 Time-Scales&lt;/h4&gt;
&lt;p&gt;CPUの命令サイクル、メモリアクセス、DISKアクセス…等、モノによってかかる時間のスケールが違うのに注意。&lt;/p&gt;
&lt;h4&gt;2.3.3 Trade-offs&lt;/h4&gt;
&lt;p&gt;例えば、I/OサイズとI/O性能・I/Oパターンの関係等、両立しないものの間のトレードオフを知ること。&lt;/p&gt;
&lt;h4&gt;2.3.4 Tuning Efforts&lt;/h4&gt;
&lt;p&gt;アプリ～MW～OS～ハードのどのレイヤで性能チューニングを施すのか？一般論としては(アプリに近い)上のレイヤで実施するほど効果は高い。&lt;/p&gt;
&lt;h4&gt;2.3.5 Level of Appropriateness&lt;/h4&gt;
&lt;p&gt;性能分析、チューニングにどこまでコストをかけて深堀りするのかは組織としての投資対効果による。&lt;/p&gt;
&lt;h4&gt;2.3.6 Point-in-Time Recommendations&lt;/h4&gt;
&lt;p&gt;チューニングパラメータの推奨値は、条件によって変わるものなので「その時点のもの」(point-in-time)と思うべし。&lt;/p&gt;
&lt;h4&gt;2.3.7 Load versus Architecture&lt;/h4&gt;
&lt;p&gt;システムの性能に影響するのは個々のソフトの「設定値」だけでなく、システムの構造（アーキテクチャ）に由来することもある。&lt;/p&gt;
&lt;h4&gt;2.3.8 Scalability&lt;/h4&gt;
&lt;p&gt;スケーラビリティ＝負荷量に対する性能値のふるまい。ふるまいの変化は、スループットの場合はリニアな伸びが変わるところ、レスポンスは一定値（≒リニア）から徐々に劣化が始まるところで見える。典型的な理由は、(なんらかの)リソースの utilization が 100%に達すること(saturation)。&lt;/p&gt;
&lt;h4&gt;2.3.9 Known-Unknowns&lt;/h4&gt;
&lt;p&gt;いわゆるknown-known/known-unknown/unknown-unknown。性能評価を進めるにしたがって、unknown-unknownに気づいていくのに注意。&lt;/p&gt;
&lt;h4&gt;2.3.10 Metrics&lt;/h4&gt;
&lt;p&gt;実際に見る具体的な指標。例としては、IOPS、troughput、utilization、latenc等々。忘れてはいけない大事な点として、1) metricの採取自体にもコストがかかること、2) metricの定義や実装そのものに信頼がないようなケースもあること。&lt;/p&gt;
&lt;h4&gt;2.3.11 Utilization&lt;/h4&gt;
&lt;p&gt;利用率には「時間(time)ベース」と「容量(capacity)ベース」の２つがある。前者は単位時間あたりに仕事をしていた時間(busy率)で、後者は処理可能な容量に対する割合。特に前者のbusy率の場合、リソースによっては多重処理が可能なケースもあるので、utilization が100%であっても限界とは限らないのに注意が必要。&lt;/p&gt;
&lt;p&gt;cloud (というか、仮想化)環境の場合には、non-idle time という見方をしたほうがよいという考え方もある。&lt;/p&gt;
&lt;h4&gt;2.3.12 Saturation&lt;/h4&gt;
&lt;p&gt;saturation (飽和)状態とは、処理可能な量を超えて、どの程度のリクエスト(仕事)量が流入しているかを示す程度。処理しきれないリクエストは、待ち行列につながることになる。&lt;/p&gt;
&lt;h4&gt;2.3.13 Profiling&lt;/h4&gt;
&lt;p&gt;一般論としては、調べて理解できるような対象システムの「描像」を得ること。実際のシステムの Profiling では、典型的にはサンプリングが基本であって、(サンプル間隔しだいだが)得られる描像は荒い（疎な）ものになるの注意。&lt;/p&gt;
&lt;h4&gt;2.3.14 Caching&lt;/h4&gt;
&lt;p&gt;本書では後ろの方でキャッシングとバッファリングの違いの話も出てきますが、ここではキャッシュのヒット率と性能の関係、キャッシュのアルゴリズム(MRU/LRU/MFU/LFU)や、キャッシュされたデータのCold/Hot/Warmという分類(と、キャッシュ暖かさ(Warmth)という用語)が出てきます。&lt;/p&gt;
&lt;h3&gt;2.4 Perspectives ＃ 全体像&lt;/h3&gt;
&lt;p&gt;性能分析には、大きく、1. Resource Analysis と 2. Workload Analysis の2つの側面がある。&lt;/p&gt;
&lt;p&gt;1.の Resource Analysisには文字通りリソースの利用状況の分析であり、さらに a) 性能問題の調査と、b) Capacity Planning が含まれる。&lt;/p&gt;
&lt;p&gt;2.の Workload Analysisはアプリケーションの構造を鑑みて指標(SLIかな)をどう定義するのか？という話で、典型的には Latency(Response)とThroughputが含まれる。&lt;/p&gt;
&lt;h3&gt;2.5 Methodology ＃ 方法論（★一番大事なところ★）&lt;/h3&gt;
&lt;p&gt;この節は一番大事なところなのですが、2.3 Concepts と同様に、並んでいる順番が少し ad hoc すぎないか？という気がしています。&lt;/p&gt;
&lt;h4&gt;2.5.1 Streetlight Anti-Method&lt;/h4&gt;
&lt;p&gt;Anti-Method(やっちゃダメ)な例。意図的な方法論がないケースのこと。適当に探してなんとなく見つかったツールで測定した指標を使うということで、検出された問題は実際のところは問題なこともあるし問題でないこともある。&lt;/p&gt;
&lt;h4&gt;2.5.2 Random Change Anti-Method&lt;/h4&gt;
&lt;p&gt;これも Anti-Method。原因になっていそうポイントをランダムに想定し、その条件を問題が消えるまで変え続けるということ。&lt;/p&gt;
&lt;h4&gt;2.5.3. Blame-Someone-Else Anti-Method&lt;/h4&gt;
&lt;p&gt;同じく Anti-Method。自分の担当範囲外の部分を見つけて、そこに原因があるという仮説を立てて担当チームに押し付ける。(ごくまれによく採用される方法論...gkbr)&lt;/p&gt;
&lt;h4&gt;2.5.4 Ad Hoc Checklist Method&lt;/h4&gt;
&lt;p&gt;定型のチェックリストにしたがう方法。チェックリスト自体は最短時間で多くの範囲をカバーできるが、あくまでその時点での推奨であって、頻繁に更新する必要があるのに注意。&lt;/p&gt;
&lt;h4&gt;2.5.5 Problem Statement ★最重要★&lt;/h4&gt;
&lt;p&gt;新しい問題に取り組むときには最初にとるべき方法。以下のような手順で、問題を具体的に書き下して定義していきます。これによって、問題点がわかることも多いです。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;性能問題があると考えた理由は何か？&lt;/li&gt;
&lt;li&gt;今まで想定どおりに動いていたか？&lt;/li&gt;
&lt;li&gt;最近何か変えたか？&lt;/li&gt;
&lt;li&gt;問題はlatencyかthroughputの指標で表せるか？&lt;/li&gt;
&lt;li&gt;その問題は、他の人やアプリケーションに影響を及ぼしているのか？それとも自分だけか？&lt;/li&gt;
&lt;li&gt;環境は？どんなソフトとハードを使っているのか？バージョンは？設定は？&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;2.5.6 Scientific Method ★重要★&lt;/h4&gt;
&lt;p&gt;通常の自然科学の研究でとるアプローチ。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;課題設定(Question)&lt;/li&gt;
&lt;li&gt;仮説を立てる(Hypothetis)&lt;/li&gt;
&lt;li&gt;予想をたてる(Prediction)&lt;/li&gt;
&lt;li&gt;テスト(Test)&lt;/li&gt;
&lt;li&gt;分析(Analysis)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;最初の 'Question' は 2.5.5の Problem Statement であって、これが出発点になる。&lt;/p&gt;
&lt;h4&gt;2.5.7 Diagnosis Cycle  ★重要★&lt;/h4&gt;
&lt;p&gt;Scientific Method と似ているが。仮説をたてる → 計測する → 分析する →　新しい仮説をたてる…という分析的なアプローチ。&lt;/p&gt;
&lt;h4&gt;2.5.8 Tools Method&lt;/h4&gt;
&lt;p&gt;手順は「使えるツールのリストを作る → 各ツールで得られる有用なmetricの一覧を作る → 各metricの解釈のルールを作る」。これが完璧というわけではないし、十分とは言えないこともあるが、現実的にはこの方法でリソースのボトルネックやエラー等の問題を検出できる。&lt;/p&gt;
&lt;h4&gt;2.5.9 The USE Method ★重要★&lt;/h4&gt;
&lt;p&gt;まず特定のリソースに着目、当該リソース関連のErrorがあるか？、Utilization は高いか？Saturationが発生しているか？の十番で事象の発生有無をチェックし、検出した事象が原因なのかどうか検討する。原因でなければ次のリソースに着目するという手順をとる。&lt;/p&gt;
&lt;p&gt;着目すべきリソースは、リソースの一覧表を使う(CPU/Memory/Network/Storage/Controller等)、機能ブロック図(例として図2.13)から考える方法がある。&lt;/p&gt;
&lt;p&gt;リソースの種別ごとに様々な metric がある。(表2.5と表2.6)手元のツールで取得できない metric は known-unknownとして意識しておくべき。&lt;/p&gt;
&lt;p&gt;CPUのようなハードウェアリソース以外に「ソフトウェアリソース」がある。例えば、mutex lock の衝突数等、thread poolの空き状況等。&lt;/p&gt;
&lt;p&gt;解釈の例&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Utilization&lt;ul&gt;
&lt;li&gt;きちんと評価するには、待ち行列を使って考えるべし。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Saturation&lt;ul&gt;
&lt;li&gt;飽和状態が発生しているということは問題な可能性がある。待ちキューの長さ滞留時間を調べる。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Error&lt;ul&gt;
&lt;li&gt;エラーのカウンタが0でなく、数値が増え続けているのであれば調べる価値がある。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2.5.10 Workload Characterization&lt;/h4&gt;
&lt;p&gt;「ワークロードの説明」をしておくのは、問題点を明らかにするための良い方法。以下の4つを問うことによって説明できる。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Who : 誰が負荷を発生させているのか？ PID？UID？remote IP address？&lt;/li&gt;
&lt;li&gt;Why : なぜその負荷が発生しているのか？code pathをstack traceで調べる？&lt;/li&gt;
&lt;li&gt;What : その負荷の特徴は？IOPS？throughput？方向(read/write) ？分散(や標準偏差)も込みで。&lt;/li&gt;
&lt;li&gt;How : その負荷には時間に依存したパターンがあるか？日時など。&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;2.5.11 Drill-Down Analysis&lt;/h4&gt;
&lt;p&gt;いわゆる段階的詳細化。以下の３段階がある。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Monitoring&lt;ul&gt;
&lt;li&gt;継続的にリソースの監視を行う。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Identification&lt;ul&gt;
&lt;li&gt;特定のリソースの挙動によって、ありうるボトルネックを特定する。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Analysis&lt;ul&gt;
&lt;li&gt;根本原因の特定と問題の定量化を試みる。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;「なぜは５回くりかえせ」…って、某自動車メーカーでも言っていますね。
ただし「５回」自体にはあまり意味はなくて、例えば "human error" で「なぜ」の追及をやめるな…等、あります。&lt;/p&gt;
&lt;h4&gt;2.5.12 Latency Analysis&lt;/h4&gt;
&lt;p&gt;１つのリクエストの処理を細かい部分処理に分解・分析していく。根本原因を特定・定量化できるように、最も時間のかかっている部分処理を調べる。&lt;/p&gt;
&lt;h4&gt;2.5.13 Method R (by Oracle)&lt;/h4&gt;
&lt;p&gt;Oracleのツール固有の話。SQL Query の 2.5.12 Latency Analysisに相当する。&lt;/p&gt;
&lt;h4&gt;2.5.14 Event Tracing&lt;/h4&gt;
&lt;p&gt;システムの動きは離散的なイベントの処理ということができる。ここでいうイベントとは、CPU命令とか、DISKコマンドとか、Networkパケットのような低レイヤのものから、SQLクエリなどもイベントとみなせる。&lt;/p&gt;
&lt;p&gt;性能分析とは、これらのイベントのサマリを検討することであり、例えば、単位時間あたりの操作、単位時間当たりのデータ量などが含まれるが、
サマリ（集計値）に詳細が埋もれてしまうこともある。&lt;/p&gt;
&lt;p&gt;例として、systemcallのトレース(strace)、I/Oトレース(Solarisのiosnoop)、パケットダンプ(tcpdump)が挙げられている。
…が、perf (というか BPF/eBPFや、昔は systemtap)を使うことによって、多彩な種類のイベントをイベント単位で知らべることもできる。&lt;/p&gt;
&lt;h4&gt;2.5.15 Baseline Statistics&lt;/h4&gt;
&lt;p&gt;基準になる性能値とその時の各種リソースの値等を採取しておくこと。&lt;/p&gt;
&lt;p&gt;これはまあPOCするときの基本ですね。&lt;/p&gt;
&lt;h4&gt;2.5.16 Static Peformance Tuning&lt;/h4&gt;
&lt;p&gt;静的性能チューニングは、例えば、NICのportが意図のリンク速度でLINK UPしているか？等の設定、状態を確認していくこと。&lt;/p&gt;
&lt;h4&gt;2.5.17 Cache Tuning&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;そもそもキャッシュ機能が有効になっているか？&lt;/li&gt;
&lt;li&gt;キャッシュのヒット率/ミス率&lt;/li&gt;
&lt;li&gt;キャッシュサイズが動的に変わる場合の現在のサイズ&lt;/li&gt;
&lt;li&gt;複数レイヤにキャッシュがある場合、処理をしている一番近くでキャッシュが効いているか？&lt;/li&gt;
&lt;li&gt;CPUキャッシュ(L1/L2/L3)の場合、レイヤごとに削れるレイテンシと効果が異なってくる。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2.5.18 Micro-Benchmarking&lt;/h4&gt;
&lt;p&gt;アプリケーションレベルだと負荷自体が複雑になりすぎて問題点がわかりにくいことも多いが、「ピンポン通信」等の、これ以上分解できないくらい細かい視点でのベンチマーク。&lt;/p&gt;
&lt;h3&gt;2.6 Modeling&lt;/h3&gt;
&lt;h4&gt;2.6.1 Enterprise versus Cloud&lt;/h4&gt;
&lt;p&gt;TBD&lt;/p&gt;
&lt;h4&gt;2.6.2 Visual Identification&lt;/h4&gt;
&lt;p&gt;性能特性をグラフにしてみると、特徴的なパターンがいくつかある。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Linear scalability (線形)&lt;/li&gt;
&lt;li&gt;Contention (競合)&lt;/li&gt;
&lt;li&gt;Coherence　(干渉)&lt;/li&gt;
&lt;li&gt;Knee point (適切な日本語が見つからないのだが、まあ折れているということ)&lt;/li&gt;
&lt;li&gt;Scalability Ceiling (天井にあたったように水平になってしまうこと)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2.6.3 Amdahl's Law of Scalability&lt;/h4&gt;
&lt;p&gt;いわゆるアムダールの法則。&lt;/p&gt;
&lt;p&gt;C(N) = N/(1 + α(N-1))&lt;/p&gt;
&lt;h4&gt;2.6.4 Universal Scalability Law&lt;/h4&gt;
&lt;p&gt;C(N) = N/(α(N-1) + βN(N-1))&lt;/p&gt;
&lt;h4&gt;2.6.5 Queueing Theory - 待ち行列理論&lt;/h4&gt;
&lt;p&gt;待ち行列大事。典型的には以下くらい？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;M/M/1&lt;/li&gt;
&lt;li&gt;M/M/c&lt;/li&gt;
&lt;li&gt;M/G/1&lt;/li&gt;
&lt;li&gt;M/D/1    &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.7 Capacity Planning&lt;/h3&gt;
&lt;p&gt;TBD&lt;/p&gt;
&lt;h4&gt;2.7.1. Resource Limits&lt;/h4&gt;
&lt;h4&gt;2.7.2 Factor Analysis&lt;/h4&gt;
&lt;h4&gt;2.7.3 Scaling Solutions&lt;/h4&gt;
&lt;h3&gt;2.8 Statistics&lt;/h3&gt;
&lt;p&gt;統計も大事。だが、TBD。&lt;/p&gt;
&lt;h4&gt;2.8.1 Quantifying Performance&lt;/h4&gt;
&lt;h4&gt;2.8.2 Averages&lt;/h4&gt;
&lt;p&gt;「平均値」って何種類もあるって意識していただろうか？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;アルキメデスの3平均&lt;ul&gt;
&lt;li&gt;Arithmetric - 算術平均(一番普通に使うやつ)&lt;/li&gt;
&lt;li&gt;Geometric - 幾何平均&lt;/li&gt;
&lt;li&gt;Harmonic 調和平均(Fの定義で出てきますね)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Averages over Time&lt;/li&gt;
&lt;li&gt;Decayed Average&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2.8.3 Standard Deviationos, Percentiles, Median&lt;/h4&gt;
&lt;h4&gt;2.8.4 Coefficient of Variation&lt;/h4&gt;
&lt;h4&gt;2.8.5 Multimodal Distributions&lt;/h4&gt;
&lt;h4&gt;2.8.6 Outliers&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Anomaly???&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.9 Monitoring&lt;/h3&gt;
&lt;h4&gt;2.9.1 Time-Based Patterns&lt;/h4&gt;
&lt;h4&gt;2.9.2 Monitoring Products&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Summary-since Boot&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.10 Visualizations&lt;/h3&gt;
&lt;h4&gt;2.10.1 Line Chart&lt;/h4&gt;
&lt;h4&gt;2.10.2 Scatter Plots&lt;/h4&gt;
&lt;p&gt;散布図の有用性をちゃんと意識している人って少ないような気がする。&lt;/p&gt;
&lt;h4&gt;2.10.3 Heat Maps&lt;/h4&gt;
&lt;h4&gt;2.10.4 Surface Plot&lt;/h4&gt;
&lt;h4&gt;2.10.5 Visualization Tools&lt;/h4&gt;
&lt;h3&gt;2.11 Exercises&lt;/h3&gt;
&lt;h3&gt;2.12 References&lt;/h3&gt;
&lt;h2&gt;13. Case Study : むかーし、Redis がナニモノかも知らなかった頃の話&lt;/h2&gt;</content><category term="tech"></category></entry><entry><title>[ja] back to basics - SRECon19 EMEA revisited, and beyond</title><link href="https://thatsdone.github.io/junkbox/backtobasics_srecon19emea_revisited.html" rel="alternate"></link><published>2020-01-13T12:21:00+09:00</published><updated>2020-01-13T12:21:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2020-01-13:/junkbox/backtobasics_srecon19emea_revisited.html</id><summary type="html">&lt;p&gt;SRE Methodologies&lt;/p&gt;</summary><content type="html">&lt;p&gt;さて、SRECon (や、USENIX LISA)では、ここしばらくCore Principles トラックという形で、
SREのチームの作り方やSREチームの運営のしかた…等といった話を多数聞くことができるわけですが、
&lt;a href="https://thatsdone.github.io/junkbox/srecon19emea.html"&gt;前に書いた記事&lt;/a&gt;で少し触れたように、
&lt;a href="https://www.usenix.org/conference/srecon19emea/"&gt;SRECon19EMEA&lt;/a&gt;の特徴だった、
運用まわりで使える確立した方法論の話をもう一回振り返ってみます。&lt;/p&gt;
&lt;h2&gt;まえおき&lt;/h2&gt;
&lt;p&gt;この記事はあと３回更新します。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;まずはポインタの一覧だけ(DONE)&lt;/li&gt;
&lt;li&gt;それぞれ解説(みたいなの)を追加&lt;/li&gt;
&lt;li&gt;SRECon の本筋の Core Princilple の話を追加&lt;/li&gt;
&lt;li&gt;日本発のback to basicな話の事例ということでTPSの話(これは別記事にするかも)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;運用まわりで使える back to basic な方法論&lt;/h2&gt;
&lt;p&gt;とりあえず、私が現地で聞いたセッションの中で気づいたものの一覧だけ。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Systems Theory -システム理論&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ja.wikipedia.org/wiki/%E5%88%B6%E5%BE%A1%E7%90%86%E8%AB%96"&gt;wikipedia(ja)&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.usenix.org/conference/srecon19emea/presentation/leveson"&gt;SRECon19EMEA セッション&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Speaker : Prof. Leveson, MIT&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Control Theory - 制御理論&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ja.wikipedia.org/wiki/%E5%88%B6%E5%BE%A1%E7%90%86%E8%AB%96"&gt;wikipedia(ja)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.usenix.org/conference/srecon19emea/presentation/hahn"&gt;SRECon19EMEA セッション&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Speaker : Ted Hahn, TCB Technologies, and Mark Hahn, Ciber Global&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Incident Command System - 現場指揮システム&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%82%B7%E3%83%87%E3%83%B3%E3%83%88%E3%83%BB%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%83%BB%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0"&gt;wikipedia(ja)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.usenix.org/conference/srecon19emea/presentation/hidalgo"&gt;SRECon19EMEA セッション&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Speaker : Alex Hidalgo and Alex Lee, Squarespace&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fault Tree Analysis - 故障木解析&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%83%84%E3%83%AA%E3%83%BC%E8%A7%A3%E6%9E%90"&gt;wikipedia(ja)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.usenix.org/conference/srecon19emea/presentation/falko"&gt;SRECon19EMEA セッション&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Speaker : Andrey Falko, Lyft&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Formal Verification Method - 形式的検証手法&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ja.wikipedia.org/wiki/%E5%BD%A2%E5%BC%8F%E7%9A%84%E6%A4%9C%E8%A8%BC"&gt;wikipedia(ja)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.usenix.org/conference/srecon19emea/presentation/khlaaf"&gt;SRECon19EMEA セッション&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Speaker : Heidy Khlaaf, Adelard LLP&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;SRE Core Principles&lt;/h2&gt;
&lt;p&gt;TBD&lt;/p&gt;
&lt;h2&gt;TPS : Toyota Production System - トヨタ生産方式&lt;/h2&gt;
&lt;p&gt;まずはとりあえず、関連情報のリンクだけ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;『トヨタ生産方式』ー脱規模の経営をめざしてー (大野耐一・著)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;https://www.amazon.co.jp/dp/4478460019/&lt;/li&gt;
&lt;li&gt;ISBN-10: 4478460019&lt;/li&gt;
&lt;li&gt;ISBN-13: 978-4478460016&lt;/li&gt;
&lt;li&gt;1978年5月25日 初版発行&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;参考&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;トヨタ生産方式のかんばん&lt;a href="https://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%B3%E3%83%90%E3%83%B3"&gt;ja&lt;/a&gt;/&lt;a href="https://en.wikipedia.org/wiki/Kanban"&gt;en&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ソフト開発のカンバン&lt;a href="https://ja.wikipedia.org/wiki/%E3%81%8B%E3%82%93%E3%81%B0%E3%82%93_(%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E9%96%8B%E7%99%BA)"&gt;ja&lt;/a&gt;/&lt;a href="https://en.wikipedia.org/wiki/Kanban_(development)"&gt;en&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</content><category term="tech"></category></entry><entry><title>[ja] Light Novels(2) - Princess Marines</title><link href="https://thatsdone.github.io/junkbox/book_light_novel2.html" rel="alternate"></link><published>2019-10-29T22:30:00+09:00</published><updated>2019-10-29T22:30:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2019-10-29:/junkbox/book_light_novel2.html</id><summary type="html">&lt;p&gt;Light Novels - 公爵家令嬢が海兵隊の新兵教育を受けたら!?&lt;/p&gt;</summary><content type="html">&lt;p&gt;さて、私が読んでいるラノベも、例にもれず異世界ファンタジーものが多いのですが、
このジャンルはパターン化したものがとても^2多いのも事実。&lt;/p&gt;
&lt;p&gt;一部の文章が軽妙で読みやすいものや設定が面白いもの以外は、さすがに食傷気味だったのですが、
ひさしぶりに面白いのを見つけました。&lt;/p&gt;
&lt;p&gt;これです。&lt;/p&gt;
&lt;p&gt;[まりんこ！～立ち塞がる敵はすべて倒す！ 不屈の悪役令嬢は異世界を海兵隊と駆け抜ける～]
(https://kakuyomu.jp/works/1177354054884156287)&lt;/p&gt;
&lt;p&gt;話は、いきなりヒロインの公爵家の令嬢が、婚約者だった第二王子様から婚約を破棄されてしまうところから始まります。
危機一髪…ということころで、従者の若者が(…といっても系列伯爵家の人間)に現代世界の人間の記憶が覚醒。
しかも、覚醒したのはアメリカ海兵隊の少佐の記憶だったのです。&lt;/p&gt;
&lt;p&gt;この従者（少佐？）、その場をなんとかおさめた後、主人の令嬢を自立させるためにとった策は、
なんと海兵隊の新兵教育(bootcamp)を施すことだったという(笑)&lt;/p&gt;
&lt;p&gt;この公爵令嬢、立派に新兵教育を勤め上げ、一人前の脳筋令嬢(?)として婚約破棄のショックを乗り越えて成長していきます。&lt;/p&gt;
&lt;p&gt;いやー、悪役令嬢に転生しちゃうパターンの話は、けっこうあるのですが、これは斜め上でした。この先が楽しみです。&lt;/p&gt;</content><category term="novel"></category></entry><entry><title>[ja] Film: Yesterday</title><link href="https://thatsdone.github.io/junkbox/movie_yesterday.html" rel="alternate"></link><published>2019-10-07T23:00:00+09:00</published><updated>2019-10-07T23:00:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2019-10-07:/junkbox/movie_yesterday.html</id><summary type="html">&lt;p&gt;Yesterday - 映画よもやま話&lt;/p&gt;</summary><content type="html">&lt;p&gt;Dublinへ行き返りの飛行機の中で久しぶりにゆっくり映画を観ました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.imdb.com/title/tt8079248/"&gt;Yesterday&lt;/a&gt; という映画ですが、これ、なかなかいいですね。&lt;/p&gt;
&lt;p&gt;改変世界…というか、普通に現代世界なのですが、あるとき突然世界中が12秒間 blackout する…という超常現象(?)が発生します。&lt;/p&gt;
&lt;p&gt;この超常現象の最中に交通事故にあった主人公は、周りの人が覚えていないナニカを自分だけが覚えていることに気づきます。&lt;/p&gt;
&lt;p&gt;実は「ナニカ」はたくさんあるのですが、売れないシンガーソングライターだった主人公にとっては
ビートルズが自分の記憶の中にしか残っていない…というのは重大なことでした。&lt;/p&gt;
&lt;p&gt;紆余曲折を経て、スターダムにのしあがる...けど、永らく応援してくれていた恋人とも離れ...苦悩する主人公の
前に現れたのは、他にもビートルズの記憶を残している夫婦だったのです。&lt;/p&gt;
&lt;p&gt;さてこの後どうなるか？…というような話です。&lt;/p&gt;
&lt;p&gt;主演の Himesh Patel さんの歌唱力もあいまって、オススメです。 :)&lt;/p&gt;
&lt;p&gt;ちなみに、この世界、ビートルズ以外にも消えた存在がいくつかあります。
例えば、Coca Cola は存在しないので、コーラを飲みたい時は "Pepsi ちょうだい" と言わないといけません。
そのほか、Harry Potter も存在しないのですが、ヒロインを演じた女優さんが &lt;strong&gt;Lily&lt;/strong&gt; &lt;strong&gt;James&lt;/strong&gt; さんだと知った時、
「あっ！」と思ってしまったのは私だけでしょうか(謎)&lt;/p&gt;
&lt;p&gt;ヒント: Harryの両親 (と、長男・長女も)の名前&lt;/p&gt;</content><category term="movie"></category></entry><entry><title>[ja] Schengen Agreement and Ireland/UK</title><link href="https://thatsdone.github.io/junkbox/schengen_aggement_and_ireland.html" rel="alternate"></link><published>2019-10-06T01:30:00+09:00</published><updated>2019-10-06T01:30:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2019-10-06:/junkbox/schengen_aggement_and_ireland.html</id><summary type="html">&lt;p&gt;SRECon19EMEA&lt;/p&gt;</summary><content type="html">&lt;p&gt;さて、Ireland の Dublin で開催された &lt;a href="https://www.usenix.org/conference/srecon19emea"&gt;USENIX SRECon19 EMEA&lt;/a&gt;に参加していたわけですが、今回、行きは Frankfurt 乗り継ぎ、帰りは Dusseldorf の乗り継ぎでした。&lt;/p&gt;
&lt;p&gt;前に、Air France の CDG 乗り継ぎで Barcelona に行ったことがあるのですが、あの時はCDGで入国審査だったので、今回も同じ…とおもいきや、
Dublin で入国審査だったので(?_?)状態でした。&lt;/p&gt;
&lt;p&gt;知人と話していたところ、実は、アイルランドとイギリスはシェンゲン協定に参加していないため、他のEUの国どうしのように
最初に入った国で入国審査をするわけではなく、国際線乗り継ぎになるとのこと。知りませんでした。&lt;/p&gt;
&lt;p&gt;https://en.wikipedia.org/wiki/Schengen_Agreement&lt;/p&gt;
&lt;p&gt;あるいは&lt;a href="https://ja.wikipedia.org/wiki/%E3%82%B7%E3%82%A7%E3%83%B3%E3%82%B2%E3%83%B3%E5%8D%94%E5%AE%9A"&gt;日本語版&lt;/a&gt;を眺めていると経緯がわかります。&lt;/p&gt;
&lt;p&gt;陸路でつながった国同士は簡略化したほうが便利だけど、島国はまた事情が異なる…というのがイギリスの意向らしいです。
ちな、アイルランドは参加の意向はあるのだけど、北アイルランドとの国境がめんどくさくなるのでまだ実現していないのだとか。&lt;/p&gt;
&lt;p&gt;ちな、この記事は Dusseldorf の空港(しかも、Passport Control の外側)で書いています(笑)&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>[ja] SRECon19 EMEA</title><link href="https://thatsdone.github.io/junkbox/srecon19emea.html" rel="alternate"></link><published>2019-10-03T14:30:00+09:00</published><updated>2019-10-03T14:30:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2019-10-03:/junkbox/srecon19emea.html</id><summary type="html">&lt;p&gt;SRECon19EMEA&lt;/p&gt;</summary><content type="html">&lt;p&gt;アイルランドのダブリンで開催中の &lt;a href="https://www.usenix.org/conference/srecon19emea/"&gt;SRECon19EMEA&lt;/a&gt; に来ています。&lt;/p&gt;
&lt;p&gt;ダブリンは初めてで、気温をみて寒そう…とは思っていたのですが、10月頭でもう冬みたいな恰好をしている人が多いとは想像しておらず、
正直、外は寒いです(苦笑)&lt;/p&gt;
&lt;p&gt;初日で一番面白かったのはGoogleの Todd Underwood さんの以下のセッションでしょうか。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.usenix.org/conference/srecon19emea/presentation/underwood"&gt;All of Our ML Ideas Are Bad (and We Should Feel Bad)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;MLを使って運用をラクにしたい…というのはけっこう誰でも考える話で、適用対象としては例えば以下のようなものがあるでしょう&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Categorizing/Prioritizing Tickets&lt;/li&gt;
&lt;li&gt;Root Cause Analysis&lt;/li&gt;
&lt;li&gt;Canary Analysis&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;しかし、実際に使ってみると...&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;(MLよりも)もっといい方法ある&lt;/li&gt;
&lt;li&gt;データが足りない&lt;/li&gt;
&lt;li&gt;ラベル付きのデータが足りない&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;といった理由でうまくいかないことがよくあります。&lt;/p&gt;
&lt;p&gt;Todd さんは、これは流行りのやり方を、深く考えずにそのまま使おうとするからだ…と言います。
よく言われる ML というのは、Marketing ML だと。&lt;/p&gt;
&lt;p&gt;Todd さんのおすすめはこんなふうにまとめられます。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Think&lt;ul&gt;
&lt;li&gt;あなたのアプリ、インフラ、お客さんをよく知る人に話を聞きましょう。&lt;/li&gt;
&lt;li&gt;そして、それらを理解するためのアイデアを出すためにブレストをしましょう。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Gather&lt;ul&gt;
&lt;li&gt;まずはデータを一か所にあつめる。&lt;/li&gt;
&lt;li&gt;整理してみないとなにもできないので、とにかく整理する。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Learn&lt;ul&gt;
&lt;li&gt;まずは基本を押さえましょう。&lt;/li&gt;
&lt;li&gt;MLワークロードを動かすプラットフォームは既にたくさんあるので、こういうものを知りましょう。&lt;/li&gt;
&lt;li&gt;そして、集めたデータを使ってプロトタイプをやってみましょう。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;もっと先まで踏み込む場合は&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ontology&lt;/li&gt;
&lt;li&gt;Epistemology&lt;/li&gt;
&lt;li&gt;Metaphysics&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;の３点を挙げていました。用語は難しいですが、一言で言うと「自分の頭で本質をよく考えろ」ってことですね。 :)
具体的にこうしたらうまくいっているよ…という事例紹介ではありませんが、考え方として、私にはとても参考になったtalkでした。&lt;/p&gt;
&lt;p&gt;Day1 だけでも他にもいろいろ興味深い講演がありました。
例えば、Network trouble の解析の紹介で、よく聞いてみたら eBPF でがんばってCloud Providerにも認めさせたぜ...という
「よくある」話だったりとか(笑)
ぼちぼち更新しようかと思います。&lt;/p&gt;
&lt;p&gt;Stay Tuned ! :)&lt;/p&gt;
&lt;p&gt;2019/10/04 (Dublin現地時間)追記&lt;/p&gt;
&lt;p&gt;SRECon19EMEA、無事に終了しました。
ハリケーンが来ていてアイルランド直撃が予測されいたのですが、大した影響なく済んでよかったです。&lt;/p&gt;
&lt;p&gt;closing での主催者の話によると、今回の出席者は約700名とのこと。3月のNorth Americaでは4桁に届くでしょうか。&lt;/p&gt;
&lt;p&gt;3日間終わってみての所感は、初日のkeynoteのLeverson教授の Systems Theory からはじまり、
Control Theory (制御理論)、Fault Tree Analysis といった、数十年前に確立された理論を振り返る話が多かったことです。
果ては一番最後のセッションが Formal Verification Method...ということで、Program Committee の心意気を感じたように思います。&lt;/p&gt;
&lt;p&gt;私は主に Core Principle の Track に出ていました。具体的にこの手法でうまくいったよ…という話もあることはありましたが、
むしろ Silver Bullet はない。利用者のことをよく知り、自分の頭で考えるべし。ついてはその指針は…という話を多く聞くことができました。
現状の私には非常に参考になる話でした。&lt;/p&gt;
&lt;p&gt;3月の SRECon '20 North America はスケジュールの都合で出席できないのですが、来年度もどれかのSREConに顔を出したいと思います。 :)&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[ja] Light Novels</title><link href="https://thatsdone.github.io/junkbox/book_light_novel1.html" rel="alternate"></link><published>2019-09-29T18:00:00+09:00</published><updated>2019-09-29T18:00:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2019-09-29:/junkbox/book_light_novel1.html</id><summary type="html">&lt;p&gt;Light Novels, so called La-Nobe in Japan / ラノベ話(その１)&lt;/p&gt;</summary><content type="html">&lt;p&gt;ここ１年ほど、隙間時間はラノベを読んでいることが多いです。&lt;/p&gt;
&lt;p&gt;その昔は、ラノベは敬遠していたのですが、幼女戦記のアニメをチラ見した後、原作を読み、他にも…といろいろ読みはじめたらハマってしまいました(笑)&lt;/p&gt;
&lt;p&gt;これまで読んだものはけっこうな量になるのですが、以下はとりあえず印象に残ったもののリストです。そのうちもっと増やすかも(笑)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.mai-net.net/bbs/sst/sst.php?act=dump&amp;amp;cate=tiraura&amp;amp;all=24734"&gt;幼女戦記&lt;/a&gt; (完結済)&lt;ul&gt;
&lt;li&gt;言わずと知れた「幼女戦記」の原点。転生もの。コミックもアニメも好きですが、私はやっぱりこれが一番面白いですかねぇ。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/4852201425154885756"&gt;魔法大学院第三呪術研究室には研究費がない&lt;/a&gt; (完結済)&lt;ul&gt;
&lt;li&gt;研究者ファンタジーとでも言えるでしょうか。これは転生は関係なく、自然科学に魔法とか呪術とかが普通に混ざりこんだ世界での博士課程の学生の奮闘話。「『魔研費』におちた」...とか、泣けます。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054887903142"&gt;辺境の老騎士&lt;/a&gt; (完結済)&lt;ul&gt;
&lt;li&gt;グルメファンタジーとか言われているようです。これも転生は関係なく、辺境で隠居した...はずの老騎士が活躍する話。後半SFっぽくなります。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054886942969"&gt;この争いの絶えない世界で　～魔王になって平和の為に戦います&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;転生もの。転生先で魔王になりますが、よくある異世界ファンタジーとは趣がだいぶ異なります。キーワードは「魔王というシステム」でしょうか。とても面白いです。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054884195461"&gt;公女殿下の家庭教師&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;転生もなしの、普通の異世界ファンタジー。ストーリーが面白いのと、軽妙な語り口で人気があり、書籍版も出ているようです。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054885338663"&gt;転生したらスキルになっていた！？　～　モニカの奇妙な相棒　～&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;転生もの。ただし、普通は主人公本人に転生するわけですが、転生先の魔法ファンタジー世界のキャラクタが使う「スキル」に転生したというのが他と違うところです。これもすごく面白いです。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054885639750"&gt;ジェミノシストーリア　～化学で捗る魔術開発～&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;転生もの。化学研究者がファンタジー系の異世界転生する話。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054880833903"&gt;異世界城主、奮闘中！　～ガチャ姫率いて、目指すは最強の軍勢～（旧題ガチャ姫）&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;転生もの。「仲間、ダイジ！」系、かつハーレムっぽいですが、面白いです。'19/9時点で作者の方は新作に力を入れているようで更新停止中ですが、再開されないかなぁ。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054882530555"&gt;リビルドワールド&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;SF。ミュータントが跋扈する未来世界で、旧世界の秘密にヒロイン(?)と一緒に挑むハンターの話。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054885808737"&gt;鉄錆びの女王機兵&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;SF。ミュータントが跋扈する近未来世界で、四肢を戦車に接続して戦うヒロインと、不器用なハンターの話。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054883170654"&gt;異邦人、ダンジョンに潜る。&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;転生...ではなく、魔法な異世界に送り込まれたところが違うところ。SFのような異世界ファンタジーのような話。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054880231475"&gt;Hi-G. -ハイスピードガールズ ディスタンス-&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;21世紀の女子高生(ただし、戦闘素養は抜群？)が2500年後に転移(?)した話。スぺオペ…かな。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054888551001"&gt;神様のモニタリング　～人類滅亡回避のススメ～&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;転生もの。転生させる神様が被転生者のモニタリングをしている…という設定。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054886331107"&gt;放浪者達の狂騒曲&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;転生...というか、だいぶ未来の異惑星(だだし、地球から軍隊を送り込まれて数百年)に転移(?)した主人公が、だいぶ昔に地球から送り込まれたAI搭載野良(?)戦車と現地で頑張る話。アニメ系の各種ネタ満載ですが、私は半分もついていけません(笑)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ncode.syosetu.com/n4343eh/"&gt;ソ連の宇宙技術は最強過ぎたのだが、それを西側諸国が完全に理解したのはつい最近だった&lt;/a&gt; (完結済)&lt;ul&gt;
&lt;li&gt;ラノベ(?)としては変わりダネ。最初見た時、宇宙技術系の知る人ぞ知るうんちく解説記事だと思ったのですが、まさかweb小説だったとは...(笑)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054884501019"&gt;異世界辺境経営記&lt;/a&gt; (完結済)&lt;ul&gt;
&lt;li&gt;転生もの。異世界「経済」ファンタジー…かな？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakuyomu.jp/works/1177354054887659844"&gt;空言ミストノーツ&lt;/a&gt; (完結済)&lt;ul&gt;
&lt;li&gt;異世界ファンタジー。転生なし。この世界観、とても好き。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</content><category term="novel"></category></entry><entry><title>[ja] BGP in the Data Center</title><link href="https://thatsdone.github.io/junkbox/book_bgp_in_the_datacenter.html" rel="alternate"></link><published>2019-09-21T20:00:00+09:00</published><updated>2019-09-21T20:00:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2019-09-21:/junkbox/book_bgp_in_the_datacenter.html</id><summary type="html">&lt;p&gt;BGP in the Data Center&lt;/p&gt;</summary><content type="html">&lt;p&gt;一部で話題の O'reily の "BGP in the Data Center" を読んだ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[https://www.oreilly.com/library/view/bgp-in-the/9781491983416/(https://www.oreilly.com/library/view/bgp-in-the/9781491983416/)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これは面白い…というか、自分が今やってること的にとても勉強になったのでメモ。&lt;/p&gt;
&lt;p&gt;日本語の他の方の記事もけっこうあるようだ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://foobaron.hatenablog.com/entry/bgp-in-the-data-center-01"&gt;https://foobaron.hatenablog.com/entry/bgp-in-the-data-center-01&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.bobuhiro11.net/2019/03-21-bgp-in-the-data-center.html"&gt;https://blog.bobuhiro11.net/2019/03-21-bgp-in-the-data-center.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;遡ると'14の JANOG33 で Microsoft の人が講演していたりとか。(時期はこの本よりも早い)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.janog.gr.jp/meeting/janog33/program/bgp.html"&gt;https://www.janog.gr.jp/meeting/janog33/program/bgp.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1. Introduction to Data Center Networks&lt;/h3&gt;
&lt;p&gt;物理構成の話。L3 Leaf-Spine 型のNWの構成のベストプラクティスの解説。&lt;/p&gt;
&lt;h3&gt;2. How BGP Has Benn Adapted to the Data Center&lt;/h3&gt;
&lt;p&gt;物理構成ができたら、その上の routing をどうやるのか？の話。BGP話。&lt;/p&gt;
&lt;p&gt;しかし、BGPの Best Path Algorithm が参照する metric が8つあって、それを覚えるのにこんなのがあるとは知らなかったw
Cisco(当時?)の Denise Fishburne さんが考えたらしい。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;mnemonic&lt;/th&gt;
&lt;th&gt;-&lt;/th&gt;
&lt;th&gt;BGP metric&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Wise&lt;/td&gt;
&lt;td&gt;W&lt;/td&gt;
&lt;td&gt;Weight&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lisp&lt;/td&gt;
&lt;td&gt;L&lt;/td&gt;
&lt;td&gt;LOCAL_PREFERENCE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lovers&lt;/td&gt;
&lt;td&gt;L&lt;/td&gt;
&lt;td&gt;Locally Originated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apply&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;AS_PATH&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Oral&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;ORIGIN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Medication&lt;/td&gt;
&lt;td&gt;M&lt;/td&gt;
&lt;td&gt;MED&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Every&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;eBGP over iBGP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Night&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;td&gt;NextHop IGP Cost&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;(うー、Pelican の調整がまだ不完全で border が出ないな...)&lt;/p&gt;
&lt;h3&gt;3. Building an Automatable BGP Configuration&lt;/h3&gt;
&lt;p&gt;各router (というか、TOR/Leaf/Spine等スイッチ)の BGP 設定は、
愚直に書くと機器ごとに個別の設定や、個別の機器内でも重複した記述が多数出てくるわけだが、
これを自動化のためにカイゼンできるか？の解説。&lt;/p&gt;
&lt;p&gt;Spine側のASNの割り当てはちょっと誤解していたところがあった...&lt;/p&gt;
&lt;h3&gt;4. Reimaging BGP Configuration&lt;/h3&gt;
&lt;p&gt;3章の解説でもろもろ設定を単純化したとして、まだ以下のような pain point がある。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NW機器間(というか、ホストも含むかな...)のインターフェースに付与して管理するのは大変。&lt;/li&gt;
&lt;li&gt;隣(neighbour)のASの定義をいちいち書くのも大変。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一つ目の問題の解決として、(IPv6) Un-Numbered の解説。&lt;/p&gt;
&lt;p&gt;二つめの問題の解決として、remote-as 構文の拡張の external / internal を使う方法の解説。&lt;/p&gt;
&lt;p&gt;ちな、僕が読んだバージョンの p58 の Figure 4-2 の下半分の図は 10.1.1.0/24 じゃなくて、10.1.2.0/24 だと思う。&lt;/p&gt;
&lt;h3&gt;5. BGP Life Cycle Mamagement&lt;/h3&gt;
&lt;p&gt;状態表示でよく使うコマンドのほか、メンテのために停止させたい時の常套手段と、デバッグのやりかた。&lt;/p&gt;
&lt;p&gt;デバッグ用の機能を使って、経路計算のロジックを勉強する…というのもあるのか。&lt;/p&gt;
&lt;h3&gt;6. BGP on the Host&lt;/h3&gt;
&lt;p&gt;この構成で本格的に動かす場合、ホストも BGP をしゃべることになるわけで、
今までのSEとNEという境界もあいまいになるよね…という話。&lt;/p&gt;
&lt;p&gt;そのほか、Anycast 話とか、Dynamic Neighbour とか。&lt;/p&gt;
&lt;p&gt;そういえば、題材に使われている &lt;a href="https://frrouting.org/"&gt;FRR&lt;/a&gt; を使い込む…
というタスクもあったのだが、再開せねば...(とおいめ&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[ja] Stray Sheep - OpenShift and CloudFoundry</title><link href="https://thatsdone.github.io/junkbox/openshift_and_cloudfoundry.html" rel="alternate"></link><published>2019-09-14T15:01:00+09:00</published><updated>2019-09-14T15:01:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2019-09-14:/junkbox/openshift_and_cloudfoundry.html</id><summary type="html">&lt;p&gt;Stray Sheep - OpenShift and Cloud Foundry (again?)&lt;/p&gt;</summary><content type="html">&lt;p&gt;こんな記事が話題になっているようだ。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://techcrunch.com/2019/09/12/together-at-last-ibm-brings-cloud-foundry-to-red-hat-openshift/"&gt;IBM brings Cloud Foundry and Red Hat OpenShift together&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;オレPaaSはこれだぜ…といって始まったはずが、kubernetes 使うならOpenShift…に言うことが全然変わり、そしてまた Cloud Foundry ですか…迷える子羊さんだなー…というのが第一印象。&lt;/p&gt;
&lt;p&gt;とはいえ、API(と、それで制御されるざっくりした構造も…かな)だけ維持して、既存のk8sベースのインフラでCF用に作られたアプリケーションを収容できるようにするというのは自然な発想と言えるかなと思うのだが、この動きって最初から計画されていたのか、それとも Cloud Foundry に大々的に投資していたIBMの意向なのか、どちらなんでしょう？
あと、OpenShiftの場合、Kuryr とか使ってOpenStackと並べて動かすみたいな話もあるようだし、ただでさえ重量級な
OpenShiftがますます複雑化しそうな雰囲気なのがちょっと...(とおいめ&lt;/p&gt;
&lt;p&gt;余談だけど、OpenShift の歴史、特に v1 と v2 の頃ってどんなんだっけ？とググっていたらこんな記事も出てきた。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://developer.ibm.com/blogs/a-brief-history-of-red-hat-openshift/"&gt;A brief history of Kubernetes, OpenShift, and IBM&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これって、8/1付の記事なのだけど、最初の記事が 9/11-12の Cloud Foundry Summit 2019での &lt;em&gt;IBM&lt;/em&gt; による発表の記事なので、情報は先に出ていた...ということですか。&lt;/p&gt;
&lt;p&gt;ところで、１つめの記事から、こんな記事もリンクされていた。&lt;/p&gt;
&lt;p&gt;[With its Kubernetes bet paying off, Cloud Foundry doubles down on developer experience]
(https://techcrunch.com/2019/09/09/with-its-kubernetes-bet-paying-off-cloud-foundry-double-down-on-developer-experience/)&lt;/p&gt;
&lt;p&gt;Fortune 500に載る会社の50%以上がCloud Foundry使っているって本当？…というのはおいておいて、
PivotalもCloud Foundryをk8sの上で動かすぜー…なんて言っていたのね。知りませんでした...orz&lt;/p&gt;
&lt;p&gt;&lt;a href="https://content.pivotal.io/announcements/pivotal-makes-kubernetes-easier-for-developers-and-operators"&gt;Pivotal Makes Kubernetes Easier for Developers and Operators&lt;/a&gt;&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[ja] Science</title><link href="https://thatsdone.github.io/junkbox/on_science.html" rel="alternate"></link><published>2019-09-12T23:00:00+09:00</published><updated>2019-09-12T23:00:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2019-09-12:/junkbox/on_science.html</id><summary type="html">&lt;p&gt;Scientific topics&lt;/p&gt;</summary><content type="html">&lt;p&gt;私は物理系の出身ということもあって、テクノロジ系だけではなく自然科学系の話題にも興味があります。&lt;/p&gt;
&lt;p&gt;最近気になった記事だとたとえばこんなのがありました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://singularityhub.com/2019/04/24/new-lifelike-biomaterial-self-reproduces-and-has-a-metabolism/"&gt;"New Lifelike Biomaterial Self-Regenerates and Has a Metabolism"&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;生物の要件の１つである自己複製を行うようなものを作り出したと。
メカニズムとして、生成と破壊が同時進行する新陳代謝の機能を備えている...というわけで、これって既に、Virus よりも普通の生き物に近いと思うのですが、そうすると、"life-like" と "alive" の境界ってなんだろう...とか思うわけです。&lt;/p&gt;</content><category term="science"></category></entry><entry><title>[ja] On OpenSDS</title><link href="https://thatsdone.github.io/junkbox/opensds.html" rel="alternate"></link><published>2019-09-03T00:00:00+09:00</published><updated>2019-09-03T00:00:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2019-09-03:/junkbox/opensds.html</id><summary type="html">&lt;p&gt;My recent OpenSDS related activities&lt;/p&gt;</summary><content type="html">&lt;p&gt;最近は趣味と実益を兼ねて &lt;a href="https://opensds.io/"&gt;OpenSDS&lt;/a&gt; をいじっています。&lt;/p&gt;
&lt;p&gt;OpenSDS は、名前からして「また新しい Software Defined Storage の実装ですか？」と聞かれるのですが、実は複数のストレージコントローラをたばねるものです。
block storage から出発して、今はNFSのような file storage や Object Storage もサポートしています。&lt;/p&gt;
&lt;p&gt;その昔いじっていたOpenStackも sub project がたくさんありましたが、OpenSDS もだいぶにぎやかになってきました。&lt;/p&gt;
&lt;p&gt;この中では telemetry と anomaly-detection (仕事的には multi-cloudも) に興味があるのですが、まずは簡単に使えるようにしなくちゃね...ということで、
githubの私のページの activity を見てもらってもわかる通り、
opensds-installer をせっせと直しています。まずは ansible で、helm chart はその次ですかね...&lt;/p&gt;
&lt;p&gt;余談ですが、現在、OpenSDSの認証には OpenStack の Keystone が導入されています。
Keystone の場合、認証した結果に各種関連サービスの endpoint の一覧が返却される
という変わった(?)仕様なのですが、このあたり、どこまで integration するかは
まだやわらかいようです。&lt;/p&gt;</content><category term="tech"></category></entry><entry><title>[en/ja] Resuming github pages</title><link href="https://thatsdone.github.io/junkbox/resuming.html" rel="alternate"></link><published>2019-09-02T22:50:00+09:00</published><updated>2019-09-02T22:50:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2019-09-02:/junkbox/resuming.html</id><summary type="html">&lt;p&gt;resuming this page after several years interval&lt;/p&gt;</summary><content type="html">&lt;p&gt;[en]
I'm resuming this github page after several years interval.
Recent my (technical) interests are below.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Connected Cars /Autonomous Cars&lt;/li&gt;
&lt;li&gt;Open Source&lt;/li&gt;
&lt;li&gt;MLOps&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;[ja]
数年ぶりにこのページの更新を再開しようと思います。
最近の興味は以下のような感じです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Connected Cars /Autonomous Cars&lt;/li&gt;
&lt;li&gt;Open Source&lt;/li&gt;
&lt;li&gt;MLOps&lt;/li&gt;
&lt;li&gt;等&lt;/li&gt;
&lt;/ul&gt;</content><category term="misc"></category></entry><entry><title>About Me</title><link href="https://thatsdone.github.io/junkbox/about.html" rel="alternate"></link><published>2019-09-01T00:00:00+09:00</published><updated>2019-09-01T00:00:00+09:00</updated><author><name>thatsdone</name></author><id>tag:thatsdone.github.io,2019-09-01:/junkbox/about.html</id><summary type="html">&lt;p&gt;about me&lt;/p&gt;</summary><content type="html">&lt;p&gt;I'm a kind of software engineer and researcher.&lt;/p&gt;
&lt;p&gt;Since April of 2018, I'm working on mainly infrastructure things shooting for
DataCenter side of Connected Car/Autonomous Car systems.&lt;/p&gt;</content><category term="misc"></category></entry></feed>