Provided by: manpages-ja_0.5.0.0.20221215+dfsg-1_all bug

名前

       vdso - 仮想 ELF 動的共有オブジェクトの概要

書式

       #include <sys/auxv.h>

       void *vdso = (uintptr_t) getauxval(AT_SYSINFO_EHDR);

説明

       "vDSO"  (virtual dynamic shared object; 仮想動的共有オブジェクト) は、 カーネルが自動的にすべてのユーザー
       空間アプリケーションのアドレス空間にマッピングを行う小さな共有ライブラリである。 vDSO はほとんどの場合  C
       ライブラリから呼び出されるため、  アプリケーションは通常これらの詳細を自分では気にする必要はない。 このよ
       うに、 標準関数と C ライブラリを使って通常の方法でコードを作成することで、 vDSO  経由で利用可能な機能が活
       用されることになる。

       いったいなぜ  vDSO は存在しているのか? カーネルが提供するシステムコールのいくつかは、 ユーザー空間のコー
       ドがこれらのシステムコールを頻繁に呼び出すことになり、 このような呼び出しが全体の性能を支配するようになる
       場合がある。 これは、 呼び出しの頻度と、 ユーザー空間から抜けてカーネルに入ることによるコンテキストスイッ
       チのオーバーヘッドの両方に起因する。

       この文書の残りの部分は、 一般の開発者向けというではなく、 好奇心がある人と C ライブラリの開発者向けの内容
       となっている。  もしあなたが C ライブラリではなく自分のアプリケーションで vDSO を呼びだそうとしているので
       あれば、 ほとんどの場合間違ったことをしていることだろう。

   Example background
       システムコールの呼び出しは遅くなる場合がある。 x86 32 ビットシステムでは、 システムコールを呼び出したいこ
       とをカーネルに教えるためにソフトウェア割り込み  (int $0x80) を使うことができる。 しかしながら、この割り込
       みはコストがかかる処理である。 割り込みがあると、  カーネルとプロセッサーのマイクロコードの両方のすべての
       割り込み処理パスが実行される。  新しいプロセッサーには、 システムコール呼び出しを起動するための高速な (だ
       が、後方互換性がある) 命令が用意されている。 C ライブラリが実行時にこの機能が利用できるかを確認するのでは
       なく、 C ライブラリは vDSO でカーネルが提供する関数を使うことができる。

       用語が紛らわしい点には注意が必要である。  x86 システムでは、 システムコールを呼び出す推奨される方法を判定
       するのに使用される vDSO 関数は "__kernel_vsyscall" という名前だが、 x86=64 では、  "vsyscall"  という用語
       は、  カーネルに時刻はいつかや呼び出し元はどの CPU 上にいるかを問い合わせるための廃止予定の方法も参照して
       いる。

       頻繁に使用されるシステムコールの一つが gettimeofday(2) である。 このシステムコールは、 ユーザー空間アプリ
       ケーションから直接呼び出されることも、  C ライブラリから間接的に呼び出されることもある。 タイムスタンプが
       必要な場面、 タイミングループを行う場面、 ポーリングを行う場面を考えてほしい。 これらはいずれも現在時刻が
       何かを直ちに知りたいのが普通である。 また、この情報は秘密ではなく、 (ルートでも非特権ユーザーでも) 任意の
       特権モードの多くのアプリケーションが同じ情報を取得できる。 したがって、  カーネルはこの質問に応えるのに必
       要な情報をプロセスがアクセスできるメモリー上に配置する。  これにより、 gettimeofday(2) はシステムコールか
       ら通常の関数コールになり、 少ないメモリーアクセスになる。

   vDSO を見つける
       vDSO のベースアドレスは、 (存在する場合には) カーネルから各プログラムに初期補助ベクトル (getauxval(3)  参
       照) の AT_SYSINFO_EHDR タグ経由で渡される。

       vDSO  がユーザーのメモリーマップの何か特定の場所にマッピングされると仮定してはならない。 通常新しいプロセ
       スイメージが作成されるたびに (execve(2) 実行時点) 、 実行時にベースアドレスのランダム化が行われる。  これ
       は "return-to-libc" 攻撃 を防ぐためにセキュリティ上の理由から行われる。

       アーキテクチャーによっては AT_SYSINFO タグもある。 このタグは vsyscall エントリーポイントの場所を知るため
       だけのものであり、 しばしば省略されるか (利用できない場合は) 0 にセットされる。 このタグは最初の vDSO  の
       実装で使用されていたものであり (下記の「歴史」を参照)、 このタグを利用するのは避けるべきである。

   ファイルフォーマット
       vDSO  は完全な形式の ELF イメージなので、 vDSO に対してシンボルの検索を行うことができる。 このため、 新し
       いカーネルリリースで新しいシンボルを追加することができ、 C ライブラリが別のバージョンのカーネル上で動作す
       る際に実行時に利用可能な機能を検出することができる。  多くの場合、 C ライブラリは最初の呼び出し時に検出を
       行い、 それ以降の呼び出しで利用できるようにその結果をキャッシュする。

       すべてのシンボルは (GNU のバージョンフォーマットを使って) バージョンが付けられている。 これにより、  カー
       ネルは後方互換性を持たせつつ関数のシグネチャーを更新することができる。  つまり、 関数が受け取る引数や返り
       値が変更されることがあるということである。 したがって、 vDSO のシンボルを検索する際には、  自分が期待する
       ABI に一致するバージョンをしなければならない。

       通常は  vDSO はすべてのシンボルに "__vdso_" か "__kernel_" というプレフィックスを付けるという慣習に従った
       名前付けを行っており、  他の標準のシンボルから区別することができる。   例えば、   "gettimeofday"   関数は
       ""__vdso_gettimeofday" という名前になっている。

       これらの関数を呼び出す場合は標準の  C の呼び出しの慣習にしたがっておけばよい。 特殊なレジスターやスタック
       の動作に気を使う必要はない。

注意

   ソース
       カーネルをコンパイルする際に、 vDSO コードはコンパイルされリンクが行われる。 通常はアーキテクチャー固有の
       ディレクトリに vDSO コードが生成される。

           find arch/$ARCH/ -name '*vdso*.so*' -o -name '*gate*.so*'

   vDSO 
       vDSO  の名前はアーキテクチャーにより異なる。 この名前は glibc の ldd(1) の出力などに現れる。 名前はコード
       で必要となることはなく、 名前をハードコードしないこと。

       ユーザー ABI   vDSO 名
       ─────────────────────────────────
       aarch64        linux-vdso.so.1
       arm            linux-vdso.so.1
       ia64           linux-gate.so.1
       mips           linux-vdso.so.1
       ppc/32         linux-vdso32.so.1
       ppc/64         linux-vdso64.so.1
       riscv          linux-vdso.so.1
       s390           linux-vdso32.so.1
       s390x          linux-vdso64.so.1
       sh             linux-gate.so.1
       i386           linux-gate.so.1
       x86-64         linux-vdso.so.1
       x86/x32        linux-vdso.so.1

   strace(1), seccomp(2), and the vDSO
       When tracing systems calls with strace(1), symbols (system calls) that are exported by the vDSO will  not
       appear in the trace output.  Those system calls will likewise not be visible to seccomp(2)  filters.

アーキテクチャー固有の注意

       以下のサブ章では vDSO のアーキテクチャー固有の注意について説明する。

       使用される vDSO は、 カーネルの ABI ではなく、 ユーザー空間コードの ABI に基づくことに注意すること。 した
       がって、 例えば、 i386 32 ビットの ELF ライブラリ上で実行する場合、 i386 32  ビットカーネル上で実行されて
       いるか x86-64 64 ビットカーネル上で実行されているかに関わらず同じ vDSO が得られる。 したがって、 以下のど
       の節が関係するかを判断する際にはユーザー空間 ABI の名前を使用する必要がある。

   ARM 関数
       以下のテーブルは vDSO で公開されるシンボルの一覧である。

       シンボル               バージョン
       ────────────────────────────────────────────────────────
       __vdso_gettimeofday    LINUX_2.6 (Linux 4.1 以降で公開)
       __vdso_clock_gettime   LINUX_2.6 (Linux 4.1 以降で公開)

       Additionally, the ARM port has a code page full of utility functions.  Since it's  just  a  raw  page  of
       code,  there  is  no ELF information for doing symbol lookups or versioning.  It does provide support for
       different versions though.

       For information on this code page, it's best to refer to  the  kernel  documentation  as  it's  extremely
       detailed and covers everything you need to know: Documentation/arm/kernel_user_helpers.txt.

   aarch64 関数
       以下のテーブルは vDSO で公開されるシンボルの一覧である。

       シンボル                 バージョン
       ──────────────────────────────────────
       __kernel_rt_sigreturn    LINUX_2.6.39
       __kernel_gettimeofday    LINUX_2.6.39
       __kernel_clock_gettime   LINUX_2.6.39
       __kernel_clock_getres    LINUX_2.6.39

   bfin (Blackfin) functions (port removed in Linux 4.17)
       As this CPU lacks a memory management unit (MMU), it doesn't set up a vDSO in the normal sense.  Instead,
       it maps at boot time a few raw functions into a fixed location in memory.  User-space  applications  then
       call  directly  into  that  region.  There is no provision for backward compatibility beyond sniffing raw
       opcodes, but as this is an embedded CPU, it can get away with things—some of the object formats  it  runs
       aren't even ELF based (they're bFLT/FLAT).

       For information on this code page, it's best to refer to the public documentation:
       http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:fixed-code

   mips 関数
       以下のテーブルは vDSO で公開されるシンボルの一覧である。

       シンボル                 バージョン
       ──────────────────────────────────────────────────────────
       __kernel_gettimeofday    LINUX_2.6 (Linux 4.4 以降で公開)
       __kernel_clock_gettime   LINUX_2.6 (Linux 4.4 以降で公開)

   ia64 (Itanium) 関数
       以下のテーブルは vDSO で公開されるシンボルの一覧である。

       シンボル                     バージョン
       ────────────────────────────────────────
       __kernel_sigtramp            LINUX_2.5
       __kernel_syscall_via_break   LINUX_2.5
       __kernel_syscall_via_epc     LINUX_2.5

       The  Itanium  port  is  somewhat tricky.  In addition to the vDSO above, it also has "light-weight system
       calls" (also known as "fast syscalls" or "fsys").  You can invoke these via the  __kernel_syscall_via_epc
       vDSO  helper.   The  system  calls listed here have the same semantics as if you called them directly via
       syscall(2), so refer to the relevant documentation  for  each.   The  table  below  lists  the  functions
       available via this mechanism.

       関数
       ────────────────
       clock_gettime
       getcpu
       getpid
       getppid
       gettimeofday
       set_tid_address

   parisc (hppa) 関数
       The parisc port has a code page with utility functions called a gateway page.  Rather than use the normal
       ELF auxiliary vector approach, it passes the address of the page to the process  via  the  SR2  register.
       The  permissions  on  the page are such that merely executing those addresses automatically executes with
       kernel privileges and not in user space.  This is done to match the way HP-UX works.

       Since it's just a raw page of code, there is no ELF information for doing symbol lookups  or  versioning.
       Simply call into the appropriate offset via the branch instruction, for example:

           ble <offset>(%sr2, %r0)

       オフセット   関数
       ────────────────────────────────────────────────
       00b0         lws_entry (CAS operations)
       00e0         set_thread_pointer (used by glibc)
       0100         linux_gateway_entry (syscall)

   ppc/32 関数
       以下のテーブルは  vDSO  で公開されるシンボルの一覧である。 * のマークが付いた関数は、カーネルが PowerPC64
       (64 ビット) カーネルの場合にだけ利用可能である。

       シンボル                   バージョン
       ────────────────────────────────────────
       __kernel_clock_getres      LINUX_2.6.15
       __kernel_clock_gettime     LINUX_2.6.15
       __kernel_datapage_offset   LINUX_2.6.15
       __kernel_get_syscall_map   LINUX_2.6.15
       __kernel_get_tbfreq        LINUX_2.6.15
       __kernel_getcpu *          LINUX_2.6.15
       __kernel_gettimeofday      LINUX_2.6.15
       __kernel_sigtramp_rt32     LINUX_2.6.15
       __kernel_sigtramp32        LINUX_2.6.15
       __kernel_sync_dicache      LINUX_2.6.15
       __kernel_sync_dicache_p5   LINUX_2.6.15

       The   CLOCK_REALTIME_COARSE   and   CLOCK_MONOTONIC_COARSE   clocks   are   not    supported    by    the
       __kernel_clock_getres  and  __kernel_clock_gettime  interfaces;  the kernel falls back to the real system
       call.

   ppc/64 関数
       以下のテーブルは vDSO で公開されるシンボルの一覧である。

       シンボル                   バージョン
       ────────────────────────────────────────
       __kernel_clock_getres      LINUX_2.6.15
       __kernel_clock_gettime     LINUX_2.6.15
       __kernel_datapage_offset   LINUX_2.6.15
       __kernel_get_syscall_map   LINUX_2.6.15
       __kernel_get_tbfreq        LINUX_2.6.15
       __kernel_getcpu            LINUX_2.6.15
       __kernel_gettimeofday      LINUX_2.6.15
       __kernel_sigtramp_rt64     LINUX_2.6.15
       __kernel_sync_dicache      LINUX_2.6.15
       __kernel_sync_dicache_p5   LINUX_2.6.15

       The   CLOCK_REALTIME_COARSE   and   CLOCK_MONOTONIC_COARSE   clocks   are   not    supported    by    the
       __kernel_clock_getres  and  __kernel_clock_gettime  interfaces;  the kernel falls back to the real system
       call.

   riscv 関数
       以下のテーブルは vDSO で公開されるシンボルの一覧である。

       シンボル                 バージョン
       ────────────────────────────────────
       __kernel_rt_sigreturn    LINUX_4.15
       __kernel_gettimeofday    LINUX_4.15
       __kernel_clock_gettime   LINUX_4.15
       __kernel_clock_getres    LINUX_4.15
       __kernel_getcpu          LINUX_4.15
       __kernel_flush_icache    LINUX_4.15

   s390 関数
       以下のテーブルは vDSO で公開されるシンボルの一覧である。

       シンボル                 バージョン
       ──────────────────────────────────────

       __kernel_clock_getres    LINUX_2.6.29
       __kernel_clock_gettime   LINUX_2.6.29
       __kernel_gettimeofday    LINUX_2.6.29

   s390x 関数
       以下のテーブルは vDSO で公開されるシンボルの一覧である。

       シンボル                 バージョン
       ──────────────────────────────────────
       __kernel_clock_getres    LINUX_2.6.29
       __kernel_clock_gettime   LINUX_2.6.29
       __kernel_gettimeofday    LINUX_2.6.29

   sh (SuperH) 関数
       以下のテーブルは vDSO で公開されるシンボルの一覧である。

       シンボル                バージョン
       ───────────────────────────────────
       __kernel_rt_sigreturn   LINUX_2.6
       __kernel_sigreturn      LINUX_2.6
       __kernel_vsyscall       LINUX_2.6

   i386 関数
       以下のテーブルは vDSO で公開されるシンボルの一覧である。

       シンボル                バージョン
       ──────────────────────────────────────────────────────────
       __kernel_sigreturn      LINUX_2.5
       __kernel_rt_sigreturn   LINUX_2.5
       __kernel_vsyscall       LINUX_2.5
       __vdso_clock_gettime    LINUX_2.6 (Linux 3.15 以降で公開)
       __vdso_gettimeofday     LINUX_2.6 (Linux 3.15 以降で公開)
       __vdso_time             LINUX_2.6 (Linux 3.15 以降で公開)

   x86-64 関数
       以下のテーブルは vDSO で公開されるシンボルの一覧である。 これらのシンボルはすべて "__vdso_"  のプレフィッ
       クスなしでも利用できるが、 これらは無視し、 以下の名前だけを使うこと。

       シンボル               バージョン
       ──────────────────────────────────
       __vdso_clock_gettime   LINUX_2.6
       __vdso_getcpu          LINUX_2.6
       __vdso_gettimeofday    LINUX_2.6
       __vdso_time            LINUX_2.6

   x86/x32 関数
       以下のテーブルは vDSO で公開されるシンボルの一覧である。

       シンボル               バージョン
       ──────────────────────────────────
       __vdso_clock_gettime   LINUX_2.6
       __vdso_getcpu          LINUX_2.6
       __vdso_gettimeofday    LINUX_2.6
       __vdso_time            LINUX_2.6

   歴史
       vDSO は元々は一つの関数 vsyscall であった。 古いカーネルでは、 プロセスのメモリーマップに "vdso" ではなく
       この名前が見えるかもしれない。 時間が経つに連れて、  この仕組みはより多くの機能をユーザー空間に渡す有効な
       方法であると認識されるようになり、 現在の形の vDSO という形に見直しが行われた。

関連項目

       syscalls(2), getauxval(3), proc(5)

       Linux のソースコードツリーのドキュメント、例、ソースコード:

           Documentation/ABI/stable/vdso
           Documentation/ia64/fsys.txt
           Documentation/vDSO/* (vDSO の使用例がある)

           find arch/ -iname '*vdso*' -o -iname '*gate*'

この文書について

       この  man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの説明とバグ報告
       に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。