目次: ブラウザー/メーラー
LinuxデスクトップマシンのFirefox(140.3.1esr 64bit)をアップデートしたところ、アドレスバーの上下に黒い線が表示されるようになりました。何も害はないですが、目立つなあ。Windows版でこのような線は見たことがありません。
昨今のブラウザってシステムのデザインはガン無視で、オレオレGUIコンポーネントを描画してるはずで。それでもデザイン統一できないのはバグなのか、Linux版に何か特有の事情があるのか……?
目次: ALSA
PipeWireに変えてから音切れがなくなりません。PulseAudioのときも音切れはしてましたが、PipeWireになってから頻度が段違いに多いです。なぜー?今回はサーバー側PipeWireのレイテンシ調整に備えて、設定反映方法と設定確認方法を紹介します。
設定を反映するにはpipewire-pulse.socket, pipewire-pulse.service, pipewire.socket, pipewire.service, wireplumber.serviceのうち設定を変更したサービスを再起動すれば良いはずです。良くわからないときは全部再起動しましょう。
$ systemctl --user daemon-reload $ systemctl --user restart pipewire.service #### もし何かおかしかったら下記もやってみると吉 $ systemctl --user restart pipewire.socket $ systemctl --user restart wireplumber.service $ systemctl --user restart pipewire-pulse.service $ systemctl --user restart pipewire-pulse.socket
デバッグ出力を見たければ、上記の5つのサービスを全部stopしてからPipeWireと仲間たちを直接起動すると良いでしょう。
#### サービスを全部止める $ systemctl --user stop pipewire.socket $ systemctl --user stop pipewire.service $ systemctl --user stop wireplumber.service $ systemctl --user stop pipewire-pulse.socket $ systemctl --user stop pipewire-pulse.service #### 直接起動する $ /usr/bin/pipewire -v $ /usr/bin/wireplumber $ /usr/bin/pipewire-pulse -v
ちなみにデバッグログを出すとわかりますが、めちゃくちゃ大量に出ます……私には意味がわかりません。
PipeWireは設定確認にはリモート音声再生している状態でpw-topコマンドを起動して確認すると便利です。
S ID QUANT RATE WAIT BUSY W/Q B/Q ERR FORMAT NAME S 30 0 0 --- --- --- --- 0 Dummy-Driver S 31 0 0 --- --- --- --- 0 Freewheel-Driver S 47 0 0 --- --- --- --- 0 Midi-Bridge R 51 2048 48000 594.1us 320.5us 0.01 0.01 1 S24_32 2 48000 alsa_output.platform-es8316-s R 56 8192 48000 245.6us 253.7us 0.01 0.01 1 S32LE 2 48000 + mpv S 52 0 0 --- --- --- --- 0 alsa_input.platform-es8316-so S 53 0 0 --- --- --- --- 0 alsa_output.platform-hdmi0-so S 54 0 0 --- --- --- --- 0 alsa_output.platform-hdmi1-so S 55 0 0 --- --- --- --- 0 alsa_input.platform-hdmiin-so
RATEがサンプリング周波数で、QUANT(※)がバッファサイズのようです。ALSAデバイス側は2048サンプル、PulseAudioモジュール(mpvの話し相手)は8192サンプルです。mpvはpulse-buffer=500を指定したので、500msつまり24000サンプルになるはずですが、なぜか8192です。
(※)QUANT = quantumのこと。バッファサイズを決めるための数値らしく、単位はサンプルだと思われます。PipeWireのドキュメントを見てもquantumについて説明している部分が見当たらなくて困りました。
目次: ALSA
先日(2025年10月11日の日記参照)の設定により、x86_64なPCからROCK 5Bにて動作しているPipeWireに対し、リモートオーディオ再生ができるようになりました。無事動いたまでは良いのですが、PipeWireにしてから音切れがひどくなり困ってしまいました。
クライアント側はx86_64、mplayer v0.40.0(今はmpvですね)+ libpipewire 1.4.8で、サーバー側はaarch64、libpipewire 1.4.2です。
一般的に音が切れるのはクライアントかサーバーかどちらかの音声用のバッファが足りない可能性が高いです。クライアント側の設定を確認するためにmpvに-vオプションを付けて実行します。
$ PULSE_SERVER=192.168.1.x mplayer --audio-device=pulse -v a.mp4 ...(略)... [ao] Trying audio driver 'pulse' [ao/pulse] requested format: 48000 Hz, stereo channels, floatp [ao/pulse] Library version: 17.0.0 [ao/pulse] Proto: 35 [ao/pulse] Server proto: 35 [ao/pulse] Channel layouts: [ao/pulse] - #fl [ao/pulse] - #fr [ao/pulse] - #fc [ao/pulse] - #lfe [ao/pulse] - #bl [ao/pulse] - #br [ao/pulse] - #flc [ao/pulse] - #frc [ao/pulse] - #bc [ao/pulse] - #sl [ao/pulse] - #sr [ao/pulse] - #tc [ao/pulse] - #tfl [ao/pulse] - #tfc [ao/pulse] - #tfr [ao/pulse] - #tbl [ao/pulse] - #tbc [ao/pulse] - #tbr [ao/pulse] result: stereo [ao/pulse] device buffer: 4800 samples. ★デバイスバッファが4800/48000 = 0.1秒 [ao/pulse] using soft-buffer of 9600 samples. ★バッファが9600/48000 = 0.2秒 ...
ログからバッファサイズをチェックしたところデフォルト100ms + 200msのようです。変更にはpulse-bufferオプションを使用します。値の単位はミリ秒です。
$ PULSE_SERVER=192.168.1.x mplayer --audio-device=pulse --pulse-buffer=1000 -v a.mp4 ... [ao/pulse] result: stereo [ao/pulse] device buffer: 48000 samples. [ao/pulse] using soft-buffer of 48000 samples. ...
ひとまず1000msくらいに変更してしばらく様子を見ようと思います。
今回は特に変えていませんが、サーバー側の設定は/usr/share/pipewire/pipewire-pulse.confにあります。設定を変更したらpipewire-pulseを再起動で反映されるはずです。ユーザー権限で動いているのでsudoは不要です。
$ systemctl --user restart pipewire-pulse
このファイルを書き換えると次のアップデートで上書きされてしまうらしいですが、他の場所にある設定ファイルが見当たらないんですよね。どこにあるんだろう。。。
目次: ARM
Debian StableがTrixieに変わったことをすっかり忘れており、ROCK 5Bをapt-get dist-upgradeしたところ環境が壊れました。ARM SBC(SBC = Single Board Computer)のベンダーがDebianを提供してくれるのは大変ありがたいですが、大抵変なパッケージか変な改造が入っていて年単位で運用すると困ったことが起きがちです。
SBCはアップデートしない派もいるでしょうけど、ネットワークに繋いでいるし可能な限りアップデートを適用したいです。取れる選択肢は下記の二つでしょうか。
正直、良し悪しは互角ですね……。
Debianは多少壊れても元に戻せますが、今回は盛大に壊れましてapt --fix-broken installはエラーになります。致命的なのはsystemdとlibsystemd0のバージョン不一致でsystemdが消えたことで、bookwormにも戻してもsystemdがインストールできなくなりました。もしこの状態で再起動したら二度と起動しないでしょう。
Preparing to unpack .../systemd_257.8-1~deb13u2_arm64.deb ... Unpacking systemd (257.8-1~deb13u2) over (252.38-1~deb12u1) ... dpkg: error processing archive /var/cache/apt/archives/systemd_257.8-1~deb13u2_arm64.deb (--unpack): trying to overwrite '/usr/lib/systemd/system/serial-getty@.service', which is also in package rockchip-overlay 4.1 dpkg: considering removing systemd in favour of udev ... dpkg: systemd is not properly installed; ignoring any dependencies on it dpkg: yes, will remove systemd in favour of udev Preparing to unpack .../udev_257.8-1~deb13u2_arm64.deb ... Unpacking udev (257.8-1~deb13u2) over (252.38-1~deb12u1) ... Removing systemd (252.38-1~deb12u1), to allow configuration of udev (257.8-1~deb13u2) ... Preparing to unpack .../libudev1_257.8-1~deb13u2_arm64.deb ... Unpacking libudev1:arm64 (257.8-1~deb13u2) over (252.38-1~deb12u1) ... Errors were encountered while processing: /var/cache/apt/archives/systemd_257.8-1~deb13u2_arm64.deb E: Sub-process /usr/bin/dpkg returned an error code (1)
エラーメッセージを見るとrockchip-overlayなるパッケージが邪魔しているようです。試行錯誤の結果、
としたところ、元気に動き始めました。代償として画面が出なくなりましたが、今のところ画面を使っていないので問題ありません。面倒なSDカードイメージの書き直しを避けることができてラッキーでした。
目次: ALSA
最近はPulseAudioがPipeWireに置き換わっているそうです。今はPulseAudioをリモートオーディオ再生機として使っているので、PipeWireで同じことをする方法を紹介します。
やりたいことはLinuxデスクトップからARM SBC上のPulseAudioへオーディオを飛ばすこと(2022年5月27日の日記参照)です。PulseAudioの場合はmodule-native-protocol-tcpを有効にして、TCPでオーディオを送るようにしました。
まずSinkデバイスの設定を行います。大抵HDMI、ヘッドフォン端子、あるいは別の出力端子があるはずですので、どこから音を鳴らすかを決めます。オーディオデバイスが1つしかない場合は設定不要かもしれませんが、一応チェックしておくと良いと思います。
設定にはWirePlumberの設定ツールwpctlを使います。wpctl statusで現在の様子を見ることができます。
$ wpctl status Audio ├─ Devices: │ 48. Built-in Audio [alsa] │ 49. Built-in Audio [alsa] │ 50. Built-in Audio [alsa] │ 51. Built-in Audio [alsa] │ ├─ Sinks: │ 35. Built-in Audio Stereo [vol: 1.00] │ 46. Built-in Audio Stereo [vol: 1.00] │ * 56. Built-in Audio Stereo [vol: 1.00] │ ├─ Sources: │ 44. Built-in Audio Stereo [vol: 1.00] │ * 57. Built-in Audio Stereo [vol: 1.00] │ ├─ Filters: │ └─ Streams:
SourcesとSinksのデフォルトデバイスを変更して、音声の入出力先を変更するにはset-defaultを使用します。wpctlはDevice、Source、Sinkの全てがユニークなIDを持っているので、SourceだとかSinkだとか指定する必要はなくて、IDのみ指定します。入出力先を変更後、もう一度statusを見るとSettingsの内容が変わるはずです。
例えば上記のstatusなら、set-defaultに指定できるのはSink系(35, 46, 56)かSource系(44, 57)のIDのうちどれか1つです。もし35か46か56を指定した場合は、IDからSinkデバイスだとわかるのでデフォルトSinkデバイスが変更されます。44か57を指定した場合はデフォルトSourceデバイスが変更されます。直感的じゃない、辛い……。
$ wpctl set-default 56 $ wpctl set-default 57 $ wpctl status ... Settings └─ Default Configured Devices: 0. Audio/Sink alsa_output.platform-es8316-sound.stereo-fallback 1. Audio/Source alsa_input.platform-es8316-sound.stereo-fallback
余談でWirePlumberが出てくる理由を紹介します。PipeWireは音声の入出力経路を管理しないため、PipeWire以外のソフトウェアをインストールして音声の経路管理しなければならないからです。WirePlumberもPipeWireもこだわりというか思想の強さがにじみ出ていて、私は仲良くなれなさそうです……。
動作確認は音を鳴らしてみて鳴れば方法は問いませんが、一例としてALSAを使った方法を紹介します。PipeWireとALSAやV4L2を繋ぐためのモジュールとalsa-utilsをインストールします。
$ sudo apt-get install pipewire-alsa pipewire-audio pipewire-v4l2 alsa-utils $ speaker-test -c 2 -r 48000 -D pipewire speaker-test 1.2.14 Playback device is pipewire Stream parameters are 48000Hz, S16_LE, 2 channels Using 16 octaves of pink noise Rate set to 48000Hz (requested 48000Hz) Buffer size range from 64 to 1048576 Period size range from 32 to 524288 Periods = 4 was set period_size = 12000 was set buffer_size = 48000 0 - Front Left
左右のスピーカーから交互にノイズ音(サーー)がなれば成功です。鳴らない場合は設定とボリューム(wpctlで確認できます)、もしくはALSAデバイス側のボリューム、ミュート設定の問題も有り得るので、alsamixerで確認してみてください。
次はPulseAudioモジュールの設定変更です。PipeWireと一緒にインストールされるはずですが、もし下記の設定ファイルが存在しなければpipewire-pulseをインストールしてください。
# /usr/share/pipewire/pipewire-pulse.conf ... pulse.properties = { # the addresses this server listens on server.address = [ "unix:native" #"unix:/tmp/something" # absolute paths may be used #★★この行を有効にする "tcp:4713" # IPv4 and IPv6 on all addresses #"tcp:[::]:9999" # IPv6 on all addresses #"tcp:127.0.0.1:8888" # IPv4 on a single address # #{ address = "tcp:4713" # address # max-clients = 64 # maximum number of clients # listen-backlog = 32 # backlog in the server listen queue # client.access = "restricted" # permissions for clients #} ] ...
$ systemctl --user restart pipewire-pulse
設定を変更したら再起動をお忘れなく。
#### クライアント側で操作 $ PULSE_SERVER=192.168.1.x speaker-test -c 2 -r 48000 -D pulse
リモートオーディオ再生のクライアント側でPULSE_SERVERにサーバーのIPアドレスを指定して音声を再生します。サーバー側から音が鳴れば成功です。
目次: Linux
Makefileの達人には常識かもしれませんが、makeがリンクを行うときのデフォルトルール(LINK.o)が使うコマンドはLDではなくCCです。私はリンク時にldが直接呼ばれるのは見たことがないにも関わらず、ずっとLDが使われると思いこんでいました。
話は以上で終わり……だとつまらないので、実験もしましょう。Makefileとコンパイラの代わりにスクリプトを呼びます。makeはGNU Make 4.4.1を使いました。
CC = ./cc-dummy
CXX = ./cxx-dummy
CPP = ./cpp-dummy
LD = ./ld-dummy
CFLAGS = cflags-dummy
CXXFLAGS = cxxflags-dummy
CPPFLAGS = cppflags-dummy
LDFLAGS = ldflags-dummy
LOADLIBES = loadlibes-dummy
LDLIBS = ldlibs-dummy
all: target-c target-cxx
target-c: target-c.o
target-cxx: target-cxx.o
$ cat ./cc-dummy #!/bin/sh touch target-c.o $ cat ./cxx-dummy #!/bin/sh touch target-cxx.o
コマンドが見つからないエラーを防ぐため、CCやCXXに指定した名前のスクリプトも作ります。スクリプトではコンパイラがオブジェクトファイル(*.o)を作成する動きのみを模しておけば十分です。
オブジェクトファイルの生成でデフォルトのコンパイルのルール、バイナリファイルの生成でリンクのルールが呼ばれます。このときCCやCXXが使われるか?LDが使われるか?がわかるはずです。実行します。
$ make #### C言語プログラムのコンパイルとリンク、どちらもCCを使う ./cc-dummy cflags-dummy cppflags-dummy -c -o target-c.o target-c.c ./cc-dummy ldflags-dummy target-c.o loadlibes-dummy ldlibs-dummy -o target-c #### C++言語プログラムのコンパイルとリンク、コンパイルはCXX、リンクはCCを使う ./cxx-dummy cxxflags-dummy cppflags-dummy -c -o target-cxx.o target-cxx.cc ./cc-dummy ldflags-dummy target-cxx.o loadlibes-dummy ldlibs-dummy -o target-cxx
C言語でもC++言語でもリンクは一緒で、CCを呼び出しました。LDは使われません。
オプション-pでmakeのデフォルトルールを見ることができます。"%: %.o"はオブジェクトファイルからバイナリを生成するときに当てはまるデフォルトルールです。コロンの左が生成ファイル、右が依存ファイルです。%はワイルドカードです。
UNIX系の慣例で、実行ファイル名は拡張子なし(例えばhoge)、オブジェクトファイル名は*.o(例えばhoge.o)にします。そのペアにうまく当てはまるルールになっています。
# デフォルト LINK.o = $(CC) $(LDFLAGS) $(TARGET_ARCH) #...(略)... %: %.o # 実行するレシピ (ビルトイン): $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
当たり前ですが、実験で見た結果と一緒です。
GNU Makeのソースコードも眺めてみました。おそらくdefault.cがデフォルトルールの定義だと思います。デフォルトルールと一緒です。そりゃそうですね。
// make/src/default.c
static const char *default_variables[] =
{
#ifdef VMS
//...
#else /* !VMS */
//...
"LINK.o", "$(CC) $(LDFLAGS) $(TARGET_ARCH)",
"COMPILE.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
"LINK.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
"COMPILE.m", "$(OBJC) $(OBJCFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
"LINK.m", "$(OBJC) $(OBJCFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
"COMPILE.cc", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
//...
ソースコードを見て初めて知ったことが、VAX用のVMSというOSだとCCではなくLDを使うことです。しかし今の時代にVMS使っている人はいないでしょう……たぶん。
目次: Linux
以前、LinuxのI/O統計情報を得る/proc/[pid]/ioの実装を調べました。あのときは深追いしませんでしたが、/procには/proc/[pid]/以下のファイルから何が読めるのか、pid_entryの配列で指定する仕組みがありました。
// fs/proc/base.c
/*
* Thread groups
*/
static const struct pid_entry tgid_base_stuff[] = {
DIR("task", S_IRUGO|S_IXUGO, proc_task_inode_operations, proc_task_operations),
DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations),
//...
#ifdef CONFIG_TASK_IO_ACCOUNTING
ONE("io", S_IRUSR, proc_tgid_io_accounting), //★★★★これ
#endif
なぜこの配列に要素を足すと/proc/[pid]/以下のファイルが定義できるのでしょう?まずはopen/readに限定して調べてみます。調査対象はLinux-5.15です。
/proc/(tgid)/以下のファイルを定義しているtgid_base_stuffの中身は、DIR()もしくはONE()マクロを使って定義します。ONE()マクロを見てみます。
// fs/proc/base.c
#define ONE(NAME, MODE, show) \
NOD(NAME, (S_IFREG|(MODE)), \
NULL, &proc_single_file_operations, \
{ .proc_show = show } )
#define NOD(NAME, MODE, IOP, FOP, OP) { \
.name = (NAME), \
.len = sizeof(NAME) - 1, \
.mode = MODE, \
.iop = IOP, \
.fop = FOP, \
.op = OP, \
}
ネストしたマクロはわかりにくいです。何か1つ(ここではio)を展開すると多少はわかりやすいと思います。
// fs/proc/base.c
// ★★★★NODを展開
#define ONE(NAME, MODE, show) { \
.name = (NAME), \
.len = sizeof(NAME) - 1, \
.mode = (S_IFREG|(MODE)), \
.iop = NULL, \
.fop = &proc_single_file_operations, \
.op = { .proc_show = show }, \
}
static const struct file_operations proc_single_file_operations = {
.open = proc_single_open, //★★open時に呼ばれる関数
.read = seq_read, //★★read時に呼ばれる関数
.llseek = seq_lseek,
.release = single_release,
};
// ★★★★ioの定義を当てはめる
ONE("io", S_IRUSR, proc_tgid_io_accounting),
#define ONE(NAME, MODE, show) { \
.name = ("io"), \
.len = sizeof("io") - 1, \
.mode = (S_IFREG|(S_IRUSR)), \
.iop = NULL, \
.fop = &proc_single_file_operations, \
.op = { .proc_show = proc_tgid_io_accounting }, \
}
ファイルopen時にproc_single_open()、read時にseq_read()が呼ばれるように、あとはop.proc_showにproc_tgid_io_accounting()を指定しています。
どうやってproc_single_open()が呼ばれるか?は一旦無視して、open時に呼ばれるものとして調べます。
// linux/fs/proc/base.c
static int proc_single_open(struct inode *inode, struct file *filp)
{
return single_open(filp, proc_single_show, inode);
}
// linux/fs/seq_file.c
int single_open(struct file *file, int (*show)(struct seq_file *, void *),
void *data)
{
struct seq_operations *op = kmalloc(sizeof(*op), GFP_KERNEL_ACCOUNT);
int res = -ENOMEM;
if (op) {
op->start = single_start;
op->next = single_next;
op->stop = single_stop;
op->show = show; //★★show = proc_single_show()
res = seq_open(file, op);
if (!res)
((struct seq_file *)file->private_data)->private = data;
else
kfree(op);
}
return res;
}
EXPORT_SYMBOL(single_open);
int seq_open(struct file *file, const struct seq_operations *op)
{
struct seq_file *p;
WARN_ON(file->private_data);
p = kmem_cache_zalloc(seq_file_cache, GFP_KERNEL);
if (!p)
return -ENOMEM;
file->private_data = p;
mutex_init(&p->lock);
p->op = op; //★★op = struct seq_operations, op->show = proc_single_show()
// No refcounting: the lifetime of 'p' is constrained
// to the lifetime of the file.
p->file = file;
/*
* seq_files support lseek() and pread(). They do not implement
* write() at all, but we clear FMODE_PWRITE here for historical
* reasons.
*
* If a client of seq_files a) implements file.write() and b) wishes to
* support pwrite() then that client will need to implement its own
* file.open() which calls seq_open() and then sets FMODE_PWRITE.
*/
file->f_mode &= ~FMODE_PWRITE;
return 0;
}
EXPORT_SYMBOL(seq_open);
ここで出てくるseq_で始まる関数群とsingle_で始まる関数群は、seq_fileと呼ばれる仕組み(The seq_file interface - The Linux Kernel Documentation)です。変な名前だなあ?と思うのはごもっともですけど正式名称なのです……。
仮想ファイルシステム上にファイルを定義するときは、openやreadを実装しなければなりません。特にread()の実装は曲者で読み出し位置の管理が面倒です。しかしseq_fileを使うと内部にバッファを勝手に確保し、読み出し位置を管理してくれます。もっとも簡単な実装だと、seq_printf()で内部バッファに書き出すだけで済みます。/procのような何か情報を返すファイルシステムを実装するときに便利です。
次にread時の動作を見ます。open同様にどうやってseq_read()が呼ばれるか?は一旦無視して、read時に呼ばれるものとして調べます。
// linux/fs/seq_file.c
ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
struct iovec iov = { .iov_base = buf, .iov_len = size};
struct kiocb kiocb;
struct iov_iter iter;
ssize_t ret;
init_sync_kiocb(&kiocb, file);
iov_iter_init(&iter, READ, &iov, 1, size);
kiocb.ki_pos = *ppos;
ret = seq_read_iter(&kiocb, &iter); //★★★★
*ppos = kiocb.ki_pos;
return ret;
}
EXPORT_SYMBOL(seq_read);
ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
{
struct seq_file *m = iocb->ki_filp->private_data;
size_t copied = 0;
size_t n;
void *p;
int err = 0;
//...略...
// get a non-empty record in the buffer
m->from = 0;
p = m->op->start(m, &m->index);
while (1) {
err = PTR_ERR(p);
if (!p || IS_ERR(p)) // EOF or an error
break;
err = m->op->show(m, p); //★★ここでshow = proc_single_show()を呼ぶ
if (err < 0) // hard error
break;
if (unlikely(err)) // ->show() says "skip it"
m->count = 0;
if (unlikely(!m->count)) { // empty record
p = m->op->next(m, p, &m->index);
continue;
}
if (!seq_has_overflowed(m)) // got it
goto Fill;
// need a bigger buffer
m->op->stop(m, p);
kvfree(m->buf);
m->count = 0;
m->buf = seq_buf_alloc(m->size <<= 1);
if (!m->buf)
goto Enomem;
p = m->op->start(m, &m->index);
}
// EOF or an error
m->op->stop(m, p);
m->count = 0;
goto Done;
//...略...
// linux/fs/proc/base.c
static int proc_single_show(struct seq_file *m, void *v)
{
struct inode *inode = m->private;
struct pid_namespace *ns = proc_pid_ns(inode->i_sb);
struct pid *pid = proc_pid(inode);
struct task_struct *task;
int ret;
task = get_pid_task(pid, PIDTYPE_PID);
if (!task)
return -ESRCH;
ret = PROC_I(inode)->op.proc_show(m, ns, pid, task); //★★ここでproc_show = proc_tgid_io_accounting()を呼ぶ
put_task_struct(task);
return ret;
}
やっとONE()に渡したproc_tgid_io_accountingが呼ばれる場所がわかりました。長かった……。
< | 2025 | > | ||||
<< | < | 10 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | - | - | 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 | - |
合計:
本日: