2010-08-23 13 views

Répondre

1

open() est une fonction de bibliothèque, il trouve dans libc.a/libc.so

13

Je doute vraiment que le compilateur sait qu'il s'agit d'un appel système. Il est beaucoup plus probable que open se trouve dans une bibliothèque quelque part et le code dans la bibliothèque appelle l'interface de noyau appropriée.

La sortie de montage du programme simple:

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

est (bits non pertinents supprimés):

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. 

La première chose que vous remarquerez est qu'il ya un appel-open. En d'autres termes, c'est une fonction. Il n'y a pas un int 80 ou sysenter en vue, qui est le mécanisme utilisé pour les appels système appropriés (sur ma plate-forme de toute façon - YMMV).

Les fonctions d'encapsulation dans libc sont celles où le travail réel d'accès à l'interface d'appel système est effectué.

Un extrait de Wikipedia sur system calls:

fournissent généralement, des systèmes de la bibliothèque qui se trouve entre les programmes normaux et le système d'exploitation, généralement une mise en oeuvre de la bibliothèque C (libc), tels que glibc. Cette bibliothèque existe entre le système d'exploitation et l'application et augmente la portabilité.

Sur les systèmes basés sur exokernel, la bibliothèque est particulièrement importante en tant qu'intermédiaire. Sur les exokernels, les bibliothèques protègent les applications utilisateur de l'API de noyau de très bas niveau et fournissent des abstractions et une gestion des ressources. Les termes «appel système» et «appel système» sont souvent utilisés de manière incorrecte pour désigner les fonctions de bibliothèque standard C, en particulier celles qui servent d'encapsuleur aux appels système correspondants portant le même nom. L'appel à la fonction bibliothèque elle-même n'entraîne pas de basculement vers le mode noyau (si l'exécution n'était pas déjà en mode noyau) et est généralement un appel de sous-routine normal (par exemple, une instruction d'assemblage "CALL" dans certains ISA). L'appel système réel transfère le contrôle au noyau (et est plus dépendant de l'implémentation que l'appel de la bibliothèque l'abstrayant). Par exemple, fork et execve sont des fonctions GLIBC qui appellent à leur tour les appels système fork et execve.

Et, après un peu de recherche, la fonction __open se trouve dans la glibc 2.9 dans le fichier io/open.c et weakref « ed à open.Si vous exécutez:

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

vous pouvez les voir là-dedans:

00000000 W __open 
00000000 W open 
+0

ouvert est également un appel système. Il n'y a pas de code à ouvrir dans une bibliothèque. Comment le compilateur résout pour l'appel ouvert? –

+0

Pas ainsi, voir la mise à jour. – paxdiablo

+0

Disons, j'ai inséré mon propre appel système et compilé le noyau qui n'a pas de fonction wrapper dans libc. –

6

lecture est un appel de la bibliothèque dans la mesure où le compilateur est concerné. Il se trouve que l'implémentation libc définit read pour générer une interruption logicielle avec le nombre correct.

+0

Je ne pense pas qu'il y ait une implémentation en lecture dans libc? –

+7

@Ganesh Kundapur oui il y a. Tous les appels système sont enveloppés dans les fonctions libc. (et il y a une fonction générique syscall() si vous voulez construire le syscall vous-même) – nos

2

Le compilateur peut voir la déclaration de cette fonction, et il génère un code objet qui appelle cette fonction.

Essayez de compiler avec gcc -S et vous verrez quelque chose comme:

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

L'appel système est fabriqué à partir de la mise en œuvre de lecture de la bibliothèque C (2).

EDIT: spécifiquement, GNU libc (qui est probablement ce que vous avez sous Linux), établit les relations entre les numéros syscall et les noms de fonctions dans glibc-2.12.1/sysdeps/syscalls.list. Chaque ligne de ce fichier est convertie en un code source en langage assembleur (basé sur sysdeps/unix/syscall-template.S), compilé et ajouté à la bibliothèque lors de la construction de la libc.

+0

oui, mais en interne il récupère le numéro d'appel système pour la lecture (__NR_read) et appelle syscall (__ NR_read, fd, buf 100); –

+1

@Ganesh Kundapur: voir modifier. L'appel système n'est pas "récupéré en interne", il est compilé en libc. – Cubbi

1

Ci-dessous la mise en oeuvre de lire dans les applications bionique (l'équivalent pour les applications 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 

Vous pouvez voir qu'il charge __NR_read dans r7 puis appelle SWI, SWI est l'interruption logicielle qui commute le prcessor en mode kernel. Donc, le compilateur n'a besoin de rien savoir sur la façon de faire des appels système, libc s'en charge.