Quelle est la différence entre un appel système et un appel de fonction? Fopen () est-il un appel système ou un appel de fonction?
Un appel système est un appel au code du noyau, généralement effectué en exécutant une interruption. L’interruption force le noyau à exécuter l’action demandée, puis redonne le contrôle à l’application. Cette commutation de mode est la raison pour laquelle les appels système sont plus lents à exécuter qu'une fonction équivalente au niveau de l'application.
fopen
est une fonction de la bibliothèque C qui effectue en interne un ou plusieurs appels système. En règle générale, en tant que programmeur C, vous devez rarement utiliser les appels système car la bibliothèque C les encapsule pour vous.
fopen est un appel de fonction.
Un appel système interagit avec le système d'exploitation sous-jacent, qui gère les ressources. Ses ordres de grandeur sont plus coûteux qu'un appel de fonction, car de nombreuses mesures doivent être prises pour préserver l'état du processus qui a déclenché l'appel système.
Sur les systèmes * nix, fopen ouvre, ce qui permet d’appeler le système (open est l’encapsuleur C pour l’appel système). La même chose arrive avec fread/read, fwrite/write, etc.
Ici il existe une belle description des tâches exécutées par un appel système unix.
En réalité, l'appel système n'est pas lié à l'appel de fonction. Le seul mécanisme commun à ces deux mécanismes est qu’ils fournissent tous deux des services à l’appelant.
De la vue de l'exécution du thread pour voir l'appel système:
Un appel système est une fonction pour que le programme en mode application demande des services fournis par le système d'exploitation souligné. L'appel système fera passer le fil d'exécution du mode utilisateur au mode noyau, exécutera la fonction de gestionnaire d'appels système, puis reviendra en mode utilisateur.
Paramètres Syscall:
Le paramètre d'un appel système est (numéro syscall, params ...). La signification et le format des paramètres dépendent du nombre d'appels système.
De la vue de la bibliothèque syscall fournie au programme userland:
Le programme en mode utilisateur appelle généralement la bibliothèque de glibc pour appeler un appel système. Par exemple, la fonction open () dans la glibc:
Si vous utilisez Linux, vous pouvez surveiller les appels système effectués par une application:
strace appname ...
Sa sortie peut vous donner une bonne idée de ce qui se passe dans libc et des fonctions qui sont en réalité des appels système.
L'appel système appelle en réalité une API exécutée par l'espace noyau. Avec tous les coûts associés, cela suppose (voir Wiki, ou ce lien pour plus de détails)
Un appel de fonction est un appel à un morceau de code dans l'espace utilisateur.
Toutefois, veuillez noter qu’un appel de fonction PEUT être attribué à une fonction qui, au cours de son exécution, appelle le système - "fopen" étant l’un de ces exemples. Ainsi, bien que l’appel à fopen soit un appel à une fonction, cela ne signifie pas que l’appel système n’arrivera pas à gérer les entrées/sorties réelles.
Un point de vue à ajouter à cette discussion est qu'un appel de fonction généralement dans le cas le plus optimiste entraîne une surcharge de quelques instructions de 8 bits (4 à 10 en moyenne) en x86.
Un appel système a les propriétés suivantes.
Pour ces trois raisons primitives (il y en a probablement plus), il convient de réduire autant que possible le nombre d'appels système - par exemple, le logiciel système en réseau conserve les descripteurs de socket (et d'autres structures de données internes spécifiques à l'application utilisées par une connexion) pour les affecter à de nouvelles connexion, pourquoi déranger le noyau?
Rappelez-vous que le logiciel est construit comme une pyramide à l'envers. Les appels système sont à la base.
La question a déjà d’excellentes réponses, mais je pense pouvoir ajouter quelque chose (un segment de ostep qui ne figure pas déjà dans les autres réponses).
Parfois, l'appel système et l'appel de fonction ont la même signature, par exemple, open()
:
open()
- appel système--- ~/Documents » man open(2)
OPEN(2) Linux Programmer's Manual OPEN(2)
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
...
open()
- appel de fonction$ man open(3)
--- ~/Documents »
OPEN(3P) POSIX Programmer's Manual OPEN(3P)
...
int open(const char *path, int oflag, ...);
...
Vous vous demandez peut-être pourquoi un appel à un appel système, tel que
open()
ouread()
, ressemble exactement à un appel de procéduredans C; autrement dit, s'il ressemble à un appel de procédure, comment le système sait-il qu’il s’agit d’un appel système, et fait tout ce qui est juste? La raison simple: c’est un appel de procédure, mais caché à l’intérieur de ce appel de procédureest le célèbre instruction trap. Plus précisément, lorsque vous appelezopen()
par exemple), vous exécutez un _ (appel de procéduredans la bibliothèque C. Dans ce cas, que ce soit pouropen()
ou pour l’un des autres appels systèmefourni , la bibliothèque utilise une convention d’appel convenue avec le noyau pour placer les arguments à ouvrir dans des emplacements bien connus (par exemple, sur le pile, ou dans un spécifique registres)), le système -callnuméro également dans un emplacement bien connu (encore une fois, sur le pileou un registre)), puis exécute la instruction d’interception) susmentionnée. Le code dans la bibliothèque après le trapunpacks) renvoie des valeurs et renvoie le contrôle au programme qui a émis le appel système. Ainsi, les parties de la bibliothèque C qui font les appels systèmesont codés à la main dans Assembly, car ils doivent suivre scrupuleusement les conventions pour traiter correctement les arguments et renvoyer les valeurs, ainsi que pour exécuter le instruction trap. Et maintenant vous savez pourquoi vous n'avez personnellement pas à écrire le code d'assembly dans trapdans un système d'exploitation; quelqu'un a déjà écrit cette assemblée pour vous.
Pour compléter le tableau présenté par les autres, fopen
est généralement implémenté en tant que wrapper autour de open
, qui est également une fonction accessible à l'utilisateur. fopen
est, dans un sens, de niveau supérieur à open
puisque la structure FILE*
qu'elle renvoie encapsule des éléments pour l'utilisateur. Certains utilisateurs utilisent directement open
pour des besoins particuliers. Par conséquent, il ne serait pas correct d'appeler fopen
un "appel système" de quelque manière que ce soit. Il n'exécute pas non plus les appels système directement , car open
est également une fonction appelable par l'utilisateur.
fopen
est un appel de fonction, mais il peut parfois être appelé un appel système car il est finalement géré par le "système" (le système d'exploitation). fopen
est intégré à la bibliothèque d'exécution C .
L'appel système est exécuté au niveau kernet et non pas dans l'espace utilisateur, car il nécessite un certain privilège pour accéder au matériel.
Par conséquent, lors de la programmation dans l’espace utilisateur et lors de l’appel d’une fonction ordinaire telle que fopen
en langage C, la libc encapsule généralement cette fonction dans un code spécifique dans lequel une interruption est générée pour passer de l’espace utilisateur à l’espace noyau; effectuer la fonctionnalité de l'appel de fonction au niveau matériel sera exécuté dans l'espace noyau.