2009-08-07 13 views
9

Вдохновленный этим вопросомКак происходит syscall на linux?

How can I force GDB to disassemble?

и связанные с этим одним

What is INT 21h?

Каким образом на самом деле системный вызов произойдет под Linux? что происходит, когда вызов выполняется до тех пор, пока не будет вызвана действительная процедура ядра?

+0

+1, интересный вопрос! –

+0

вопрос реализации syscall: http://stackoverflow.com/questions/499188/how-is-the-system-call-in-linux-implemented – nik

+0

голосующий сам, чтобы закрыть. действительно, является дубликатом (не отображался при поиске, так как я использовал syscall) –

ответ

8

Предположим, что мы говорим о x86:

  1. ID of the system call осаждается в EAX регистр
  2. Любые аргументы, необходимые для системного вызова откладываются в locations dictated by the system call. Например, некоторые системные вызовы ожидают, что их аргумент будет находиться в регистре EBX. Другие могут ожидать, что их аргумент будет сидеть на вершине стека.
  3. Вызывается прерывание INT 0x80.
  4. Ядро Linux обслуживает системный вызов, идентифицируемый идентификатором в регистре EAX, внося любые результаты в заранее определенные местоположения.
  5. Вызывающий код использует любые результаты.

Может быть, я немного ржавый на это, это было несколько лет ...

+0

Если я правильно помню, так как ядро ​​имеет свой собственный стек, никакая программа пользовательского пространства не может что-то помещать на него, поэтому все аргументы должны передаваться через регистры. – Benno

+0

Действительно? Я смутно помню, как мой профессор упоминал, что Linux имеет несколько макросов для сопоставления адресов пользователей в ядерном пространстве ... Я мог ошибаться. –

+3

INT 0x80 используется только там, где инструкции SYSCALL/SYSENTER недоступны, IIRC. –

3

В принципе, его очень просто: Где-то в памяти лежит таблица, где каждый номер системного вызова и адрес соответствующего обработчика (см. http://lxr.linux.no/linux+v2.6.30/arch/x86/kernel/syscall_table_32.S для версии x86)

Обработчик прерываний INT 0x80 затем просто выводит аргументы из регистров, помещает их в стек (ядро) и вызывает соответствующий обработчик syscall.

7

Данные ответы верны, но я хотел бы добавить, что для входа в режим ядра существует больше механизмов. Каждое новое ядро ​​отображает страницу «vsyscall» в адресном пространстве каждого процесса. Он содержит немного больше, чем самый эффективный метод ловушки syscall.

Например, на обычной 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 может поместиться там точно так же.