Noyau - Linux Attitude Skip to content

Linux Attitude

Le libre est un état d'esprit

Archive

Tag: Noyau

Alsa

Apr 21

Niveau :      
Résumé :

Aujourd'hui un truc obscur pour beaucoup d'entre nous : alsa. Pas la poudre blanche, mais le truc avec un mixer, enfin pas celui de la cuisine, mais celui de linux ...

Pour simplifier disons que alsa est une API présentée par le noyau et qui permet d'accéder à travers une interface unique à toutes les cartes son que vous pouvez avoir.

Fichier de configuration

Alsa étant relativement bien fait, ses utilisateurs (l'application qui émet du son, la gestion du volume ...) n'ont pas besoin de configuration particulière pour fonctionner. Mais il est possible de changer cette non configuration. Cela peut se faire soit de façon globale au système dans /etc/asound.conf soit spécifiquement à l'utilisateur dans ~/.asoundrc.

Que peut-on mettre dans ces fichiers ?

Là ça devient vite obscur et peu documenté. Mais nous allons voir que c'est assez simple. Il s'agit d'une configuration hiérarchique. Vous avez le choix entre les 2 formats suivants pour écrire des valeurs (ou un mix des 2) :

# commentaire
val.eur.1 "toto"
val.eur.2 "tata"
val.ue "help"

val {
  eur {
   1 "toto"
   2 "tata"
  }
  ue "help"
}

Éléments de configuration

Mais que peut-on bien mettre dans ce fichier ?

Ici les exemples sont nombreux, mais rarement expliqués.

Tout d'abord une liste détaillée se trouve ici : Asoundrc.txt

Reste à trouver ce que les attributs veulent dire. Ce qui va vous intéresser est essentiellement pcm qui permet de créer une nouvelle carte son (virtuelle). Les autres ne vous seront utiles que rarement et dépendront surtout du contenu de vos pcm.


continue reading...

Niveau :      
Résumé : /proc/sys/fs/binfmt_misc/register

Exécution

Savez-vous qu'on peut rendre n'importe quel fichier exécutable sous linux ? Bien sûr il suffit de faire un chmod +x, mais le noyau risque de vous envoyer balader si le fichier n'est pas réellement exécutable.

Mais je parle ici de rendre exécutable n'importe quel fichier, un jar, un source en C, un MP3 ...

Mais comment quoi que donc !?

Pour exécuter un fichier, le noyau lit les premiers octets du fichier et vérifie qu'ils correspondent à un format binaire (binfmt) connu. Il existe un système pour ajouter des formats binaires à ceux déjà supportés dans le noyau (en gros les elf et les scripts). Il s'agit du format misc.

Pour savoir si ce format est supporté chez vous, ce qui est très probable, lancez la commande :

$ cat /proc/sys/fs/binfmt_misc/status

S'il n'est pas supporté, il faut charger le module et monter le répertoire :

$ modprobe binfmt_misc
$ mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc 

continue reading...

Niveau :      
Résumé : grub ; noyau ; multiboot ; mandelbrot

Suite à de précédentes bidouilles, on veut faire mieux.

Multiboot

Donc grub peut booter plusieurs formats, l'un d'entre eux est le multiboot, un format de fichier bootable défini par les développeurs de grub espérant qu'il soit adopté par différentes distributions. Il souffre d'un certain nombre de faiblesses et n'est pas encore vraiment un standard. D'autant que grub lui-même ne supporte pas encore complètement la spécification pourtant très courte. Si vous ne voulez pas lire toute la spécification, allez directement au chapitre 4 où on trouve un code d'exemple prêt à compiler pour vous lancer dans le développement.

Vous trouverez un autre exemple chez quelqu'un qui s'est amusé à coder un space invaders bootable directement à partir de la spécification multiboot.

Alors c'est parti, reprenons notre projet précédent. Faites attention, le processeur est dans un état particulier lorsqu'on vous laisse la main (lisez le chapitre 3.2), à vous de vous en accommoder.

Mode graphique

Tout d'abord on voudrait changer le mode graphique, et si possible pour mieux que la première fois. Pour cela, on va utiliser le standard vesa 2.0 qui standardise des modes avec une plus grande définition et qui ajoute de nouvelles fonctions au bios pour manipuler la carte.

Choisissons le mode 0x118 (1024x768x24) avec 16 millions de couleurs. Plus besoin de gérer un palette puisqu'on écrit directement les couleurs RGB à utiliser pour le pixel. On aura tout de même une fonction de palette puisqu'on n'utilise qu'un petit nombre de couleurs placées sur une échelle.

Le problème c'est que vesa n'a pas prévu qu'on puisse appeler les fonctions de la carte en mode protégé sans passer au moins une fois par une interruption en mode réel. Multiboot est bien gentil, il a prévu le cas, malheureusement, grub n'implémente pas les fonctions qu'il devrait pour le faire pour nous. Un patch est disponible pour ceux qui voudrait quand même cette fonctionnalité.


continue reading...

Niveau :      
Résumé : grub ; noyau ; mandelbrot

Vous souvenez-vous du bon vieux temps ? Je vous parle du temps de l'autoexec.bat et des driver de quelques ko, le temps où on écrivait directement en mémoire vidéo, le temps de l'assembleur, du mode réel et des interruptions.

Hé bien cette époque bien que révolue nous a laissé des traces. Il est toujours possible de coder sans noyau, de faire son propre noyau, de se passer de système d'exploitation ou de booter directement sur une application en quelques secondes.

Boot loader

Choisissons un bootloader, grub par exemple, nous allons lui demander de lancer notre programme. Avec grub il existe plusieurs méthodes pour charger un os, entre autres :

  • Chainloader charge 512 octets, met le processeur en mode en mode réel, tel qu'il serait après le passage du bios. Pratique pour partir de zéro, mais 512 octet c'est un peu petit et nous n'avons pas vraiment envie de gérer le chargement de fichier sur le disque en plus.
  • Linux charge un noyau au format zimage ou bzimage et lui passe le contrôle en mode réel 16 bits. Il est possible de charger des fichiers de plusieurs méga avec le format bzimage.
  • Multiboot charge un noyau au format multiboot et lui passe le contrôle en mode protégé 32 bits après un certain nombre d'initialisations. On utilisera cette méthode une prochaine fois.

zImage

On commence par une solution simple à mettre en place, un exécutable au format zImage. Le format est décrit dans la documentation des sources du noyau linux : /usr/src/linux-2.X.XX/Documentation/i386/boot.txt. C'est dans ce format que nous allons développer un binaire bootable directement.

Le bootloader (grub) lit l'en-tête du fichier zImage puis pose la première section (attention, taille limitée à quelques dizaines de ko) à l'adresse 0x90000, Ensuite, il lit le reste du fichier et le place en 0x1000 (pour une zImage, limitée à 512ko) ou en 0x100000 (pour une bzImage). Ensuite, dans le cas de linux, le noyau s'amuse à redéplacer tout ça selon un processus plus ou moins compliqué décrit ici et ici. Attention, ne prenez pas ces documents pour argent comptant, ils sont un peu dépassés. En pratique nous n'irons pas si loin puisque nous resterons en mode réel et que 512ko nous seront largement suffisant (640Ko ça devrait suffire pour tout le monde !).

Nous allons donc faire simple et récupérer le code de boot de linux pour lancer notre petit projet. Le fichier qui contient le code de lancement ainsi que les en-têtes qui vont bien s'appelle header.S.

Attention, il est écrit en assembleur GNU (gas), celui-ci diffère beaucoup de l'assembleur intel. Le point le plus important est que les arguments sont inversés (source puis destination). header.S Apportons quelques modifications au fichier pour qu'il corresponde à nos besoins :


continue reading...

Niveau :      
Résumé : Internet Protocol

Pour ceux qui n'ont pas tout compris au dernier article réseau, voici quelques compléments sur le protocole IP. Celui qui vous permet d'envoyer n'importe quelle information à l'autre bout de la planète.

Toute machine sur internet dispose d'une adresse IP (v4 pour l'instant). Écrite sous la forme w.x.y.z où chaque lettre est un nombre compris entre 0 et 255 (donc un total de 32 bits). A chaque fois qu'une machine veut communiquer avec une autre elle remplit un paquet ip qu'elle envoie sur le réseau. Ce paquet soit contenir au moins les informations suivantes :

IP source
IP destination
protocole
Diverses choses

L'ip source, c'est tout simplement l'ip de la machine qui envoie le paquet et l'ip de destination peut être récupérée par le dns si le nom complet de la machine est connu.

Ce paquet doit être envoyé au bon routeur qui se débrouillera avec, et c'est là qu'intervient la configuration de la machine.

Supposons que nous soyons le noyau et essayons de traiter le paquet

#on regarde toutes les routes et on sélectionne celle qui nous intéresse
$ ip route show 
# on regarde l'ip source et la carte à partir de laquelle on va envoyer nos paquets
$ ip addr show
#ces deux opérations peuvent être résumées ainsi
$ ip route get w.x.y.z

La configuration de votre réseau se fait (au niveau du noyau) avec les commandes

# activation de la carte
$ ip link set dev toto up
# mise en place d'un adresse ip (et de son réseau)
$ ip addr add 10.0.1/24 dev toto
# mise en place d'un routage
$ ip route add default via 10.0.0.2

Heureusement, tout cela est fait automatiquement par votre distribution (à la lecture de /etc/nerwork/interfaces pour debian).

Vous aurez remarqué la notion de réseau, qui est apparu sous la forme 10.0.0.1/24. Cela veut dire que l'adresse 10.0.0.1 appartient au réseau constitué des ip de 10.0.0.0 à 10.0.0.255. Nous l'avons déduit grâce au maque /24 (qui s'écrit aussi 255.255.255.0), c'est-à-dire que les 24 premiers bits sont fixe.

On a beau avoir un cerveau brillant et pouvoir faire ceci de tête, le plus simple pour ne pas se tromper est d'utiliser un commande qui fait les calculs pour nous :

$ ipcalc 10.0.0.1/24

Vous remarquerez que dans un réseau il y a toujours 2 adresses qui ne peuvent pas être utilisées : la première, qui sert à désigner le réseau lui-même et la dernière qui sert de broadcast (envoi des paquets à tout le monde). Le plus petit réseau possible est donc un /30 avec 2 ip. Il est possible de faire plus petit, mais ce n'est plus vraiment un réseau au sens IP. On peut faire communiquer 2 IP dans un /31 moyennant quelques variations dans la configuration.

Niveau :      
Résumé : ip_forward ; iptables -j MASQUERADE ; iptables -j DROP ; brctl ; ip

Routeur

Un routeur, c'est une machine qui renvoie les paquets qui ne lui sont pas destinés vers d'autres machines qui les accepteront. Faisons-en un sous linux :

$ echo 1 > /proc/sys/net/ipv4/all/ip_forward

Facile hein ! Maintenant linux (le noyau) renverra tous les paquets qu'il reçoit (au niveau ethernet) mais qui ne lui sont pas destinés (au niveau IP). Reste plus qu'à maintenir une table de routage (avec la commande "route", "ip route" ou avec un démon dédié comme quagga qui le gère dynamiquement).

NAT

Parfois la machine de départ utilise des IP qui n'ont pas le droit d'aller sur internet (c'est pratique pour communiquer en interne, mais c'est tout). Le routeur (la passerelle) doit donc traduire ces IP privées en IP publiques (en général il utilise la sienne). C'est le NAT. Les réseaux ip privées sont : 10.0.0.0/8 172.16.0.0/12 et 192.168.0.0/16

Pour activer le nat sur un linux, il faut déjà qu'il fasse routeur (voir ci dessus), puis on transforme les paquets avec netfilter (netfilter est le fltre du noyau, iptables est la commande pour le piloter) :

$ iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE

Firewall

Un firewall va examiner la couche IP et la couche TCP pour filtrer ce qui se passe. Il peut tout faire, couper, changer le paquet ... Tout ceci se fait avec iptables sous linux. C'est un peu complexe, donc voici simplement un exemple qui coupe un utilisateur :

$ iptables -A FORWARD -s 10.0.0.12 -j DROP

Pont

Un pont (bridge) relie 2 (ou plus) réseaux ethernet comme le ferait un switch. Pour faire un bridge sous linux on utilise la commande brctl.

# on crée un nouveau bridge nommé bridge0
$ brctl addbr bridge0
# on ajoute les cartes réseau au bridge (le bridge prend l'adresse mac de la première carte ajoutée)
$ brctl addif bridge0 eth0
$ brctl addif bridge0 eth1

Et voila, à partir de ce moment, les paquets sont bien retransmis sur le réseau, si un paquet arrive sur une interface, il est retransmis sur l'autre s'il y a lieu. Mais si on veut que l'ordinateur qui fait bridge soit aussi sur le réseau en question, il faut y ajouter quelques modifications :

# on désactive la pile ip sur les cartes du bridge
$ ip addr del 10.0.0.1/24 dev eth0
$ ip addr del 10.0.1.1/24 dev eth1
# et on l'active sur le bridge lui-même (représenté pare une carte réseau virtuelle)
$ ip addr add 10.0.0.1/24 dev bridge0

Réseaux multiples

La notion de réseau IP est décorrélé de la notion de réseau ethernet. Il est donc parfaitement possible d'avoir plusieurs réseaux IP sur le même réseau ethernet. Et cela se fait très simplement :

$ ip addr add 10.0.0.1/24 dev eth0
$ ip addr add 192.168.0.1/24 dev eth0

Tunnel

Un tunnel permet d'encapsuler un flux entre 2 machines dans un autre flux. Par exemple le tunnel ssh encapsule un flux tcp dans un flux ssh.

Faisons tunnel ip, avec le module gre du noyau :

# on crée un tunnel nommé tunnel0 
$ ip tunnel add tunnel0 mode gre remote 1.2.3.4
# ce tunnel est en fait une interface virtuelle qu'on configure
$ ip link set tunnel0 up
$ ip addr add 10.0.1.1 dev tunnel0
# un tunnel n'a que 2 bouts, on choisit de gérer le sous-réseau à la main
$ ip route add 10.0.1.2 dev tunnel0

N'oubliez pas qu'il faut faire la même chose à l'autre bout du tunnel (avec des ip inversée bien sûr) et vous avez maintenant une carte réseau sur chaque machine reliées par un câble virtuel.

Niveau :      
Résumé : linux

Imaginez que vous soyez un simple utilisateur (un compte dans une université par exemple), alors les joies de l'administration système vous sont interdites. Heureusement une bande de jeunes hippies a décidé de faire quelque chose contre nature, essayer de transformer le noyau en simple application qui tournerait dans l'espace utilisateur. Et ça a marché, le noyau est maintenant un processus comme les autres.

On peut donc faire tourner linux sur un système existant, théoriquement un bsd ou un solaris peut même faire l'affaire, on a même trouvé des fous pour porter linux sous windows (cherchez colinux, vous trouverez).

Le noyau

Si vous êtes sous debian prenez le paquet user-mode-linux, et si vous êtes fans de la compilation de noyau :

$ make menuconfig ARCH=um
$ make ARCH=um

Et voila, il suffit de lancer linux :

$ linux

Le système

Bon, tout n'est pas si simple, il faudra bien que vous ayez un système de fichier pour ce linux. Si vous n'êtes pas root, vous devrez le préparer sur une autre machine. Il vous faut faire une image disque, soit à partir d'une installation existante, soit une nouvelle installation (par exemple avec debootstrap) :

# récupérer un disque existant
$ dd if=/dev/sda1 of=/data/image.dd

# créer un nouveau disque
$ dd if=/dev/zero of=/data/image.dd bs=1M count=512
$ mke2fs -j /data/image.dd
$ mount -o loop /data/image.dd /mnt
$ debootstrap etch /mnt
$ umount /mnt

Maintenant que nous avons notre image, c'est parti :

$ linux ubd0=/data/image.dd

continue reading...