
プロセスの仮想アドレス空間には、1GBのカーネル空間が含まれます。
ここで、この 1 GB カーネル空間がカーネル関連データとコード (IDT (Interrupt Descriptor Table) を含む) を指していると仮定します。
プロセスがCPUによって実行されていて、そのプロセスがシステムコールをしていると仮定します(割り込み0x80
(int 0x80
)をトリガします)。何が起こるかは、CPUがIDTに行き、割り込み番号に関連付けられた割り込みハンドラを実行することです0x80
。
これで、CPUは現在のプロセスにとどまり、現在のプロセスのカーネル空間で割り込みハンドラを実行します(コンテキスト切り替えは発生しません)。
答え1
int 0x80
i386が他のアーキテクチャを使用できると仮定します。たとえばsyscall
amd64の場合。システムコールが行われるたびにコンテキスト切り替えが発生する場合、これは多くのシステムコールを生成するプログラムを実行するときに見やすくする必要があります。幸いなことに、そのようなプログラムがあります。
bits 64
section .text
global _start
_start: mov r9,9551615
mov rax,1 ; sys_write
mov rdi,1 ; stdout
mov rsi,letter
mov rdx,1 ; length
_again: syscall
dec r9
jnz _again
mov rax,60 ; sys_exit
mov rdi,0 ; exit code
syscall
section .data
letter: db "a"
64ビットLinuxシステムでコンパイルして実行すると、次の結果perf
が表示されます。
$ nasm -f elf64 -g -F dwarf -o max.o max.asm
$ ld -o max max.o
$ sudo perf stat ./max > /dev/null 2> perf.log
$ grep context perf.log
88 context-switches # 0.051 K/sec
$
プロセスは88回のコンテキスト切り替えのみを行いました。カーネルがプロセスのコンテキスト内にあるたびにコンテキスト切り替えが発生した場合は、9551615回のコンテキスト切り替えを表示できます。
今!コンテキスト遷移によるシステムエラーを確認するには、上記のコマンドを以下に実行します。strace
$ strace -c ./max
...
すでに別のウィンドウで実行していますvmstat 1
...
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 896 333928 2132 3124628 0 0 0 0 74 98 0 0 100 0 0
0 0 896 333896 2132 3124628 0 0 0 0 89 103 0 0 100 0 0
0 0 896 333896 2132 3124628 0 0 0 0 65 85 0 0 100 0 0
0 0 896 333896 2132 3124628 0 0 0 0 67 83 0 0 100 0 0
2 0 896 333756 2132 3124628 0 0 0 0 21460 529902 10 29 61 0 0
3 0 896 333832 2132 3124628 0 0 0 0 23690 652506 13 32 55 0 0
1 0 896 333832 2132 3124628 0 0 0 0 27574 673152 11 33 55 0 0
0 0 896 333768 2132 3124628 0 0 0 0 24351 650723 11 30 59 0 0
strace
これは、and max
(および出力を忘れた場合は他のソフトウェア/dev/null
)がおよび間で狂ったように切り替えを開始したときに非常に明白に見えます。