2010-08-23 9 views

Respuesta

1

abierta() es una función de biblioteca, se encuentra en libc.a/libc.so

13

Dudo mucho que el compilador sepa que es una llamada al sistema. Es mucho más probable que open esté en una biblioteca en alguna parte y el código dentro de la biblioteca llame a la interfaz del kernel relevante.

La salida de montaje del programa simple:

#include <stdio.h> 
int main (void) { 
    int fd = open("xyz"); 
    return 0; 
} 

es (bits irrelevantes eliminados):

main: 
    pushl %ebp   ; stack frame setup. 
    movl %esp, %ebp 
    andl $-16, %esp 
    subl $32, %esp 

    movl $.LC0, (%esp) ; Store file name address. 
    call open   ; call the library function. 
    movl %eax, 28(%esp) ; save returned file descriptor. 

    movl $0, %eax  ; return 0 error code. 

    leave     ; stack frame teardown. 
    ret 

.LC0: 
    .string "xyz"   ; file name to open. 

Lo primero que notará es que hay una llamada-open. En otras palabras, es una función. No hay un int 80 o sysenter a la vista, que es el mecanismo utilizado para las llamadas al sistema adecuadas (en mi plataforma de todos modos, YMMV).

Las funciones de envoltura en libc son donde se realiza el trabajo real de acceder a la interfaz de llamada del sistema.

Un extracto de Wikipedia en system calls:

general, los sistemas proporcionan una biblioteca que se encuentra entre los programas normales y el sistema operativo, por lo general una implementación de la biblioteca de C (libc), tales como glibc. Esta biblioteca existe entre el sistema operativo y la aplicación, y aumenta la portabilidad.

En sistemas basados ​​en exokernel, la biblioteca es especialmente importante como intermediario. En exokernels, las bibliotecas protegen las aplicaciones de usuario de la API kernel de muy bajo nivel y proporcionan abstracciones y administración de recursos.

Los términos "llamada al sistema" y "syscall" a menudo se usan incorrectamente para referirse a las funciones de biblioteca estándar C, particularmente aquellas que actúan como un contenedor para las llamadas al sistema correspondientes con el mismo nombre. La llamada a la función de biblioteca no causa un cambio al modo kernel (si la ejecución no estaba ya en modo kernel) y suele ser una llamada de subrutina normal (es decir, utilizando una instrucción de ensamblaje "CALL" en algunas ISA). La llamada al sistema real transfiere el control al núcleo (y depende más de la implementación que la llamada a la biblioteca que lo abstrae). Por ejemplo, fork y execve son funciones GLIBC que a su vez llaman a las llamadas al sistema fork y execve.

Y, después de un poco de búsqueda, la función __open se encuentra en glibc 2.9 en el archivo io/open.c, y weakref 'ed a open.Si se ejecuta:

nm /usr/lib/libc.a | egrep 'W __open$|W open$' 

se pueden ver allí:

00000000 W __open 
00000000 W open 
+0

open también es llamada al sistema. No hay código para abrir en ninguna biblioteca. ¿Cómo se resuelve el compilador para la llamada abierta? –

+0

No es así, consulte la actualización. – paxdiablo

+0

Digamos, inserté mi propia llamada al sistema y compilé el kernel que no tiene la función de envoltura en libc. –

6

lectura es una llamada a la librería en lo que se refiere al compilador. Sucede que la implementación de libc define leer para generar una interrupción de software con el número correcto.

+0

No creo que haya ninguna implementación de lectura en libc? –

+7

@Ganesh Kundapur sí hay. Todas las llamadas al sistema están envueltas en funciones libc. (y hay una función genérica syscall() si desea construir el syscall) – nos

2

El compilador puede ver la declaración de esta función y genera un código objeto que hace una llamada a esa función.

tratar de compilar con gcc -S y verá algo como:

movl $100, %edx 
movq %rcx, %rsi 
movl %eax, %edi 
call read 

La llamada al sistema se hace de la implementación de la biblioteca C de la lectura (2).

EDITAR: específicamente, GNU libc (que es lo que probablemente tenga en Linux), establece las relaciones entre los números de syscall y los nombres de funciones en glibc-2.12.1/sysdeps/syscalls.list. Cada línea de ese archivo se convierte a un código fuente de lenguaje ensamblador (basado en sysdeps/unix/syscall-template.S), se compila y se agrega a la biblioteca cuando se genera libc.

+0

sí, pero internamente recupera el número de llamada del sistema para la lectura (__NR_read) y realiza una llamada como syscall (__ NR_read, fd, buf , 100); –

+1

@Ganesh Kundapur: ver edición. La llamada al sistema no se "recupera internamente", sino que se compila en libc. – Cubbi

1

La siguiente es la aplicación Android de leer en biónica (el equivalente para Android libc)

/* autogenerated by gensyscalls.py */ 
#include <sys/linux-syscalls.h> 

    .text 
    .type read, #function 
    .globl read 
    .align 4 
    .fnstart 

read: 
    .save {r4, r7} 
    stmfd sp!, {r4, r7} 
    ldr  r7, =__NR_read 
    swi  #0 
    ldmfd sp!, {r4, r7} 
    movs r0, r0 
    bxpl lr 
    b  __set_syscall_errno 
    .fnend 

Puede ver que carga __NR_read en r7 y luego llama a SWI, SWI es la interrupción de software que cambia el procesador al modo kernel. Por lo tanto, el compilador no necesita saber nada sobre cómo hacer llamadas al sistema, libc se ocupa de ello.

Cuestiones relacionadas