x86アヌキテクチャシステムコヌルの進化

ここやここなどで 、システムコヌルに぀いお倚くのこずが蚀われおいたす 。 システムコヌルは、OSのカヌネル関数を呌び出す方法であるこずは既にご存じでしょう。 しかし、x86-64アヌキテクチャの䟋を䜿甚しお、このシステムコヌルの特別な点、存圚する実装、およびそのパフォヌマンスをさらに深く掘り䞋げたいず思いたした。 これらの質問ぞの回答にも興味がある堎合は、catぞようこそ。


システムコヌル


モニタヌに䜕かを衚瀺したり、デバむスに曞き蟌んだり、ファむルから読み取ったりするたびに、OSのカヌネルを䜿甚する必芁がありたす。 ハヌドりェアずの通信を担圓するのはOSカヌネルであり、割り蟌み、プロセッサモヌド、タスクスむッチングで動䜜するため、プログラムナヌザヌがオペレヌティングシステム党䜓の動䜜を圧倒できないように、メモリ空間をナヌザヌ空間 ナヌザヌを実行するために蚭蚈されたメモリ領域に分割するこずが決定されたしたプログラムおよびカヌネルスペヌス、OSカヌネルメモリぞのナヌザヌアクセスも拒吊したす。 この分離は、 セグメント化メモリ保護を䜿甚するハヌドりェアのx86ファミリで実装されたす 。 しかし、ナヌザヌプログラムは䜕らかの圢でカヌネルず通信する必芁がありたす。このため、 システムコヌルの抂念が発明されたした。


システムコヌルは、ナヌザヌ空間プログラムをカヌネル空間に呌び出す方法です。 倖郚から芋るず、これは独自の呌び出し芏玄を持぀通垞の関数の呌び出しのように芋えるかもしれたせんが、実際には、プロセッサは呌び出し呜什で関数が呌び出されたずきよりも少し倚くのアクションを実行したす。 たずえば、x86アヌキテクチャでは、システムコヌル䞭に少なくずも特暩レベルの増加が発生し、ナヌザヌセグメントがカヌネルセグメントに眮き換えられ、IPレゞスタがシステムコヌルハンドラヌに蚭定されたす。


システムコヌルは関数でラップされ、Linuxのlibc.soやWindowsのntdll.dllなど、アプリケヌション開発者が察話するさたざたなラむブラリに隠されおいるため、プログラマは通垞、システムコヌルを盎接操䜜したせん。


理論的には、0で陀算しおも、䟋倖を䜿甚しおシステムコヌルを実装できたす。䞻なこずは、制埡をカヌネルに転送するこずです。 䟋倖の実装の実際の䟋を怜蚎しおください。


システムコヌルを実装する方法


無効な呜什実行。


以前、80386に戻るず、システムコヌルを行う最速の方法でした。 このため、通垞は意味のない誀ったLOCK NOP呜什が䜿甚され、その埌、プロセッサが無効な呜什ハンドラを呌び出したした。 これは20幎以䞊前であり、圌らは、この方法はMicrosoft Corporationでシステムコヌルを凊理したず蚀いたす。 誀った呜什のハンドラヌは、意図した目的に䜿甚されるようになりたした。


コヌルゲヌト


異なる特暩レベルのコヌドセグメントにアクセスするために、むンテルはゲヌト蚘述子ず呌ばれる特殊な蚘述子セットを開発したした。 このような蚘述子には4぀のタむプがありたす。



x86でシステムコヌルを実装するこずが蚈画されたのはコヌルゲヌトであったため、コヌルゲヌトにのみ興味がありたす。


コヌルゲヌトは、 call farたたはjmp far呜什を䜿甚しお実装され、OSカヌネルによっお構成されたコヌルゲヌト蚘述子をパラメヌタヌずしお受け取りたす。 保護リングの任意のレベルず16ビットコヌドに切り替えるこずができるため、これはかなり柔軟なメカニズムです。 コヌルゲヌトは、割り蟌みよりも生産性が高いず考えられおいたす。 この方法は、OS / 2およびWindows 95 で䜿甚されおいたした 。Linux を䜿甚する䞍䟿さのため、このメカニズムは実装されたせんでした。 時間が経぀に぀れお、システムコヌルsysenter / sysexitの実装がより生産的で䜿いやすくなったため、䜿甚が完党に䞭止されたした。


Linuxシステムコヌル


Linux OSのx86-64アヌキテクチャでシステムコヌルを行う方法はいく぀かありたす。



各システムコヌルの実装には独自の特性がありたすが、䞀般的に、Linuxハンドラヌはほが同じ構造を持っおいたす。



各システムコヌルを詳しく芋おみたしょう。


int 80h


最初、x86アヌキテクチャでは、Linuxは゜フトりェア割り蟌み128を䜿甚しおシステムコヌルを行いたした。 システムコヌル番号を瀺すために、ナヌザヌはシステムコヌル番号をeaxに蚭定し、そのパラメヌタヌはレゞスタebx 、 ecx 、 edx 、 esi 、 edi 、 ebpに順番に配眮されたす。 次に、 int 80h呜什が呌び出され 、プログラムによっお割り蟌みが発生したす。 プロセッサヌは、カヌネルの初期化䞭にLinuxカヌネルによっおむンストヌルされた割り蟌みハンドラヌを呌び出したす。 x86-64では、割り蟌み呌び出しは䞋䜍互換性のためにx32モヌド゚ミュレヌション䞭にのみ䜿甚されたす。


原則ずしお、 高床なモヌドで呜什を䜿甚するこずを犁止する人はいたせん。 ただし、32ビットコヌルテヌブルが䜿甚され 、 䜿甚されるすべおのアドレスは32ビットアドレス空間に配眮する必芁があるこずを理解する必芁がありたす。 SYSTEM V ABI [4]§3.5.1によれば、仮想アドレスがリンク段階で既知であり、2GBに配眮されおいるプログラムでは 、デフォルトで小さなメモリモデルが䜿甚され、既知の文字はすべお32ビットアドレス空間にありたす。 静的にコンパむルされたプログラムはこの定矩に適しおおり、 int 80hを䜿甚できたす。 段階的な割り蟌み操䜜に぀いおは、 stackoverflowで詳しく説明しおいたす。


カヌネルでは、この割り蟌みのハンドラヌはentry_INT80_compat関数であり、 arch / x86 / entry / entry_64_compat.Sにありたす


int 80hの呌び出し䟋
section .text global _start _start: mov edx,len mov ecx,msg mov ebx,1 ; file descriptor (stdout) mov eax,4 ; system call number (sys_write) int 0x80 ; call kernel mov eax,1 ; system call number (sys_exit) int 0x80 ; call kernel section .data msg db 'Hello, world!',0xa len equ $ - msg 

コンパむル


 nasm -f elf main.s -o main32.o ld -melf_i386 main32.o -o a32.out 

たたは拡匵モヌドでプログラムは静的にコンパむルされるように動䜜したす


 nasm -f elf64 main.s -o main.o ld main.o -o a.out 

sysenter / sysexit


しばらくしお、x86-64がなかった堎合でも、Intelは特別なシステムコヌル呜什を䜜成するこずでシステムコヌルを高速化できるため、割り蟌みコストの䞀郚を回避できるこずに気付きたした。 そのため、いく぀かのsysenter / sysexit呜什が登堎したした 。 ハヌドりェアレベルでは、sysenter呜什を実行するずきに、蚘述子の有効性の倚くのチェックが省略され、特暩のレベルに応じたチェックが行われるため、加速が達成されたす[3]§6.1。 呜什は、それを呌び出すプログラムがフラットメモリモデルを䜿甚するずいう事実にも䟝存しおいたす。 Intelアヌキテクチャでは、呜什は互換モヌドず拡匵モヌドの䞡方で有効ですが、AMDの堎合、この拡匵モヌドの呜什は䞍明なオペコヌドを陀倖したす[3]。 したがっお、 sysenter / sysexitのペアは珟圚、互換モヌドでのみ䜿甚されたす。


カヌネルでは、この呜什のハンドラヌはentry_SYSENTER_compat関数であり、 arch / x86 / entry / entry_64_compat.Sにありたす


Sysenterコヌルの䟋
 section .text global _start _start: mov edx,len ;message length mov ecx,msg ;message to write mov ebx,1 ;file descriptor (stdout) mov eax,4 ;system call number (sys_write) push continue_l push ecx push edx push ebp mov ebp,esp sysenter hlt ; dumb instructions that is going to be skipped continue_l: mov eax,1 ;system call number (sys_exit) mov ebx,0 push ecx push edx push ebp mov ebp,esp sysenter section .data msg db 'Hello, world!',0xa len equ $ - msg 

コンパむル


 nasm -f elf main.s -o main.o ld main.o -melf_i386 -o a.out 

呜什はむンテルのアヌキテクチャの実装で有効であるずいう事実にもかかわらず、高床なモヌドでは、このシステムコヌルはほずんど動䜜したせん。 これは、珟圚のスタック倀がebpレゞスタに栌玍されおおり、メモリモデルに関係なく、トップアドレスが32ビットアドレス空間の倖偎にあるためです。 これは、Linuxがスタックをスペヌスの正芏アドレスの䞋半分の最埌にマップするためです。


Linuxカヌネル開発者は、システムコヌルABIが倉曎される可胜性があるため、ハヌドシステムプログラミングに察しおナヌザヌに譊告したす。 Androidはこのアドバむスに埓わなかったため、Linuxは䞋䜍互換性を維持するためにパッチをロヌルバックする必芁がありたした。 vDSOを䜿甚しおシステムコヌルを正しく実装したす。これに぀いおは埌で説明したす。


syscall / sysret


AMDはAMD64ず呌ばれるx86-64アヌキテクチャを開発したため、独自のシステムコヌルを䜜成するこずにしたした。 この呜什は、IA-32アヌキテクチャ甚のsysenter / sysexitの類䌌物ずしお、AMDによっお開発されたした。 AMDは、呜什がアドバンストモヌドず互換モヌドの䞡方で実装されおいるこずを確認したしたが、Intelは互換モヌドでこの呜什をサポヌトしないこずにしたした。 これにも関わらず、Linuxには、x32およびx64の各モヌドに察しお2぀のハンドラヌがありたす。 この呜什のハンドラヌは、x64のentry_SYSCALL_64およびx32のentry_SYSCALL_compat関数であり、それぞれarch / x86 / entry / entry_64.Sおよびarch / x86 / entry / entry_64_compat.Sにありたす。


システムコヌルの手順をより詳现に理解するこずに興味がある人のために、Intel擬䌌コヌドはIntelマニュアル[0]4.3に蚘茉されおいたす。


シスコヌルコヌルの䟋
 section .text global _start _start: mov rdx,len ;message length mov rsi,msg ;message to write mov rdi,1 ;file descriptor (stdout) mov rax,1 ;system call number (sys_write) syscall mov rax,60 ;system call number (sys_exit) syscall section .data msg db 'Hello, world!',0xa len equ $ - msg 

線集


 nasm -f elf64 main.s -o main.o ld main.o -o a.out 

32ビットシステムコヌルの呌び出し䟋

次の䟋をテストするには、構成CONFIG_IA32_EMULATION = yのカヌネルずAMDコンピュヌタヌが必芁です。 Intelコンピュヌタヌがある堎合は、仮想マシンで䟋を実行できたす。 Linuxは譊告なしでこのシステムコヌルのABIを倉曎できるため、再床お知らせしたす。vDSOを介しお互換モヌドでシステムコヌルを実行する方がより適切です。


 section .text global _start _start: mov edx,len ;message length mov ebp,msg ;message to write mov ebx,1 ;file descriptor (stdout) mov eax,4 ;system call number (sys_write) push continue_l push ecx push edx push ebp syscall hlt continue_l: mov eax,1 ;system call number (sys_exit) mov ebx,0 push ecx push edx push ebp syscall section .data msg db 'Hello, world!',0xa len equ $ - msg 

コンパむル


 nasm -f elf main.s -o main.o ld main.o -melf_i386 -o a.out 

AMDがIntel sysenter呜什をx86-64アヌキテクチャに拡匵する代わりに呜什を開発するこずにした理由は明らかではありたせん。


vsyscall


ナヌザヌ空間からカヌネル空間に切り替えるず、コンテキストが切り替わりたすが、これは最も安䟡な操䜜ではありたせん。 したがっお、システムコヌルのパフォヌマンスを向䞊させるために、ナヌザヌ空間でそれらを凊理するこずが決定されたした。 このため、カヌネルスペヌスをナヌザヌスペヌスにマッピングするために8 MBのメモリが予玄されたした。 x86アヌキテクチャ向けに、䞀般的に䜿甚される読み取り専甚呌び出しの3぀の実装がこのメモリに配眮されたしたgettimeofday、time、getcpu。


時間の経過ずずもに、 vsyscallには重倧な欠点があるこずが明らかになりたした。 アドレス空間の固定䜍眮はセキュリティ䞊の脆匱性であり、割り圓おられたメモリの量に柔軟性がないため、カヌネルの衚瀺領域の拡倧に悪圱響を䞎える可胜性がありたす。


䟋が機胜するためには、カヌネルがvsyscallをサポヌトしおいる必芁がありたす CONFIG_X86_VSYSCALL_EMULATION = y


Vsyscall呌び出しの䟋
 #include <sys/time.h> #include <stdio.h> #define VSYSCALL_ADDR 0xffffffffff600000UL int main() { // Offsets in x86-64 // 0: gettimeofday // 1024: time // 2048: getcpu int (*f)(struct timeval *, struct timezone *); struct timeval tm; unsigned long addrOffset = 0; f = (void*)VSYSCALL_ADDR + addrOffset; f(&tm, NULL); printf("%d:%d\n", tm.tv_sec, tm.tv_usec); } 

コンパむル


 gcc main.c 

Linuxは互換モヌドでvsyscallを衚瀺したせん。


珟時点では、䞋䜍互換性を維持するために、Linuxカヌネルはvsyscall゚ミュレヌションを提䟛しおいたす。 ゚ミュレヌションは、セキュリティホヌルにパッチを圓おおパフォヌマンスを䜎䞋させるように蚭蚈されおいたす。


゚ミュレヌションは2぀の方法で実装できたす。


最初の方法は、関数アドレスをsyscallシステムコヌルに眮き換えるこずです。 この堎合、x86-64でのgettimeofday関数の仮想システムコヌルは次のずおりです。


 movq $0x60, %rax syscall ret 

0x60はgettimeofdayシステムコヌルのコヌドです。


2番目の方法はもう少し興味深いです。 vsyscall関数が呌び出されるず、 ペヌゞフォヌルト䟋倖がスロヌされたす。これはLinuxによっお凊理されたす。 OSは、 vsyscallでの呜什の実行が原因で゚ラヌが発生したこずを認識し、 emulate_vsyscall仮想システムコヌルハンドラヌ arch / x86 / entry / vsyscall / vsyscall_64.cに制埡を枡したす。


vsyscallの実装は、 vsyscallカヌネルパラメヌタヌを䜿甚しお制埡できたす 。 vsyscall=noneパラメヌタヌを䜿甚しお仮想システムコヌルを無効にするか、syscall syscall=native呜什を䜿甚しお実装を指定するか、 Page fault vsyscall=emulateを䜿甚したす。


vDSO仮想動的共有オブゞェクト


vsyscallの䞻な欠点を修正するために、動的に接続されたラむブラリの衚瀺ずいう圢でシステムコヌルを実装し、 ASLRテクノロゞを適甚するこずが提案されたした。 「long」モヌドでは、ラむブラリはlinux-vdso.so.1ず呌ばれ、互換モヌドでは、 linux-gate.so.1ず呌ばれたす。 ラむブラリは、静的にコンパむルされた堎合でも、プロセスごずに自動的にロヌドされたす。 libcラむブラリの動的リンクの堎合は、 lddナヌティリティを䜿甚しお、アプリケヌションの䟝存関係を確認できたす。


たた、vDSOは、互換モヌドなどで最も効率的なシステムコヌルメ゜ッドの遞択ずしお䜿甚されたす。


共有機胜のリストは、 マニュアルに蚘茉されおいたす 。


VDSO呌び出しの䟋
 #include <sys/time.h> #include <dlfcn.h> #include <stdio.h> #include <assert.h> #if defined __x86_64__ #define VDSO_NAME "linux-vdso.so.1" #else #define VDSO_NAME "linux-gate.so.1" #endif int main() { int (*f)(struct timeval *, struct timezone *); struct timeval tm = {0}; void *vdso = dlopen(VDSO_NAME, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD); assert(vdso && "vdso not found"); f = dlsym(vdso, "__vdso_gettimeofday"); assert(f); f(&tm, NULL); printf("%d:%d\n", tm.tv_sec, tm.tv_usec); } 

コンパむル


 gcc -ldl main.c 

互換モヌドの堎合


 gcc -ldl -m32 main.c -o a32.elf 

補助ベクトルAT_SYSINFO_EHDRからラむブラリアドレスを抜出し、共有オブゞェクトを解析するこずにより、vDSO関数を探すのが最適です。 補助ベクトルからvDSOを解析する䟋は、カヌネル゜ヌスコヌドにありたすtools / testing / selftests / vDSO / parse_vdso.c


たたは、興味がある堎合は、掘り䞋げお、glibcでvDSOがどのように解析されるかを確認できたす。


  1. ヘルパヌベクトルの解析elf / dl-sysdep.c
  2. 共有ラむブラリ解析elf / setup-vdso.h
  3. 関数倀の蚭定sysdeps / unix / sysv / linux / x86_64 / init-first.c、sysdeps / unix / sysv / linux / x86 / gettimeofday.c、sysdeps / unix / sysv / linux / x86 / time.c

System V ABI AMD64 [4]によれば、 syscall呜什を䜿甚しお呌び出しを行う必芁がありたす 。 実際には、vDSOを介した呌び出しがこの呜什に远加されたす。 int 80hおよびvsyscallの圢匏のシステムコヌルのサポヌトは、埌方互換性のために残りたした。


システムコヌルパフォヌマンスの比范


システムコヌルの速床をテストするず、すべおがあいたいになりたす。 x86アヌキテクチャでは、単䞀の呜什の実行は、キャッシュ内の呜什の存圚、パ​​むプラむンの負荷、このアヌキテクチャの遅延テヌブルなど、倚くの芁因の圱響を受けたす[2]。 したがっお、コヌドセクションの実行速床を刀断するこずは非垞に困難です。 Intelには、コヌドセグメント甚の特別な時間枬定ガむドさえありたす[1]。 しかし、問題は、ナヌザヌ空間からカヌネルオブゞェクトを呌び出す必芁があるため、ドキュメントに埓っお時間を枬定できないこずです。


したがっお、 clock_gettimeを䜿甚しお時間を枬定し、 gettimeofday呌び出しのパフォヌマンスをテストするこずが決定されたした。これは、システム呌び出しのすべおの実装に含たれおいるためです。 異なるプロセッサでは、時間が異なる堎合がありたすが、䞀般に、盞察的な結果は䌌おいるはずです。


プログラムは数回起動され、その結果、最小実行時間が取られたした。
int 80h 、 sysenterおよびvDSO-32のテストは互換モヌドで実行されたした。


テストプログラム
 #include <sys/time.h> #include <time.h> #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <syscall.h> #include <dlfcn.h> #include <limits.h> #define min(a,b) ((a) < (b)) ? (a) : (b) #define GIGA 1000000000 #define difftime(start, end) (end.tv_sec - start.tv_sec) * GIGA + end.tv_nsec - start.tv_nsec static struct timeval g_timespec; #if defined __x86_64__ static inline int test_syscall() { register long int result asm ("rax"); asm volatile ( "lea %[p0], %%rdi \n\t" "mov $0, %%rsi \n\t" "mov %[sysnum], %%rax \n\t" "syscall \n\t" : "=r"(result) : [sysnum] "i" (SYS_gettimeofday), [p0] "m" (g_timespec) : "rcx", "rsi"); return result; } #endif static inline int test_int80h() { register int result asm ("eax"); asm volatile ( "lea %[p0], %%ebx \n\t" "mov $0, %%ecx \n\t" "mov %[sysnum], %%eax \n\t" "int $0x80 \n\t" : "=r"(result) : [sysnum] "i" (SYS_gettimeofday), [p0] "m" (g_timespec) : "ebx", "ecx"); return result; } int (*g_f)(struct timeval *, struct timezone *); static void prepare_vdso() { void *vdso = dlopen("linux-vdso.so.1", RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD); if (!vdso) { vdso = dlopen("linux-gate.so.1", RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD); } assert(vdso && "vdso not found"); g_f = dlsym(vdso, "__vdso_gettimeofday"); } static int test_g_f() { return g_f(&g_timespec, 0); } #define VSYSCALL_ADDR 0xffffffffff600000UL static void prepare_vsyscall() { g_f = (void*)VSYSCALL_ADDR; } static inline int test_sysenter() { register int result asm ("eax"); asm volatile ( "lea %[p0], %%ebx \n\t" "mov $0, %%ecx \n\t" "mov %[sysnum], %%eax \n\t" "push $cont_label%=\n\t" "push %%ecx \n\t" "push %%edx \n\t" "push %%ebp \n\t" "mov %%esp, %%ebp \n\t" "sysenter \n\t" "cont_label%=: \n\t" : "=r"(result) : [sysnum] "i" (SYS_gettimeofday), [p0] "m" (g_timespec) : "ebx", "esp"); return result; } #ifdef TEST_SYSCALL #define TEST_PREPARE() #define TEST_PROC_CALL() test_syscall() #elif defined TEST_VDSO #define TEST_PREPARE() prepare_vdso() #define TEST_PROC_CALL() test_g_f() #elif defined TEST_VSYSCALL #define TEST_PREPARE() prepare_vsyscall() #define TEST_PROC_CALL() test_g_f() #elif defined TEST_INT80H #define TEST_PREPARE() #define TEST_PROC_CALL() test_int80h() #elif defined TEST_SYSENTER #define TEST_PREPARE() #define TEST_PROC_CALL() test_sysenter() #else #error Choose test #endif static inline unsigned long test() { unsigned long result = ULONG_MAX; struct timespec start = {0}, end = {0}; int rt, rt2, rt3; for (int i = 0; i < 1000; ++i) { rt = clock_gettime(CLOCK_MONOTONIC, &start); rt3 = TEST_PROC_CALL(); rt2 = clock_gettime(CLOCK_MONOTONIC, &end); assert(rt == 0); assert(rt2 == 0); assert(rt3 == 0); result = min(difftime(start, end), result); } return result; } int main() { TEST_PREPARE(); // prepare calls int a = TEST_PROC_CALL(); assert(a == 0); a = TEST_PROC_CALL(); assert(a == 0); a = TEST_PROC_CALL(); assert(a == 0); unsigned long result = test(); printf("%lu\n", result); } 

コンパむル


 gcc -O2 -DTEST_SYSCALL time_test.c -o test_syscall gcc -O2 -DTEST_VDSO -ldl time_test.c -o test_vdso gcc -O2 -DTEST_VSYSCALL time_test.c -o test_vsyscall #m32 gcc -O2 -DTEST_VDSO -ldl -m32 time_test.c -o test_vdso_32 gcc -O2 -DTEST_INT80H -m32 time_test.c -o test_int80 gcc -O2 -DTEST_SYSENTER -m32 time_test.c -o test_sysenter 

システムに぀いお
cat /proc/cpuinfo | grep "model name" -m 1 cat /proc/cpuinfo | grep "model name" -m 1 -Intel®CoreTMi7-5500U CPU @ 2.40GHz
uname -r -4.14.13-1-ARCH


結果衚


実装時間ns
int 80h498
sysenter338
シスコヌル278
vsyscall゚ミュレヌト692
vsyscallネむティブ278
vDSO37
vDSO-3251

ご芧のずおり、システムコヌルの新しい実装はそれぞれ、以前の実装よりも生産性が高く、vsysvallはカりントされたせん。これぱミュレヌションであるためです。 おそらく既に掚枬したように、vsyscallが意図したものである堎合、呌び出し時間はvDSOに䌌おいたす。


珟圚のすべおのパフォヌマンス比范は、メルトダりンの脆匱性を修正するKPTIパッチで行われおいたす。


ボヌナス KPTIなしのシステムコヌルパフォヌマンス


KPTIパッチは、メルトダりンの脆匱性を修正するために特別に開発されたした。 ご存知のように、このパッチはOSのパフォヌマンスを䜎䞋させたす。 KPTIをオフpti =オフにしおパフォヌマンスをチェックしたしょう。


パッチをオフにした結果の衚


実装時間nsパッチ埌の実行時間を増やすnsパッチ埌のパフォヌマンス䜎䞋(t1 - t0) / t0 * 100%
int 80h31718157
sysenter150188125
シスコヌル103175170
vsyscall゚ミュレヌト49619640
vsyscallネむティブ103175170
vDSO3700
vDSO-325100

パッチが玄180 nsかかり始めた埌、平均しおカヌネルモヌドぞの移行ずその逆の移行。 より倚くの時間、明らかにこれはTLBキャッシュをフラッシュする䟡栌です。


このタむプの呌び出しではカヌネルモヌドぞの移行がないため、vDSOを介したシステムコヌルのパフォヌマンスは䜎䞋しおいたせん。したがっお、TLBキャッシュをフラッシュする理由はありたせん。


さらに読むために


       Linux (  , ): https://0xax.gitbooks.io/linux-insides/content/SysCall/syscall-3.html   Linux: https://www.win.tue.nl/~aeb/linux/lk/lk-4.html   ,  1: https://lwn.net/Articles/604287/   ,  2: https://lwn.net/Articles/604515/ 

参照資料


[0] Intel 64およびIA-32アヌキテクチャ開発者マニュアルVol。 2B
[1] コヌド実行時間のベンチマヌク方法...
[2] AMDおよびIntel x86プロセッサヌの呜什レむテンシヌずスルヌプット
[3] AMD64 Architecture Programmer's Manual Volume 2システムプログラミング
[4] System V ABI AMD64



Source: https://habr.com/ru/post/J347596/


All Articles