メインコンテンツに進む

チラシの表の反対側

development

Linuxのreadとrecvは何が違うのか

2023-01-25
man 2 recv [Enter]ターン The only difference between recv() and read(2) is the presence of flags. With a zero flags argument, recv() is generally equivalent to read(2) (but see NOTES). (適当な訳) recv() と read(2) の違いは flags の有無のみです。flags が 0 のとき、recv() はほとんどの場合 read(2) と等価になります。 おわり というのもアレなので Linux kernel のソースを読んでどうなっているのか見てみることにしました。 僕は Linux ニワカなので見当違いなことを言っている可能性もあるのでまあそういうつもりで読んでいただけると……。 Linux のソースコードはたまたま手元にあったやつなので超適当ですが、よく見たら 2020 年のやつでした(思ったより古かった) Linux のシステムコールは SYSCALL_DEFINEn みたいなマクロで定義するので、適当に grep します。 すると read は fs/read_write.c recv は net/compat.c にあることが分かりま… 続きを読む

Mesonのコードを読む (1)

2023-01-07
お久しぶりです。 どうでもいいことを気軽に書けるように(ブログサービスではなく)自分のブログを作っているのに、あんまり気軽に書けてないなと感じている今日この頃です。 で、普段からどうでもいいことを書いていないとどうでもいいことも書きづらくなってしまうな(?)と思ったわけで、質にはこだわらずにどうでもいい記事をぽんぽん出していこうと 思ったわけですね。でも書くからには何かネタがないと厳しいなというわけで、適当にそのへんの OSS のコードを読んでそれを記事にするというのをひとまず続けてみようと思っています。 コード読んで解説くらいだったらそんなに負荷も高くないので続けられそうという希望的観測もあります。 あと他人… 続きを読む

Meson で subproject のオプションを指定する方法

2022-12-31
備忘録。 出てこないなーとか思ってたら普通に書いてあった。 単に -D で指定するときに subproject名:オプション名 というふうに指定すればいいだけだった。 例えば subproject hoge でだけ warning_level を 3 にしたい場合は $ meson configure -Dhoge:warning_level=3 のように指定すれば ok。 ちなみにモジュール (meson.build の中で import とかして使うやつ) ごとのオプションは . で区切る。 なので pkgconfig の relocatable を true にする場合とかは -Dpkgconfig.relocatable=true とかを指定すればいい。 参考 Built-in options

CentOS 7 (rootなし) でLLVM 15をビルドする方法

2022-09-20
入ってるパッケージが諸々古すぎるので、周辺のライブラリのビルドから始める必要がある。 そのへんを自動でやってくれるようにシェルスクリプトにまとめた。 /tmp に tmpfs がいなかったり、ホームディレクトリが NFS だったりする環境のものなので、_build_dir 系の変数は変更して使ったほうがいいと思う。 ビルド手順 まず、標準で入っている GCC は LLVM をビルドするには古すぎるので、GCC のビルドから始める必要がある。 古い LLVM から徐々にバージョンアップしていく方法でもいいが、最新の GCC はビルドできるので。ついでに GCC も最新にしてやる方が首尾が良いと思う。 で、最新の GCC をビルドするには周辺のライブラリが古すぎるので、最初にとりかかるべきは… 続きを読む

mallocをフックしてメモリ使用量を測る

2022-09-16
いろいろと怪しいけどこれでフックすれば取れるはず。 まあ malloc をフックしている時点で怪しいので細かいことを気にしてはいけない (?) #define _GNU_SOURCE #include <dlfcn.h> #include <string.h> #include <stdio.h> static size_t max_usage; static size_t cur_usage; static void *(*orig_malloc)(size_t); static void (*orig_free)(void *); static void *(*orig_realloc)(void *, size_t); __attribute__((constructor)) void initialize(void) { orig_malloc = dlsym(RTLD_NEXT, "malloc"); orig_free = dlsym(RTLD_NEXT, "free"); orig_realloc = dlsym(RTLD_NEXT, "realloc"); } extern char *__progname; __attribute__((destructor)) void print_stat(void) { size_t result = max_usage; fprintf(stderr, "%s: max memory usage: %zu\n", __progname, result); } void *malloc(size_t size) { void *ptr = orig_malloc(size + sizeof(size_t)); if (ptr == NULL) { return NULL; } memcpy(ptr, &size, sizeof(size_t)); cur_usage += size; if (cur_usage > max_usage) { max_usage = cur_usage; } return (void *)((unsigned char *)ptr + sizeof(size_t)); } void *calloc(size_t nmemb, size_t size) { void *ptr = malloc(nmemb * size); if (ptr != NULL) { memset(ptr, 0, size * nmemb); } return ptr; } void free(void *ptr) { if (ptr == NULL) { return; } void *head = (void *)((unsigned char *)ptr - sizeof(size_t)); size_t size; memcpy(&size, head, sizeof(size_t)); cur_usage -= size; orig_free(head); } void *realloc(void *ptr, size_t size) { size_t old_size = 0; void *result; if (ptr != NULL) { void *head = (void *)((unsigned char *)ptr - sizeof(size_t)); memcpy(&old_size, head, sizeof(size_t)); result = orig_realloc(head, size + sizeof(size_t)); } else { result = orig_realloc(ptr, size + sizeof(size_t)); } if (result != NULL) { cur_usage -= old_size; cur_usage += size; if (cur_usage > max_usage) { max_usage = cur_usage; } memcpy(result, &size, sizeof(size)); return (void *)((unsigned char *)result + sizeof(size_t)); } return NULL;… 続きを読む

ELF ファイルを適当に編集する方法

2022-09-16
patchelf を使うと一発。elfedit というコマンドが binutils にあるっぽかったが、使い方がイマイチ分からなかった。 RPATH の追加 $ORIGIN/../lib を追加する例。ちなみに $ORIGIN はファイルがあるディレクトリを指すので、絶対パスを使うより柔軟にパスの指定ができる。 $ patchelf --add-rpath '$ORIGIN/../lib' NEEDED の追加 $ patchelf --add-needed libhoge.so.0 RPATH と NEEDED を組み合わせると LD_PRELOAD 的なことが環境変数なしでできる 下みたいな内容で適当なライブラリを作る。 int puts(const char *s) { return 0; } で、下みたいな内容の実行ファイルに patchelf する。 #include <stdio.h> int main(void) { puts("hoge"); } $ ./hoge hoge $ patchelf --add-rpath '$ORIGIN/lib' $ patchelf --add-needed 'libhoge.so.0' $ ./hoge (何も出ない) 実用性があるかは謎。

QEMUで雑に作るArch Linux ARMビルド環境

2022-04-04(最終更新: 2022-04-05)
QEMU で起動するのが楽な Alpine Linux で aarch64 な Linux 環境を作り、 その中でブートストラップした Arch Linux ARM に chroot して使ってやろうというもの。 Alpine も Arhc も小さいのでビルドしようとするものによるが、tmpfs だけで戦える可能性が十分ある。 bazel と mozc のビルドをやったが、16 GB メモリのマシンで tmpfs しか使わずに作業が終わった (ビルド後にいらなくなった一時ファイルを消したりはしたが)。 準備 aarch64 の仮想マシンの実行には qemu-arch-extra が必要なので事前に入れておく。 Alpine のイメージを公式サイトから落としておく。 多分どれでもいいが、今回は standard を使った。 UEFI を使うため、edk2-armvirt を入れる。 QEMU のイメージの準備 サイズとかは適当に。後で拡張したりできるので大袈裟に気にす… 続きを読む

Elasticsearchでサイト内検索できるようにしてみた

2022-03-18
このサイトは静的サイトジェネレータの Hugo を使って生成していて、これまで検索欄は Google 検索に site: をつけてクエリを投げるという方法で実現されていました (これは使っているテーマのデフォルトだったため)。 それを今回、Google に飛ばずに自前で検索を行うという感じにしました。 モチベーション Google 検索での一番の問題は、「サイト内のすべてのページにタグ一覧が配置されているために、 キーワードがタグ名と一致する場合すべてのページがヒットしてしまう」という点でした。 Google 検索で検索に使う範囲を指定できればよいのですが、そういったこともできそうになく、 自前で検索する必要性を感じていました。 あと、サイト内の情報が知りたいだけなのに… 続きを読む

エミュレータについて

2022-01-31(最終更新: 2022-02-25)
遊びで作っているエミュレータについていろいろまとめておこうかなというだけの投稿。 実験で作った CPU のエミュレータです。 最初は実機でデバッグするのが辛いだろうということでアセンブラに簡易的な実行機能を つけようといった程度のモチベーションで始めたんですが、デバッガの実装が意外に面白かったので だんだん機能が増えてきているという感じです。 機能 今の所こんな感じです。 アセンブリで書いたプログラムを実行する 分岐命令の飛び先のアドレスをラベルで指定できる メモリの初期化ファイルに書かれた内容で内部のメモリを初期化 命令のアドレスにブレークポイントを置く 実行した命令をもとに戻す (Undo) 未定義動作を踏みそうになったら例外を飛ば… 続きを読む

Emacs内のターミナルでのEmacsの実行をいい感じにした

2021-11-30
ちょっと前ですが、「Emacs 内のターミナルで Emacs を開こうとしたら既に開いている Emacs でそのファイルを開く」やつを作りました。 しくみ ざっくり説明すると、DBus を使って Emacs とシェル (で立ち上がるプロセス) が通信して、 Emacs を開く代わりに現在のセッションで開いているように見せるという感じになります。 通信できるなら別に DBus じゃなくてソケットでもいいんですが、DBus だと Emacs Lisp の インターフェースでサーバを作るのが楽なので DBus になりました。 さて、この機能の実現には Emacs 側とシェル側 (厳密には emacs コマンドで立ち上げるプロセス) に細工が必要です。これ以降でそれらをもう少し詳しく説明します。 Emacs 側の細工 DBus インターフェースで待ち受けて… 続きを読む