linux linux - Quoi de mieux "int 0x80" ou "syscall"?




table x64 (5)

J'étudie le noyau Linux et découvre que pour l'architecture x86_64 , l'interruption int 0x80 ne fonctionne pas en tant qu'appel pour l'appel système.

La question est: dans le cas de l'architecture x86 , quel est préférable syscall ou int 0x80 et pourquoi?

EDIT : j'utilise le noyau 3.4


Answers

  • syscall est la méthode par défaut pour entrer en mode noyau sur x86-64 . Cette instruction n'est pas disponible dans les modes de fonctionnement 32 bits sur les processeurs Intel .
  • sysenter est une instruction utilisée le plus souvent pour invoquer des appels système dans des modes de fonctionnement 32 bits. C'est similaire à syscall , un peu plus difficile à utiliser, mais c'est la préoccupation du noyau.
  • int 0x80 est un moyen hérité pour appeler un appel système et doit être évité.

La meilleure façon d'invoquer un appel système est d'utiliser VDSO, une partie de la mémoire mappée dans chaque espace d'adressage de processus qui permet d'utiliser les appels système plus efficacement (par exemple, en n'entrant pas dans le mode noyau dans certains cas). VDSO se charge également de la gestion des instructions syscall ou sysenter .

Aussi, voir ceci et cela .


int 0x80 est une meilleure terminologie pour indiquer son appel système au noyau pour lui dire de faire quelque chose.

La signification et l'interprétation sont interchangeables, «faire un appel système» ou «émettre int 80h».

Ce n'est pas différent des jours de DOS:

  • invoque int 21h pour que DOS fasse quelque chose de dépendant sur le registre AX et éventuellement sur la paire de registres ES: DX,
  • int 13h est le gestionnaire de disque dur du BIOS.
  • int 10h est l'écran EGA / VGA.
  • int 09h est le gestionnaire de clavier.

Quel est le thème commun ici est, quand une interruption / syscall est invoquée, le noyau vérifie l'état des registres pour voir quel type d'appel système est requis. En regardant par exemple, eax register, par exemple, et déterminer ce qu'il faut effectuer, le contexte interne bascule dans l'espace noyau, exécute la procédure et le contexte revient à l'espace utilisateur, avec une option pour retourner les résultats de l'appel, c'est-à-dire était-ce réussi ou était-ce en échec.


Ma réponse ici couvre votre question.

En pratique, les noyaux récents implémentent un VDSO , notamment pour optimiser dynamiquement les appels système (le noyau positionne le VDSO à un meilleur code pour le processeur courant). Vous devriez donc utiliser le VDSO, et vous utiliserez mieux, pour les appels système existants, l'interface fournie par la libc.

Notez que, AFAIK, une partie importante du coût des syscalls simples va de l'espace utilisateur au noyau et vice versa. Par conséquent, pour certains appels système (probablement gettimeofday , getpid ...) le VDSO pourrait même éviter cela (et techniquement pourrait éviter de faire un véritable appel système). Pour la plupart des appels système (comme open , read , send , mmap ....), le coût du noyau de syscall est suffisamment important pour améliorer la transition de l'espace utilisateur vers l'espace noyau (ex: utilisation des instructions machine SYSENTER ou SYSCALL au lieu de INT ) insignifiant.



struct Point {
  double x;
  double y;
  double z;
  double& operator[]( std::size_t i ) {
    auto self = reinterpret_cast<uintptr_t>( this );
    auto v = self+i*sizeof(double);
    return *reinterpret_cast<double*>(v);
  }
  double const& operator[]( std::size_t i ) const {
    auto self = reinterpret_cast<uintptr_t>( this );
    auto v = self+i*sizeof(double);
    return *reinterpret_cast<double const*>(v);
  }
};

Cela repose sur l'absence de compression entre les double de votre structure. Affirmer que c'est difficile.

Une structure POD est une séquence d'octets garantie.

Un compilateur devrait être capable de compiler [] jusqu'aux mêmes instructions (ou en l'absence de celles-ci) en tant qu'arithmétique de pointeur ou d'accès à un tableau brut. Il peut y avoir certains problèmes où cette optimisation se produit "trop ​​tard" pour que d'autres optimzations se produisent, donc revérifiez le code sensible aux performances.

Il est possible que la conversion en insted char* ou std::byte* de uintptr_t soit valide, mais il y a un problème de base si l'arithmétique du pointeur est autorisée dans ce cas.





c linux linux-kernel system-calls