File: vdso.7

package info (click to toggle)
manpages-ja 0.5.0.0.20210215%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 28,568 kB
  • sloc: perl: 161; makefile: 58
file content (440 lines) | stat: -rw-r--r-- 17,807 bytes parent folder | download | duplicates (3)
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
.\" Written by Mike Frysinger <vapier@gentoo.org>
.\"
.\" %%%LICENSE_START(PUBLIC_DOMAIN)
.\" This page is in the public domain.
.\" %%%LICENSE_END
.\"
.\" Useful background:
.\"   http://articles.manugarg.com/systemcallinlinux2_6.html
.\"   https://lwn.net/Articles/446528/
.\"   http://www.linuxjournal.com/content/creating-vdso-colonels-other-chicken
.\"   http://www.trilithium.com/johan/2005/08/linux-gate/
.\"
.\"*******************************************************************
.\"
.\" This file was generated with po4a. Translate the source file.
.\"
.\"*******************************************************************
.TH VDSO 7 2014\-08\-19 Linux "Linux Programmer's Manual"
.SH 名前
vDSO \- 仮想 ELF 動的共有オブジェクトの概要
.SH 書式
\fB#include <sys/auxv.h>\fP

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

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

この文書の残りの部分は、 一般の開発者向けというではなく、 好奇心がある人と C ライブラリの開発者向けの内容となっている。 もしあなたが C
ライブラリではなく自分のアプリケーションで vDSO を呼びだそうとしているのであれば、 ほとんどの場合間違ったことをしていることだろう。
.SS "Example background"
システムコールの呼び出しは遅くなる場合がある。 x86 32 ビットシステムでは、
システムコールを呼び出したいことをカーネルに教えるためにソフトウェア割り込み (\fIint $0x80\fP) を使うことができる。
しかしながら、この割り込みはコストがかかる処理である。 割り込みがあると、
カーネルとプロセッサーのマイクロコードの両方のすべての割り込み処理パスが実行される。 新しいプロセッサーには、
システムコール呼び出しを起動するための高速な (だが、後方互換性がある) 命令が用意されている。 C
ライブラリが実行時にこの機能が利用できるかを確認するのではなく、 C ライブラリは vDSO でカーネルが提供する関数を使うことができる。

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

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

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

アーキテクチャーによっては \fBAT_SYSINFO\fP タグもある。 このタグは vsyscall エントリーポイントの場所を知るためだけのものであり、
しばしば省略されるか (利用できない場合は) 0 にセットされる。 このタグは最初の vDSO の実装で使用されていたものであり
(下記の「歴史」を参照)、 このタグを利用するのは避けるべきである。
.SS ファイルフォーマット
vDSO は完全な形式の ELF イメージなので、 vDSO に対してシンボルの検索を行うことができる。 このため、
新しいカーネルリリースで新しいシンボルを追加することができ、 C
ライブラリが別のバージョンのカーネル上で動作する際に実行時に利用可能な機能を検出することができる。 多くの場合、 C
ライブラリは最初の呼び出し時に検出を行い、 それ以降の呼び出しで利用できるようにその結果をキャッシュする。

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

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

これらの関数を呼び出す場合は標準の C の呼び出しの慣習にしたがっておけばよい。 特殊なレジスターやスタックの動作に気を使う必要はない。
.SH 注意
.SS ソース
カーネルをコンパイルする際に、 vDSO コードはコンパイルされリンクが行われる。 通常はアーキテクチャー固有のディレクトリに vDSO
コードが生成される。

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

.SS "vDSO 名"
vDSO の名前はアーキテクチャーにより異なる。 この名前は glibc の \fBldd\fP(1) の出力などに現れる。
名前はコードで必要となることはなく、 名前をハードコードしないこと。
.if  t \{\
.ft CW
\}
.TS
l l.
ユーザー ABI	vDSO 名
_
aarch64	linux\-vdso.so.1
ia64	linux\-gate.so.1
ppc/32	linux\-vdso32.so.1
ppc/64	linux\-vdso64.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
.TE
.if  t \{\
.in
.ft P
\}
.SH アーキテクチャー固有の注意
以下のサブ章では vDSO のアーキテクチャー固有の注意について説明する。

使用される vDSO は、 カーネルの ABI ではなく、 ユーザー空間コードの ABI に基づくことに注意すること。 したがって、 例えば、 i386
32 ビットの ELF ライブラリ上で実行する場合、 i386 32 ビットカーネル上で実行されているか x86_64 64
ビットカーネル上で実行されているかに関わらず同じ vDSO が得られる。 したがって、 以下のどの節が関係するかを判断する際にはユーザー空間 ABI
の名前を使用する必要がある。
.SS "ARM 関数"
.\" See linux/arch/arm/kernel/entry-armv.S
.\" See linux/Documentation/arm/kernel_user_helpers.txt
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: \fIDocumentation/arm/kernel_user_helpers.txt\fP.
.SS "aarch64 関数"
.\" See linux/arch/arm64/kernel/vdso/vdso.lds.S
以下のテーブルは vDSO で公開されるシンボルの一覧である。
.if  t \{\
.ft CW
\}
.TS
l l.
シンボル	バージョン
_
__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
.TE
.if  t \{\
.in
.ft P
\}
.SS "bfin (Blackfin) 関数"
.\" See linux/arch/blackfin/kernel/fixed_code.S
.\" See http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:fixed-code
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\(emsome 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:
.br
http://docs.blackfin.uclinux.org/doku.php?id=linux\-kernel:fixed\-code
.SS "ia64 (Itanium) 関数"
.\" See linux/arch/ia64/kernel/gate.lds.S
.\" Also linux/arch/ia64/kernel/fsys.S and linux/Documentation/ia64/fsys.txt
以下のテーブルは vDSO で公開されるシンボルの一覧である。
.if  t \{\
.ft CW
\}
.TS
l l.
シンボル	バージョン
_
__kernel_sigtramp	LINUX_2.5
__kernel_syscall_via_break	LINUX_2.5
__kernel_syscall_via_epc	LINUX_2.5
.TE
.if  t \{\
.in
.ft P
\}

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 \fI__kernel_syscall_via_epc\fP vDSO helper.  The
system calls listed here have the same semantics as if you called them
directly via \fBsyscall\fP(2), so refer to the relevant documentation for
each.  The table below lists the functions available via this mechanism.
.if  t \{\
.ft CW
\}
.TS
l.
関数
_
clock_gettime
getcpu
getpid
getppid
gettimeofday
set_tid_address
.TE
.if  t \{\
.in
.ft P
\}
.SS "parisc (hppa) 関数"
.\" See linux/arch/parisc/kernel/syscall.S
.\" See linux/Documentation/parisc/registers
The parisc port has a code page full of 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)
.if  t \{\
.ft CW
\}
.TS
l l.
オフセット	関数
_
00b0	lws_entry
00e0	set_thread_pointer
0100	linux_gateway_entry (syscall)
0268	syscall_nosys
0274	tracesys
0324	tracesys_next
0368	tracesys_exit
03a0	tracesys_sigexit
03b8	lws_start
03dc	lws_exit_nosys
03e0	lws_exit
03e4	lws_compare_and_swap64
03e8	lws_compare_and_swap
0404	cas_wouldblock
0410	cas_action
.TE
.if  t \{\
.in
.ft P
\}
.SS "ppc/32 関数"
.\" See linux/arch/powerpc/kernel/vdso32/vdso32.lds.S
以下のテーブルは vDSO で公開されるシンボルの一覧である。 \fI*\fP のマークが付いた関数は、カーネルが PowerPC64 (64 ビット)
カーネルの場合にだけ利用可能である。
.if  t \{\
.ft CW
\}
.TS
l l.
シンボル	バージョン
_
__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 \fI*\fP	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
.TE
.if  t \{\
.in
.ft P
\}
.SS "ppc/64 関数"
.\" See linux/arch/powerpc/kernel/vdso64/vdso64.lds.S
以下のテーブルは vDSO で公開されるシンボルの一覧である。
.if  t \{\
.ft CW
\}
.TS
l l.
シンボル	バージョン
_
__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
.TE
.if  t \{\
.in
.ft P
\}
.SS "s390 関数"
.\" See linux/arch/s390/kernel/vdso32/vdso32.lds.S
以下のテーブルは vDSO で公開されるシンボルの一覧である。
.if  t \{\
.ft CW
\}
.TS
l l.
シンボル	バージョン
_
__kernel_clock_getres	LINUX_2.6.29
__kernel_clock_gettime	LINUX_2.6.29
__kernel_gettimeofday	LINUX_2.6.29
.TE
.if  t \{\
.in
.ft P
\}
.SS "s390x 関数"
.\" See linux/arch/s390/kernel/vdso64/vdso64.lds.S
以下のテーブルは vDSO で公開されるシンボルの一覧である。
.if  t \{\
.ft CW
\}
.TS
l l.
シンボル	バージョン
_
__kernel_clock_getres	LINUX_2.6.29
__kernel_clock_gettime	LINUX_2.6.29
__kernel_gettimeofday	LINUX_2.6.29
.TE
.if  t \{\
.in
.ft P
\}
.SS "sh (SuperH) 関数"
.\" See linux/arch/sh/kernel/vsyscall/vsyscall.lds.S
以下のテーブルは vDSO で公開されるシンボルの一覧である。
.if  t \{\
.ft CW
\}
.TS
l l.
シンボル	バージョン
_
__kernel_rt_sigreturn	LINUX_2.6
__kernel_sigreturn	LINUX_2.6
__kernel_vsyscall	LINUX_2.6
.TE
.if  t \{\
.in
.ft P
\}
.SS "i386 関数"
.\" See linux/arch/x86/vdso/vdso32/vdso32.lds.S
以下のテーブルは vDSO で公開されるシンボルの一覧である。
.if  t \{\
.ft CW
\}
.TS
l l.
シンボル	バージョン
_
__kernel_sigreturn	LINUX_2.5
__kernel_rt_sigreturn	LINUX_2.5
__kernel_vsyscall	LINUX_2.5
.\" Added in 7a59ed415f5b57469e22e41fc4188d5399e0b194 and updated
.\" in 37c975545ec63320789962bf307f000f08fabd48.
__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 以降で公開)
.TE
.if  t \{\
.in
.ft P
\}
.SS "x86_64 関数"
.\" See linux/arch/x86/vdso/vdso.lds.S
以下のテーブルは vDSO で公開されるシンボルの一覧である。 これらのシンボルはすべて "__vdso_" のプレフィックスなしでも利用できるが、
これらは無視し、 以下の名前だけを使うこと。
.if  t \{\
.ft CW
\}
.TS
l l.
シンボル	バージョン
_
__vdso_clock_gettime	LINUX_2.6
__vdso_getcpu	LINUX_2.6
__vdso_gettimeofday	LINUX_2.6
__vdso_time	LINUX_2.6
.TE
.if  t \{\
.in
.ft P
\}
.SS "x86/x32 関数"
.\" See linux/arch/x86/vdso/vdso32.lds.S
以下のテーブルは vDSO で公開されるシンボルの一覧である。
.if  t \{\
.ft CW
\}
.TS
l l.
シンボル	バージョン
_
__vdso_clock_gettime	LINUX_2.6
__vdso_getcpu	LINUX_2.6
__vdso_gettimeofday	LINUX_2.6
__vdso_time	LINUX_2.6
.TE
.if  t \{\
.in
.ft P
\}
.SS 歴史
vDSO は元々は一つの関数 vsyscall であった。 古いカーネルでは、 プロセスのメモリーマップに "vdso"
ではなくこの名前が見えるかもしれない。 時間が経つに連れて、 この仕組みはより多くの機能をユーザー空間に渡す有効な方法であると認識されるようになり、
現在の形の vDSO という形に見直しが行われた。
.SH 関連項目
\fBsyscalls\fP(2), \fBgetauxval\fP(3), \fBproc\fP(5)

Linux のソースコードツリーのドキュメント、例、ソースコード:
.in +4n
.nf

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

find arch/ \-iname '*vdso*' \-o \-iname '*gate*'
.fi
.in
.SH この文書について
この man ページは Linux \fIman\-pages\fP プロジェクトのリリース 3.79 の一部
である。プロジェクトの説明とバグ報告に関する情報は
http://www.kernel.org/doc/man\-pages/ に書かれている。