靈感來自這個問題系統調用在Linux上如何實際發生?
How can I force GDB to disassemble?
和與此相關的一個
如何實際的系統調用Linux下發生的呢?調用執行時會發生什麼,直到調用實際的內核例程?
靈感來自這個問題系統調用在Linux上如何實際發生?
How can I force GDB to disassemble?
和與此相關的一個
如何實際的系統調用Linux下發生的呢?調用執行時會發生什麼,直到調用實際的內核例程?
假設我們正在談論86:
INT 0x80
中斷被調用。我可能是在這個有點生疏了,它已經有幾年...
如果我沒有記錯,由於內核有自己的堆棧,所以用戶空間程序不能在其上放置任何東西,所以所有參數都必須通過寄存器傳遞。 – Benno 2009-08-07 17:18:07
真的嗎?我隱約記得我的教授提到Linux有一些將用戶空間地址映射到內核空間的宏...我可能是錯的。 – 2009-08-07 17:20:09
INT 0x80僅用於SYSCALL/SYSENTER指令不可用的情況下,IIRC。 – 2009-08-09 23:37:34
基本上,它很簡單:在某處內存躺着一個表,其中每個系統調用號和相應的處理程序的地址(請參見http://lxr.linux.no/linux+v2.6.30/arch/x86/kernel/syscall_table_32.S x86版本)
INT 0x80中斷處理程序然後將參數從寄存器中取出,放在(內核)堆棧上並調用相應的系統調用處理程序。
這已經回答了在
How is the system call in Linux implemented?
可能沒有用,因爲不同的「系統調用」長期使用的這個問題相匹配。
給出的答案是正確的,但我想補充說有更多的機制進入內核模式。每個最近的內核都在每個進程的地址空間中映射「vsyscall」頁面。它只包含最有效的系統調用陷阱方法。
例如常規的32位系統上它可能包含:
0xffffe000: int $0x80
0xffffe002: ret
但在我64 bitsystem我有機會的方式來使用更有效的方法的系統調用/ SYSENTER指令
0xffffe000: push %ecx
0xffffe001: push %edx
0xffffe002: push %ebp
0xffffe003: mov %esp,%ebp
0xffffe005: sysenter
0xffffe007: nop
0xffffe008: nop
0xffffe009: nop
0xffffe00a: nop
0xffffe00b: nop
0xffffe00c: nop
0xffffe00d: nop
0xffffe00e: jmp 0xffffe003
0xffffe010: pop %ebp
0xffffe011: pop %edx
0xffffe012: pop %ecx
0xffffe013: ret
這個vsyscall頁面還映射了一些可以在沒有上下文切換的情況下完成的系統調用。我知道一定gettimeofday的,時間和getcpu被映射在那裏,但我想GETPID可能適合在那裏一樣好。
+1,有趣的問題! – 2009-08-07 17:12:48
系統調用實現問題:http://stackoverflow.com/questions/499188/how-is-the-system-call-in-linux-實施 – nik 2009-08-07 17:17:05
投票自己關閉。實際上是重複的(沒有出現在搜索中,因爲我使用了系統調用) – 2009-08-07 18:41:14