sysctl

Table of Contents

systemd

以前ArchLinuxで動作してるsshdをpsしたら、ダエモン君のように見えた。 systemdが一枚噛んでいると想像したんだけど、リナのソースを参照するよう な面倒は避けたい。で、識者に聞いてみた。下記は、その長いセッションの最後の 部分だ。

Q: systemd がそのプロセスをフォアグラウンドのまま管理し、必要な監視や制御を行っているためです。 との事ですが、具体的にどのように管理しているのでしょうか? 概略のコードで説明してください。

A: `systemd` がフォアグラウンドで動作するプロセス(例えば、`sshd -D`)をどのように管理しているかを、概略のコードで説明します。

### 1. `systemd` ユニットファイル まず、`sshd` のサービスは `systemd` ユニットファイルで定義されています。このユニットファイルには、`ExecStart` のような指示が含まれています。

[Unit]
Description=OpenSSH Daemon

[Service]
ExecStart=/usr/bin/sshd -D
Type=simple

### 2. `systemd` の管理方法

`systemd` は `ExecStart` で指定されたプロセスを起動し、そのプロセスをフォアグラウンドで実行したまま管理します。具体的には、`systemd` の内部で次のような操作が行われます。

#### 2.1 プロセスのフォークと監視

`systemd` は `fork()` システムコールを使用して、新しいプロセスを生成します。その際、`sshd -D` がフォアグラウンドで実行されます。

pid_t pid = fork();
if (pid == 0) {
    // 子プロセス:sshd -D を実行
    execl("/usr/bin/sshd", "sshd", "-D", NULL);
} else {
    // 親プロセス:systemd が子プロセスを監視
    // pid は子プロセスの PID を持つ
    monitor_process(pid);
}

#### 2.2 フォアグラウンドプロセスの監視

`systemd` は `pid` を追跡し、そのプロセスの終了を `waitpid()` などで監視します。

int status;
waitpid(pid, &status, 0);
if (WIFEXITED(status)) {
    // プロセスが正常に終了した場合の処理
} else if (WIFSIGNALED(status)) {
    // プロセスがシグナルで終了した場合の処理
}

#### 2.3 ログの管理

`systemd` はプロセスの標準出力や標準エラー出力をキャプチャして、`journalctl` で確認できるようにします。これにより、`sshd` がフォアグラウンドで実行されている間のログを管理します。

int stdout_pipe[2];
int stderr_pipe[2];

pipe(stdout_pipe);
pipe(stderr_pipe);

// 子プロセスの標準出力とエラー出力をパイプにリダイレクト
if (pid == 0) {
    dup2(stdout_pipe[1], STDOUT_FILENO);
    dup2(stderr_pipe[1], STDERR_FILENO);
    close(stdout_pipe[0]);
    close(stderr_pipe[0]);
} else {
    // 親プロセスはパイプの出力を読み取ってログを保存
    close(stdout_pipe[1]);
    close(stderr_pipe[1]);
    read_and_log(stdout_pipe[0]);
    read_and_log(stderr_pipe[0]);
}

### 3. サービスの再起動や停止

`systemd` はサービスの再起動や停止を管理します。これにより、`sshd` がクラッシュした場合や手動で停止・再起動された場合でも適切に処理されます。

void restart_service() {
    // サービスの再起動処理
    kill(pid, SIGTERM);
    waitpid(pid, &status, 0);
    // 再度起動
    pid_t new_pid = fork();
    if (new_pid == 0) {
        execl("/usr/bin/sshd", "sshd", "-D", NULL);
    }
}

### 概要

`systemd` はフォアグラウンドプロセスをフォークして起動し、そのプロセス の状態を監視しながら、標準出力とエラー出力を管理することで、バックグラ ウンドで動作するデーモンのようにそのプロセスを扱います。また、プロセス が終了した場合の再起動やログの保存などの機能も提供します。

折角なので、sshdのユニットファイルを調べてみた。@ ArchLinux

/etc/systemd/system/multi-user.target.wants/sshd.service

[Unit]
Description=OpenSSH Daemon
Wants=sshdgenkeys.service
After=sshdgenkeys.service
After=network.target

[Service]
Type=notify-reload
ExecStart=/usr/bin/sshd -D
KillMode=process
Restart=always

[Install]
WantedBy=multi-user.target

/proc

今度は /procだ。これも、前回ひょいと出てきてた。

Q: Linuxの/procについて質問します。OS起動時から/procが参照できます。 /procはファイルシステムの様に見えますが、mountに相当する処理は どのように実行されているのでしょうか?

A: `/proc`はLinuxカーネルによって自動的に管理される特殊な仮想ファイルシステムで、プロセスやシステムに関する情報を提供します。これは他のファイルシステムのようにディスク上のデータを保持するのではなく、カーネル内のデータ構造に直接アクセスするためのインターフェースを提供します。

`/proc`ファイルシステムは、OSの起動時にカーネルによって自動的にマウントされます。このマウントは通常、`/proc`ディレクトリに行われます。

### `/proc`のマウントに関する仕組み

  1. カーネル初期化:
    • Linuxカーネルがブートされると、まずシステムの基本的な初期化が行われます。カーネルは初期化プロセスの一環として、様々な仮想ファイルシステム(例えば、`/proc`や`/sys`など)をマウントします。
  2. 仮想ファイルシステムのマウント:
    • `/proc`ファイルシステムは、カーネル内の初期化コードで`proc`として指定されている場所にマウントされます。具体的には、カーネルのブートプロセス内で`procmount`関数が呼び出されることで、このマウント処理が行われます。
  3. initプロセスの開始:
    • カーネル初期化が完了すると、ユーザーモードで`init`プロセスが開始されます。この時点で`/proc`ファイルシステムはすでにマウントされているため、`init`プロセスやそれに続くユーザー空間のプロセスは、`/proc`を利用してカーネルの情報を取得することができます。

### 実際のマウントコマンド 通常、`/etc/fstab`ファイルには`proc`ファイルシステムを`/proc`にマウントするためのエントリが含まれていますが、これは通常のマウント処理ではなく、OSの起動時にカーネルが自動的に行う処理です。

例えば、`/etc/fstab`のエントリは以下のようになっています:

proc /proc proc defaults 0 0

このエントリは、カーネルによって自動的に処理され、OSが起動すると同時に `/proc`ファイルシステムがマウントされることを意味します。

注) 必須の事なんで、/etc/fstabの記述は無い。ユーザーの手が届かない高見 な所に昇格してますよ。

Q: /procが提供するカーネルデータは、どのように反映されるのですか? 例えば、/proc/interrupts とか、/proc/pid/cmdlineとかです。 catとかでアクセスが有った時に、カーネルから該当データを取得してる と想像しています。

A: はい、あなたの理解は正しいです。`/proc`ファイルシステムは仮想ファイルシステムであり、実際には物理的なディスク上に存在するファイルではなく、カーネルのデータ構造に直接アクセスするインターフェースを提供します。

### `/proc`の動作仕組み

  • アクセス時の動作:
    • ユーザーが`cat proc/interrupts`や`cat /proc[pid]/cmdline`のように`/proc`ファイルを読み取ると、カーネルはその瞬間に対応するデータを生成して返します。この生成は、通常のファイルシステムでデータをディスクから読み込むのとは異なり、カーネル内の特定のコードがその場で必要な情報を収集し、仮想的なファイル内容として提供するというプロセスです。
  • 動的生成:
    • 例えば、`/proc/interrupts`を読むと、カーネルはその時点でのシステム内の割り込み情報を収集し、ユーザーに表示するためのテキストとして動的に生成します。
    • 同様に、`/proc/[pid]/cmdline`を読むと、そのPID(プロセスID)に対応するプロセスのコマンドライン引数をカーネルが動的に取得し、テキスト形式で表示します。

### 具体的な例

  1. /proc/interrupts:
    • このファイルにはシステム内の割り込み(ハードウェア割り込み)の統計情報が含まれています。カーネルはこのファイルがアクセスされた時点で、各ハードウェアデバイスから発生した割り込みのカウント情報を収集し、それをフォーマットして提供します。
  2. proc[pid]/cmdline:
    • このファイルには、特定のプロセスが起動された時のコマンドライン引数が含まれています。カーネルは`/proc/[pid]/cmdline`が読み取られると、そのプロセスのコマンドライン引数を取得し、ヌル文字(`\0`)で区切った文字列として提供します。

### カーネル内の実装

これらの動作は、カーネル内の特定の関数やファイル操作に関連するハンドラーによって実装されています。`/proc`ファイルシステムの各エントリ(例えば`/proc/interrupts`や`/proc/[pid]/cmdline`)には、それぞれに対応するカーネルのコードがあります。このコードはファイルが開かれた際に実行され、必要な情報をカーネル内部から収集し、ファイルの内容として出力します。

  • このように、`/proc`のエントリにアクセスがあると、カーネルはその情報 を動的に生成し、利用者に提供するため、常に最新の情報が得られるように なっています。

Q: /procの項目を更新して、カーネルに影響を与える事は可能ですか? 可能な項目が有ったら、紹介してください。wなパーミションが付いて いれば、OKなのかな?

A: `/proc`ファイルシステム内のいくつかのファイルやディレクトリは、読み書き可能であり、これを通じてカーネルやシステムの設定を変更することができます。ただし、これを行うには管理者(root)権限が必要で、誤った操作をするとシステムに重大な影響を与える可能性があります。

### 書き込み可能な`/proc`の項目

  1. /proc/sys ディレクトリ内の項目:

    • `/proc/sys`はカーネルパラメータを動的に変更するためのインターフェースを提供しています。ここにはシステムの動作に関連する様々な設定が含まれており、`sysctl`コマンドを使ってこれらの設定を変更することができますが、直接ファイルに書き込むことでも同様の効果を得ることができます。

    例:

    • `/proc/sys/net/ipv4/ipforward`: このファイルに`1`を書き込むと、IPフォワーディングが有効になります(ネットワークパケットのルーティングを許可)。
    • `/proc/sys/vm/swappiness`: このファイルに数値(0-100)を書き込むと、スワップの使用頻度を変更できます。

    echo 1 > proc/sys/net/ipv4 ip_forward

  2. */proc/[pid]/ oom_adj *:
    • 特定のプロセスに対するOut Of Memory(OOM)キラーの挙動を調整するために使用されます。値を変更することで、そのプロセスがメモリ不足時に終了される可能性を調整できます。
  3. proc[pid]/readdir`:
    • 特定のプロセスに関連するパラメータや制御を変更できるファイルもありますが、ほとんどは読み取り専用です。一部の特殊なパラメータは書き込み可能で、プロセスの動作に影響を与えることができます。

### wパーミッションの意味

  • `/proc`内のファイルに`w`パーミッション(書き込み権限)が設定されている場合、それに書き込むことでカーネルやシステムの挙動に影響を与えることができます。これらのファイルは、通常rootユーザーのみが書き込み可能です。
  • パーミッションが`-rw-r–r–`の場合、所有者(通常はroot)が書き込みでき、他のユーザーは読み取りのみが可能です。

### 注意点

  • `/proc/sys`内の設定を変更する場合、システムに重大な影響を与えることがあるため、操作は慎重に行う必要があります。変更後の動作が予期しない結果を引き起こすこともあるため、設定変更の前にその意味と影響をよく理解することが重要です。
  • 一部の設定は一時的なもので、システム再起動時にリセットされるため、永 続的な変更を行うには`/etc/sysctl.conf`ファイルや他の適切な設定ファイ ルに変更を加える必要があります。

詳しい事は、 proc(5)を参照。山のように解説が載ってて目がチカチカするぞ。

FreeBSD /proc

FreeBSD でプログラムからシステムやプロセスの情報を取得する

FreeBSDでLinuxバイナリ互換機能を使ってみる

FreeBSD on Virtual Box

GUIなんかを使う場合、/procは必須になるんか。リナ由来のアプリが大多数だ から、暗黙のうちに要求されるんだな(毒されてるとも言う)。OpenBSDでは、 いさぎよく、procfsは実装されていない。複雑になる(==BUGを誘発)って理由 からだ。

lib(re)ssl

前回だったか、ちょっとlibsslに言及した。その後、 SSLとは?必要な理由を説明します なんていう超マクロな説明に遭遇。 それはそれとして、 半導体ビジネスの定性的コスト分析論 の所のYieldなんてのによると、欠陥 (BUG)はチップ面積に比例するって説明が出ています。ソフトウェアの場合の面積っ たら、ソースの行数だろうって、想像できます。

そこで、核心部分の面積ならぬソースの行数と個数を調べてみます。

OpenBSD

LibreSSLとlibsslはリンク時に決定するみたい、な事がhidden/READMEに説明 されてた。

ob$ cd /usr/src/lib/libcrypto/
ob$ find . -name '*.[ch]' | xargs wc
     :
  220254  832967 6494184 total
ob$ find . -name '*.[ch]' | wc
     687     687   12512

aesとかshaでの各種の石用に、perlを利用してアセンブラのコードを生成して るなあ。知らなかったぞ。でも、今更アセンブラですかい? って疑問に思っ てコードを開いてみたら、テスター用のコードだよーーん。こいつを叩き台に して拡張するのは大歓迎。その場合はこうしたらいいんでないかいってヒント が出てた。

FreeBSD

sakae@fb:/usr/src/crypto/openssl $ find . -name '*.[ch]' | xargs wc
    :
  382507 1317041 12966216 total
sakae@fb:/usr/src/crypto/openssl $ find . -name '*.[ch]' | wc
    1009    1009   24195

極めて雑に調べてみたけど、これが実情ですよ。

そうそう、機能豊富が仇になって、時々修正が入るブラウザーとか、 curl,sudoなんてのも、お馴染みですな。

sysctl

前回作成したsetproctitleを使うコードで、カーネル側を追求してみる。ユー ザーランド側では、

const int mib[2] = { CTL_VM, VM_PSSTRINGS };

が、

(gdb) p mib
$1 = {2, 3}

こんなコードに変換されてたぞ。

sysctl(2)

(gdb) bt
#0  sys_sysctl (p=0xd1983d0c, v=0xf3a926b4, retval=0xf3a926ac) at /usr/src/sys/kern/kern_sysctl.c:174
#1  0xd068ba01 in mi_syscall (p=0xd1983d0c, code=202, indirect=-1, callp=0xd0d0fa58 <sysent+2424>, argp=0xf3a926b4, retval=0x\
f3a926ac) at /usr/src/sys/sys/syscall_mi.h:110
#2  0xd068b604 in syscall (frame=0xf3a926f0) at /usr/src/sys/arch/i386/i386/trap.c:574
#3  0xd071a135 in Xsyscall_untramp ()
#4  0xf3a926f0 in ?? ()
#5  0x09e9868b in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

少々追跡すると

        case CTL_VM:
                fn = uvm_sysctl;
                break;
                 :
=>      error = (*fn)(&name[1], SCARG(uap, namelen) - 1, SCARG(uap, old),
            &oldlen, SCARG(uap, new), SCARG(uap, newlen), p);

こういう動的なコード呼出になってる。

uvn_sysctl を厳しく追求すると、 uvm_meter.c が出てくる。そこの

case VM_PSSTRINGS:
        return (sysctl_rdstruct(oldp, oldlenp, newp, &pr->ps_strings,
            sizeof(pr->ps_strings)));

更に飛ばされて、

/*
 * Validate parameters and get old parameters
 * for a structure oriented sysctl function.
 */
int
sysctl_rdstruct(void *oldp, size_t *oldlenp, void *newp, const void *sp,
    size_t len)
{
        int error = 0;

        if (oldp && *oldlenp < len)
                return (ENOMEM);
        if (newp)
                return (EPERM);
        *oldlenp = len;
        if (oldp)
                error = copyout(sp, oldp, len);
        return (error);
}

こんな風に、掘り出されていたよ。こういう風にして、カーネルのデータを収 集している訳ね。あちことに坑道を用意しておくって、大変だな。

sysctl(8)

カーネルのデータをセンシングしたり、逆にデータをカーネルへ注入したりす る、汎用のコマンドが用意されてる。興味本位に、そのプローブ・ポイントの 個数を調べてみた。

ob$ sysctl -a | wc
     419    2729   24981
sakae@fb:~ $ sysctl -a | wc
    7920   17635  255653

FreeBSDはOpenBSDに比べて断トツだな。この努力って、DTraceの協力があった から? DTraceの使い方 とか、習ってみるかな。

[sakae@arch ~]$ sudo sysctl -a | wc
   1013    3168   36794

リナもディストリビューションによって(or kernel ver.)個数は、異なってい た。

いずれにしろ、カーネルに対向してユーザーランド側のライブラリィーに、そ れなりのコードを用意しないとプログラム上から制御できないので、大変な労 力だろう。いや、sysctl(8)をシェルから使えって事にして、glib界隈の人は 知らぬ存じぬを決めこんでいるんだろうか? リナだったら、カーネルとglib は別組織が開発してるから、そういう事も有りうるか。

README

化石に眠るDNA

『化石に眠るDNA』/更科功インタビュー

最後の章が楽しい。恐竜を蘇えらせるのか? 進化を逆にたどらせられれば、 恐竜も誕生するんでないかい。恐竜 -> 鳥類 と進化してきたんだから、その 進化を巻き戻せ、作戦。

胎児も母のお腹の中で、進化が高速で実行されている。たとえば尾が発生する けど、成長のスイッチが途中で切れてしまう。その名残が尾てい骨。

ならば、そのスイッチが切れないように遺伝子編集してしまえば良い。この方 針で、ニワトリからミニ恐竜を発生する研究が行なわれているらしい。 人によっては、マッド・サイエンスと見做す向きもあるらしい。

いずれにしろ、遺伝子を良く知る事が肝要。その道具がシーケンサー。どんな 物か聞いてみた。

Q: DNAの分析に利用されるシーケンサーについて、その原理と分析手法について、 説明してください。

A: DNAシーケンサーは、DNA分子の塩基配列(アデニン(A)、シトシン(C)、グアニン(G)、チミン(T)の順序)を解読するための装置です。DNAシーケンスの情報は、生物学的な研究、医療、法医学などで重要な役割を果たします。以下に、主要なシーケンサーの種類とその原理について説明します。

### 1. サンガー法(Sanger Sequencing) 原理:

  • サンガー法は、1970年代にフレデリック・サンガーによって開発された古典的なシーケンシング手法です。
  • この方法では、DNAの複製過程を利用し、複製の終了を特定の塩基で止める「ジデオキシヌクレオチド(ddNTP)」を使います。
  • 複製を途中で終了させたDNA断片を電気泳動によってサイズ別に分離し、各塩基の位置を解析します。

分析手法:

  • 4種類のジデオキシヌクレオチド(ddATP、ddCTP、ddGTP、ddTTP)をそれぞれ使った反応を行い、それぞれの反応で得られたDNA断片の長さを比較して、塩基配列を決定します。

### 2. 次世代シーケンサー(Next-Generation Sequencing, NGS) 原理:

  • NGSは、サンガー法に比べて大規模かつ高速にDNAの塩基配列を決定する技術です。IlluminaやIon Torrentなどのプラットフォームが代表的です。
  • 多くの場合、短いDNA断片を並行して大量にシーケンスし、それをコンピュータで解析して全体の配列を再構築します。

代表的なNGS技術:

  • Illumina シーケンス: 特定の塩基が組み込まれると蛍光を発するヌクレオチドを使用し、光学的に塩基配列を読み取ります。
  • Ion Torrent シーケンス: DNAの複製中に放出される水素イオンを検出し、その電荷変化をもとに塩基を識別します。

分析手法:

  • DNAサンプルを断片化し、各断片にアダプターを結合します。
  • その後、断片を増幅してマルチプレックスにシーケンスし、得られたデータをコンピュータで解析して全体の配列を組み立てます。

### 3. 第三世代シーケンサー(Third-Generation Sequencing) 原理:

  • 第三世代シーケンサーでは、さらに長いDNA分子をリアルタイムでシーケンスする技術が開発されています。代表的なものにPacBioやOxford Nanoporeがあります。

代表的な技術:

  • PacBio(Pacific Biosciences)シーケンス: DNA分子がポリメラーゼにより複製される過程をリアルタイムで観察し、蛍光標識されたヌクレオチドの追加を検出します。
  • Oxford Nanopore シーケンス: DNA分子がナノポア(ナノサイズの孔)を通過する際に生じる電流変化を測定し、塩基配列を直接読み取ります。

分析手法:

  • これらの技術は長いリード(数十キロベースの長さの連続した塩基配列)を生成でき、従来の方法では困難だったゲノムの複雑な領域もシーケンス可能です。

### 応用例

  • 医学研究: がん研究における突然変異の解析、遺伝病の診断などに利用されます。
  • 環境科学: 微生物群集の多様性解析や生態系研究などで使用されます。
  • 法医学: 犯罪現場での証拠物のDNA解析に用いられます。

これらの技術は日々進化しており、より高精度、高速、低コストでDNAシーケンスが可能になっています。


This year's Index

Home