 Guide pratique d'analyse du noyau (version franaise du KernelAnalysis HOWTO)

Roberto Arcomano berto_CHEZ_bertolinux_POINT_com

   Version : 0.7.fr.1.0 du 28 juin 2004

   --------------------------------------------------------------------------

   Ce document essaye d'expliquer quelques choses au sujet du noyau de Linux,
   tel que les composants les plus importants, comment ils fonctionnent,
   etc... Ce guide pratique devrait aider le lecteur  viter de devoir
   passer en revue tous les fichiers source du noyau pour rechercher la
   "bonne fonction", dclaration, et dfinition, et puis les lier les unes
   les autres. Vous pouvez trouver la dernire version originale de ce
   document  [1]http://www.bertolinux.com. Si vous avez des suggestions pour
   amliorer ce document, veuillez soumettre vos ides en anglais  mon
   adresse: [2]berto CHEZ bertolinux POINT com. La dernire version
   franaise: [3]http://www.traduc.org. Les corrections de la version
   franaise sont les bienvenues, veuillez en informer l'auteur sur son site
   ou sur [4]http://www.traduc.org.

   --------------------------------------------------------------------------

1. Introduction

1.1 Version franaise

   La version franaise de ce guide pratique a t ralise le 28 juin 2004
   par Patrick Trauquesegue.

1.2 Introduction

   Ce guide pratique essaye de dfinir comment les parties du Noyau Linux
   fonctionnent, ce que sont les principales fonctions et structures de
   donnes utilises, et comment la "roue tourne". Vous pouvez trouver la
   dernire version de ce document  [5]http://www.bertolinux.com. Si vous
   avez des suggestions pour amliorer ce document, veuillez soumettre vos
   ides en anglais  mon adresse: [6]berto CHEZ bertolinux POINT com. Le
   code utilis dans ce document se rapporte  la version 2.4.x de noyau de
   Linux, qui est la dernire version stable du noyau au moment d'crire ce
   guide pratique.

1.3 Copyright

   Copyright (C) 2000,2001,2002 Roberto Arcomano, traduction Patrick
   Trauquesegues. Ce document est libre; vous pouvez le redistribuer et/ou le
   modifier selon les termes de la Licence Publique Gnrale GNU telle que
   publie par la Free Software Foundation (fondation pour le logiciel
   libre); licence version 2, ou ( votre choix) toute version postrieure.
   Ce document est distribu dans l'espoir qu'il sera utile, mais SANS AUCUNE
   GARANTIE; sans mme de garantie implicite de VALEUR MARCHANDE ou
   d'UTILISATION POUR UN BUT PARTICULIER. Voyez la Licence Publique Gnrale
   GNU pour plus de dtails. Vous pouvez obtenir une copie de la GNU GPL
   [7]ici.

1.4 Traductions

   Si vous voulez traduire ce document vous tes libre de le faire.
   Cependant, vous aurez besoin de ce qui suit:

    1. Vrifiez qu'une autre version du document n'existe pas dj  votre
       LDP local
    2. Maintenez toutes les sections 'Introduction' (y compris
       'Introduction', 'copyright', 'Traductions', 'Remerciements')

   Avertissement! Vous ne devez pas traduire de fichier TXT ou HTML, vous
   devez modifier le dossier de LYX (Ndt: ou SGML), de sorte qu'il soit
   possible de le convertir dans tous autres formats (TXT, HTML, RIFF (RTF?),
   etc...): pour le faire vous pouvez utiliser l'application "LyX" 
   tlchargez sur [8]http://www.lyx.org.

   Aucun besoin de me demander de traduire! Vous juste devez me faire
   connatre (si vous voulez) votre traduction.

   Merci de votre traduction!

1.5 Remerciements

   Merci  [9]Linux Documentation Project pour publier et tlcharger
   rapidement mon document.

   Merci  Klaas de Waal pour ses suggestions.

2. Syntaxe utilise

2.1 Syntaxe de Fonction

   Quand nous parlons d'une fonction, nous crivons:

 "nom_de_function  [ fichier emplacement . extension ]"

   Par exemple:

 "schedule [kernel/sched.c]"

   nous dit que nous parlons de

   "schedule"

   function accessible depuis le fichier

   [ kernel/sched.c ]

   Note: Nous supposons /usr/src/linux comme racine du dossier.

2.2 Indentation

   L'indentation du code source est de 3 caractres blancs.

2.3 Analyse d'InterCallings

  Vue d'ensemble

   Nous utilisons l'analyse d'"InterCallings" (ICA) pour voir (de manire
   indente) comment les fonctions du noyau s'appellent les unes les autres.

   Par exemple, la commande de sleep_on est dcrite ainsi dans ICA:

 |sleep_on
 |init_waitqueue_entry      --
 |__add_wait_queue            |   enqueuing request
    |list_add                 |
       |__list_add          --
    |schedule              ---     waiting for request to be executed
       |__remove_wait_queue --
       |list_del              |   dequeuing request
          |__list_del       --

                           sleep_on ICA


   L'ICA indent est suivi par les fonctions d'emplacement:

     * sleep_on [kernel/sched.c]
     * init_waitqueue_entry [include/linux/wait.h]
     * __add_wait_queue
     * list_add [include/linux/list.h]
     * __list_add
     * schedule [kernel/sched.c]
     * __remove_wait_queue [include/linux/wait.h]
     * list_del [include/linux/list.h]
     * __list_del

   Note: Nous n'indiquons plus l'emplacement du dossier, s'il est indiqu
   juste avant.

  Dtails

   Dans un ICA une telle ligne ressemble  ce qui suit

  function1 -> function2

   signifie que < function1 > est un pointeur gnrique vers une autre
   fonction. Dans ce cas < function1 > pointe vers < function2 >.

   Quand nous crivons:

   function:

   a signifie que < fonction > n'est pas une vraie fonction. C'est une
   tiquette/un label (typiquement tiquette/label d'assembleur).

   Dans beaucoup de sections nous pouvons reporter un code ''C'' ou un
   ''pseudo-code''. Dans de vrais fichiers source, vous pourriez utiliser
   code ''assembleur'' ou ''non structur de ''. Cette diffrence est  but
   d'tude.

  POUR l'usage d'ICA

   Les avantages d'utiliser ICA (Analyse d'InterCallings) sont nombreux:

     * Vous obtenez une vue d'ensemble de ce qui se produit quand vous
       appelez une fonction du noyau.
     * L'emplacement des Fonctions est indiqu aprs la fonction, ainsi ICA
       pourrait aussi un peu tre appel "rfrence des fonctions"
     * L'analyse d'InterCallings (ICA) est utile dans des mcanismes de
       sleep/awake (sommeil/veill), o nous pouvons voir ce que nous
       faisons avant le sommeil, l'action propre au sommeil, et ce que nous
       feront aprs rveil (aprs programme).

  CONTRE l'usage d'ICA

     * Certains des inconvnients d'utiliser ICA sont numrs ci-dessous:
       Some of the disadvantages of using ICA are listed below:

   Comme tous les modles thoriques, nous simplifions la ralit vitant
   beaucoup de dtails, comme le vrai code source et les conditions
   spciales.

     * Additional diagrams should be added to better represent stack
       conditions, data values, etc.. Des diagrammes additionnels devraient
       tre ajouts pour mieux reprsenter les tats de pile, valeurs de
       donnes, etc...

3. Fondamentaux

3.1 Qu'est-ce que noyau?

   Le noyau est le "coeur" de n'importe quel systme informatique: c'est le
   "logiciel" qui permet aux utilisateurs de partager des ressources de
   informatique.

   On peut penser le noyau comme le logiciel principal du SE (Systme
   d'Exploitation ou OS pour Operating System en anglais), qui peut galement
   inclure la gestion de graphiques.

   Par exemple, sous Linux (comme d'autres Unix), l'environnement de XWindow
   n'appartient pas au noyau, parce qu'il contrle seulement des oprations
   graphiques (il utilise l' E/S du Mode Utilisateur pour accder  la carte
   vido).

   Par contre, les environnements de Windows (Win9x, WinME, WinNT, Win2K,
   WinXP, etc...) sont un mlange entre environnement graphique et noyau.

3.2 Quelle est la diffrence entre Mode Utilisateur et Mode Noyau?

  Vue d'ensemble

   Il y a quelques annes, quand les ordinateurs taient aussi grands qu'une
   pice, les applications utilisateur tournaient avec beaucoup de difficult
   et, parfois, faisaient planter l'ordinateur.

  Modes Oprationnel

   Pour viter d'avoir des applications qui plantent constamment, les
   nouveaux SE ont t conus avec 2 modes oprationnels:

    1. Mode Noyau: la machine fonctionne avec une structure de donnes
       critique, matriel direct (entre/sortie ou mmoire trace), mmoire
       directe, IRQ, DMA, etc...
    2. Mode Utilisateur: les utilisateurs peuvent faire tourner des
       applications.


                |          Applications           /|\
                |         ______________           |
                |         | User Mode  |           |
                |         ______________           |
                |               |                  |
 Implementation |        _______ _______           |   Abstraction
     Detail     |        | Kernel Mode |           |
                |        _______________           |
                |               |                  |
                |               |                  |
                |               |                  |
               \|/          Hardware               |

   Le Mode Noyau "empche" les applications de Mode Utilisateur d'endommager
   le systme ou ses dispositifs.

   Les microprocesseurs modernes implmentent dans le matriel au moins 2
   tats diffrents. Par exemple sous Intel, 4 tats dterminent le PL
   (niveau de privilge). Il est possible d'utiliser 0.1.2.3 tats, avec 0
   utilis pour le Mode Noyau.

   Le SE Unix requiert seulement 2 niveaux de privilge, et nous utiliserons
   un tel paradigme comme point de rfrence.

3.3 Commutation du Mode Utilisateur au Mode Noyau

  Quand commutons-nous?

   Une fois que nous avons compris qu'il y a 2 modes diffrents, nous devons
   savoir quand nous passons de l'un  l'autre.

   Typiquement, il y a 2 points de commutation:

    1. Quand on appelle un Appel Systme: aprs avoir appel un Appel
       Systme, la Tche appelle volontairement des des bouts de code
       rsidant en Mode Noyau.
    2. Quand une IRQ (ou exception) arrive: aprs l'IRQ un gestionnaire d'IRQ
       (ou gestionnaire d'exception) est appel, alors le contrle revient 
       la Tche qui a t interrompue comme si rien ne s'tait pass.

  Appels Systme

   Les Appels Systme sont comme des fonctions spciales qui grent les
   routines du SE qui rsident en Mode Noyau.

   Un Appel Systme peut tre appel quand nous:

     * accdons  une unit d'E/S ou  un fichier (comme lecture ou criture)
     * devons accder  une information privilgie (comme le pid, en
       changeant la politique de programmation (changing scheduling policy)
       ou une autre information)
     * devons changer le contexte d'excution (comme bifurquer ou excuter
       une autre application)
     * devons excuter une commande particulire (comme ''chdir'', ''kill",
       ''brk'', ou ''signal'')

                                  |                |
                          ------->| System Call i  | (Accessing Devices)
 |                |       |       |  [sys_read()]  |
 | ...            |       |       |                |
 | system_call(i) |--------       |                |
 |   [read()]     |               |                |
 | ...            |               |                |
 | system_call(j) |--------       |                |
 |   [get_pid()]  |       |       |                |
 | ...            |       ------->| System Call j  | (Accessing kernel data structures)
 |                |               |  [sys_getpid()]|
                                  |                |

     USER MODE                        KERNEL MODE


                         Unix System Calls Working

   Les Appels Systme sont presque la seule interface utilise par le Mode
   Utilisateur pour dialoguer avec des ressources de bas niveau (matriel).
   La seule exception  cette rgle est quand un processus utilise l'Appel
   Systme ''ioperm''. Dans ce cas le processus en Mode Utilisateur peut
   accder directement  un priphrique (les IRQs ne peuvent pas tre
   utilises).

   NOTE: Toutes les fonctions ''C'' ne sont pas des Appels Systme, seulement
   certaines d'entre-elles.

   Ci-dessous une liste d'Appels Systme du noyau 2,4,17 de Linux, de [
   arch/i386/kernel/entry.S ]

         .long SYMBOL_NAME(sys_ni_syscall)       /* 0  -  old "setup()" system call*/
         .long SYMBOL_NAME(sys_exit)
         .long SYMBOL_NAME(sys_fork)
         .long SYMBOL_NAME(sys_read)
         .long SYMBOL_NAME(sys_write)
         .long SYMBOL_NAME(sys_open)             /* 5 */
         .long SYMBOL_NAME(sys_close)
         .long SYMBOL_NAME(sys_waitpid)
         .long SYMBOL_NAME(sys_creat)
         .long SYMBOL_NAME(sys_link)
         .long SYMBOL_NAME(sys_unlink)           /* 10 */
         .long SYMBOL_NAME(sys_execve)
         .long SYMBOL_NAME(sys_chdir)
         .long SYMBOL_NAME(sys_time)
         .long SYMBOL_NAME(sys_mknod)
         .long SYMBOL_NAME(sys_chmod)            /* 15 */
         .long SYMBOL_NAME(sys_lchown16)
         .long SYMBOL_NAME(sys_ni_syscall)                               /* old break syscall holder */
         .long SYMBOL_NAME(sys_stat)
         .long SYMBOL_NAME(sys_lseek)
         .long SYMBOL_NAME(sys_getpid)           /* 20 */
         .long SYMBOL_NAME(sys_mount)
         .long SYMBOL_NAME(sys_oldumount)
         .long SYMBOL_NAME(sys_setuid16)
         .long SYMBOL_NAME(sys_getuid16)
         .long SYMBOL_NAME(sys_stime)            /* 25 */
         .long SYMBOL_NAME(sys_ptrace)
         .long SYMBOL_NAME(sys_alarm)
         .long SYMBOL_NAME(sys_fstat)
         .long SYMBOL_NAME(sys_pause)
         .long SYMBOL_NAME(sys_utime)            /* 30 */
         .long SYMBOL_NAME(sys_ni_syscall)                               /* old stty syscall holder */
         .long SYMBOL_NAME(sys_ni_syscall)                               /* old gtty syscall holder */
         .long SYMBOL_NAME(sys_access)
         .long SYMBOL_NAME(sys_nice)
         .long SYMBOL_NAME(sys_ni_syscall)       /* 35 */                /* old ftime syscall holder */
         .long SYMBOL_NAME(sys_sync)
         .long SYMBOL_NAME(sys_kill)
         .long SYMBOL_NAME(sys_rename)
         .long SYMBOL_NAME(sys_mkdir)
         .long SYMBOL_NAME(sys_rmdir)            /* 40 */
         .long SYMBOL_NAME(sys_dup)
         .long SYMBOL_NAME(sys_pipe)
         .long SYMBOL_NAME(sys_times)
         .long SYMBOL_NAME(sys_ni_syscall)                               /* old prof syscall holder */
         .long SYMBOL_NAME(sys_brk)              /* 45 */
         .long SYMBOL_NAME(sys_setgid16)
         .long SYMBOL_NAME(sys_getgid16)
         .long SYMBOL_NAME(sys_signal)
         .long SYMBOL_NAME(sys_geteuid16)
         .long SYMBOL_NAME(sys_getegid16)        /* 50 */
         .long SYMBOL_NAME(sys_acct)
         .long SYMBOL_NAME(sys_umount)                                   /* recycled never used phys() */
         .long SYMBOL_NAME(sys_ni_syscall)                               /* old lock syscall holder */
         .long SYMBOL_NAME(sys_ioctl)
         .long SYMBOL_NAME(sys_fcntl)            /* 55 */
         .long SYMBOL_NAME(sys_ni_syscall)                               /* old mpx syscall holder */
         .long SYMBOL_NAME(sys_setpgid)
         .long SYMBOL_NAME(sys_ni_syscall)                               /* old ulimit syscall holder */
         .long SYMBOL_NAME(sys_olduname)
         .long SYMBOL_NAME(sys_umask)            /* 60 */
         .long SYMBOL_NAME(sys_chroot)
         .long SYMBOL_NAME(sys_ustat)
         .long SYMBOL_NAME(sys_dup2)
         .long SYMBOL_NAME(sys_getppid)
         .long SYMBOL_NAME(sys_getpgrp)          /* 65 */
         .long SYMBOL_NAME(sys_setsid)
         .long SYMBOL_NAME(sys_sigaction)
         .long SYMBOL_NAME(sys_sgetmask)
         .long SYMBOL_NAME(sys_ssetmask)
         .long SYMBOL_NAME(sys_setreuid16)       /* 70 */
         .long SYMBOL_NAME(sys_setregid16)
         .long SYMBOL_NAME(sys_sigsuspend)
         .long SYMBOL_NAME(sys_sigpending)
         .long SYMBOL_NAME(sys_sethostname)
         .long SYMBOL_NAME(sys_setrlimit)        /* 75 */
         .long SYMBOL_NAME(sys_old_getrlimit)
         .long SYMBOL_NAME(sys_getrusage)
         .long SYMBOL_NAME(sys_gettimeofday)
         .long SYMBOL_NAME(sys_settimeofday)
         .long SYMBOL_NAME(sys_getgroups16)      /* 80 */
         .long SYMBOL_NAME(sys_setgroups16)
         .long SYMBOL_NAME(old_select)
         .long SYMBOL_NAME(sys_symlink)
         .long SYMBOL_NAME(sys_lstat)
         .long SYMBOL_NAME(sys_readlink)         /* 85 */
         .long SYMBOL_NAME(sys_uselib)
         .long SYMBOL_NAME(sys_swapon)
         .long SYMBOL_NAME(sys_reboot)
         .long SYMBOL_NAME(old_readdir)
         .long SYMBOL_NAME(old_mmap)             /* 90 */
         .long SYMBOL_NAME(sys_munmap)
         .long SYMBOL_NAME(sys_truncate)
         .long SYMBOL_NAME(sys_ftruncate)
         .long SYMBOL_NAME(sys_fchmod)
         .long SYMBOL_NAME(sys_fchown16)         /* 95 */
         .long SYMBOL_NAME(sys_getpriority)
         .long SYMBOL_NAME(sys_setpriority)
         .long SYMBOL_NAME(sys_ni_syscall)                               /* old profil syscall holder */
         .long SYMBOL_NAME(sys_statfs)
         .long SYMBOL_NAME(sys_fstatfs)          /* 100 */
         .long SYMBOL_NAME(sys_ioperm)
         .long SYMBOL_NAME(sys_socketcall)
         .long SYMBOL_NAME(sys_syslog)
         .long SYMBOL_NAME(sys_setitimer)
         .long SYMBOL_NAME(sys_getitimer)        /* 105 */
         .long SYMBOL_NAME(sys_newstat)
         .long SYMBOL_NAME(sys_newlstat)
         .long SYMBOL_NAME(sys_newfstat)
         .long SYMBOL_NAME(sys_uname)
         .long SYMBOL_NAME(sys_iopl)             /* 110 */
         .long SYMBOL_NAME(sys_vhangup)
         .long SYMBOL_NAME(sys_ni_syscall)       /* old "idle" system call */
         .long SYMBOL_NAME(sys_vm86old)
         .long SYMBOL_NAME(sys_wait4)
         .long SYMBOL_NAME(sys_swapoff)          /* 115 */
         .long SYMBOL_NAME(sys_sysinfo)
         .long SYMBOL_NAME(sys_ipc)
         .long SYMBOL_NAME(sys_fsync)
         .long SYMBOL_NAME(sys_sigreturn)
         .long SYMBOL_NAME(sys_clone)            /* 120 */
         .long SYMBOL_NAME(sys_setdomainname)
         .long SYMBOL_NAME(sys_newuname)
         .long SYMBOL_NAME(sys_modify_ldt)
         .long SYMBOL_NAME(sys_adjtimex)
         .long SYMBOL_NAME(sys_mprotect)         /* 125 */
         .long SYMBOL_NAME(sys_sigprocmask)
         .long SYMBOL_NAME(sys_create_module)
         .long SYMBOL_NAME(sys_init_module)
         .long SYMBOL_NAME(sys_delete_module)
         .long SYMBOL_NAME(sys_get_kernel_syms)  /* 130 */
         .long SYMBOL_NAME(sys_quotactl)
         .long SYMBOL_NAME(sys_getpgid)
         .long SYMBOL_NAME(sys_fchdir)
         .long SYMBOL_NAME(sys_bdflush)
         .long SYMBOL_NAME(sys_sysfs)            /* 135 */
         .long SYMBOL_NAME(sys_personality)
         .long SYMBOL_NAME(sys_ni_syscall)       /* for afs_syscall */
         .long SYMBOL_NAME(sys_setfsuid16)
         .long SYMBOL_NAME(sys_setfsgid16)
         .long SYMBOL_NAME(sys_llseek)           /* 140 */
         .long SYMBOL_NAME(sys_getdents)
         .long SYMBOL_NAME(sys_select)
         .long SYMBOL_NAME(sys_flock)
         .long SYMBOL_NAME(sys_msync)
         .long SYMBOL_NAME(sys_readv)            /* 145 */
         .long SYMBOL_NAME(sys_writev)
         .long SYMBOL_NAME(sys_getsid)
         .long SYMBOL_NAME(sys_fdatasync)
         .long SYMBOL_NAME(sys_sysctl)
         .long SYMBOL_NAME(sys_mlock)            /* 150 */
         .long SYMBOL_NAME(sys_munlock)
         .long SYMBOL_NAME(sys_mlockall)
         .long SYMBOL_NAME(sys_munlockall)
         .long SYMBOL_NAME(sys_sched_setparam)
         .long SYMBOL_NAME(sys_sched_getparam)   /* 155 */
         .long SYMBOL_NAME(sys_sched_setscheduler)
         .long SYMBOL_NAME(sys_sched_getscheduler)
         .long SYMBOL_NAME(sys_sched_yield)
         .long SYMBOL_NAME(sys_sched_get_priority_max)
         .long SYMBOL_NAME(sys_sched_get_priority_min)  /* 160 */
         .long SYMBOL_NAME(sys_sched_rr_get_interval)
         .long SYMBOL_NAME(sys_nanosleep)
         .long SYMBOL_NAME(sys_mremap)
         .long SYMBOL_NAME(sys_setresuid16)
         .long SYMBOL_NAME(sys_getresuid16)      /* 165 */
         .long SYMBOL_NAME(sys_vm86)
         .long SYMBOL_NAME(sys_query_module)
         .long SYMBOL_NAME(sys_poll)
         .long SYMBOL_NAME(sys_nfsservctl)
         .long SYMBOL_NAME(sys_setresgid16)      /* 170 */
         .long SYMBOL_NAME(sys_getresgid16)
         .long SYMBOL_NAME(sys_prctl)
         .long SYMBOL_NAME(sys_rt_sigreturn)
         .long SYMBOL_NAME(sys_rt_sigaction)
         .long SYMBOL_NAME(sys_rt_sigprocmask)   /* 175 */
         .long SYMBOL_NAME(sys_rt_sigpending)
         .long SYMBOL_NAME(sys_rt_sigtimedwait)
         .long SYMBOL_NAME(sys_rt_sigqueueinfo)
         .long SYMBOL_NAME(sys_rt_sigsuspend)
         .long SYMBOL_NAME(sys_pread)            /* 180 */
         .long SYMBOL_NAME(sys_pwrite)
         .long SYMBOL_NAME(sys_chown16)
         .long SYMBOL_NAME(sys_getcwd)
         .long SYMBOL_NAME(sys_capget)
         .long SYMBOL_NAME(sys_capset)           /* 185 */
         .long SYMBOL_NAME(sys_sigaltstack)
         .long SYMBOL_NAME(sys_sendfile)
         .long SYMBOL_NAME(sys_ni_syscall)               /* streams1 */
         .long SYMBOL_NAME(sys_ni_syscall)               /* streams2 */
         .long SYMBOL_NAME(sys_vfork)            /* 190 */
         .long SYMBOL_NAME(sys_getrlimit)
         .long SYMBOL_NAME(sys_mmap2)
         .long SYMBOL_NAME(sys_truncate64)
         .long SYMBOL_NAME(sys_ftruncate64)
         .long SYMBOL_NAME(sys_stat64)           /* 195 */
         .long SYMBOL_NAME(sys_lstat64)
         .long SYMBOL_NAME(sys_fstat64)
         .long SYMBOL_NAME(sys_lchown)
         .long SYMBOL_NAME(sys_getuid)
         .long SYMBOL_NAME(sys_getgid)           /* 200 */
         .long SYMBOL_NAME(sys_geteuid)
         .long SYMBOL_NAME(sys_getegid)
         .long SYMBOL_NAME(sys_setreuid)
         .long SYMBOL_NAME(sys_setregid)
         .long SYMBOL_NAME(sys_getgroups)        /* 205 */
         .long SYMBOL_NAME(sys_setgroups)
         .long SYMBOL_NAME(sys_fchown)
         .long SYMBOL_NAME(sys_setresuid)
         .long SYMBOL_NAME(sys_getresuid)
         .long SYMBOL_NAME(sys_setresgid)        /* 210 */
         .long SYMBOL_NAME(sys_getresgid)
         .long SYMBOL_NAME(sys_chown)
         .long SYMBOL_NAME(sys_setuid)
         .long SYMBOL_NAME(sys_setgid)
         .long SYMBOL_NAME(sys_setfsuid)         /* 215 */
         .long SYMBOL_NAME(sys_setfsgid)
         .long SYMBOL_NAME(sys_pivot_root)
         .long SYMBOL_NAME(sys_mincore)
         .long SYMBOL_NAME(sys_madvise)
         .long SYMBOL_NAME(sys_getdents64)       /* 220 */
         .long SYMBOL_NAME(sys_fcntl64)
         .long SYMBOL_NAME(sys_ni_syscall)       /* reserved for TUX */
         .long SYMBOL_NAME(sys_ni_syscall)       /* Reserved for Security */
         .long SYMBOL_NAME(sys_gettid)
         .long SYMBOL_NAME(sys_readahead)        /* 225 */



  Evnement IRQ

   Quand arrive une IRQ, la Tche qui tourne est interrompue pour servir (in
   order to service) le gestionnaire d'IRQ.

   Aprs que l'IRQ soit gre, le contrle retourne exactement au point de
   l'interruption, comme si rien ne s'tait pass.



               Running Task
              |-----------|          (3)
 NORMAL       |   |       | [break execution] IRQ Handler
 EXECUTION (1)|   |       |     ------------->|---------|
              |  \|/      |     |             |  does   |
  IRQ (2)---->| ..        |----->             |  some   |
              |   |       |<-----             |  work   |
 BACK TO      |   |       |     |             |  ..(4). |
 NORMAL    (6)|  \|/      |     <-------------|_________|
 EXECUTION    |___________|  [return to code]
                                     (5)
                USER MODE                     KERNEL MODE

          Transition Mode Utilisateur->Noyau cause par un vnement IRQ


   Les pas numrs plus bas se rfrent  la squence des vnements dans le
   diagramme au-dessus/

    1. Le processus est excut
    2. l'IRQ arrive alors que la Tche tourne.
    3. La Tche est interrompue pour appeler un "gestionnaire
       d'Interruption".
    4. Le code du "gestionnaire d'Interruption" est excut.
    5. Le contrle revient  la Tche en mode utilisateur (comme si rien ne
       s'tait pass)
    6. Le processus revient  une excution normale

   Un point spcialement intressant, l'IRQ Timer, qui se produit  chaque
   TIMER ms pour grer:

    1. Alarmes
    2. Compteurs systmes and Tches (utilis par un programmes pour dcider
       quand arrter un processus ou pour comptage (for accounting))
    3. Le mutiTche bas sur un mcanisme d'veil aprs un temps TIMESLICE.

3.4 Multitache

  Mcanisme

   Le point central d'un SE moderne est la "Tche". La Tche est une
   application qui tourne en mmoire en partageant toutes ressources (y
   compris CPU =processeur et mmoire) avec les autres Tches.

   Cette "ressource partage" est gre par le "Mcanisme MultiTche". Le
   Mcanisme MultiTche passe d'une Tche  une autre aprs un "timeslice"
   (temps de glissement). Les utilisateurs ont l'"illusion" qu'ils possdent
   toutes les ressources. On peut aussi imaginer un scnario simple
   utilisateur, quand un utilisateur paut avoir l'"illusion" de faire tourner
   plusieurs Tches en mme temps.

   Pour implmenter ce multitche, la Tche utilise la variable d'"tat"
   ("the state" variable), qui peut tre:

    1. READY, prt pour excution
    2. BLOCKED, en attente d'une ressource

   L'tat de la Tche est gr par sa prsence dans une liste relative: liste
   READY et liste BLOCKED.

  Changement de Tche

   Le mouvement d'une Tche  l'autre est appel ''Task Switching''
   (Changement de Tche). plusieurs ordinateurs ont une instruction
   matrielle qui ralise automatiquement cette opration. Le Changement de
   Tche se produit dans les cas suivants:

    1. Aprs la fin d'un Timeslice: nous devons programmer une Tche "Prte 
       excution" et lui donner accs (schedule a "Ready for execution" task
       and give it access).
    2. Quand une Tche doit attendre un priphrique: nous devons programmer
       une nouvelle Tche et l'y brancher *

   * Nous programmons une autre Tche pour viter "Busy Form Waiting" (forme
   occupe en attente), qui se produit quand nous attendons un priphrique
   au lieu de raliser un autre travail.

   Le Changement de Tche est gr par l'entit "Schedule" (Programme).


 Timer    |           |
  IRQ     |           |                            Schedule
   |      |           |                     ________________________
   |----->|   Task 1  |<------------------>|(1)Chooses a Ready Task |
   |      |           |                    |(2)Task Switching       |
   |      |___________|                    |________________________|
   |      |           |                               /|\
   |      |           |                                |
   |      |           |                                |
   |      |           |                                |
   |      |           |                                |
   |----->|   Task 2  |<-------------------------------|
   |      |           |                                |
   |      |___________|                                |
   .      .     .     .                                .
   .      .     .     .                                .
   .      .     .     .                                .
   |      |           |                                |
   |      |           |                                |
   ------>|   Task N  |<--------------------------------
          |           |
          |___________|

             Changement de Tche bas sur un glissement de temps (TimeSlice)


   Un Glissement de temps typique pour linux est environ 10ms.




  |           |
  |           | Resource    _____________________________
  |   Task 1  |----------->|(1) Enqueue Resource request |
  |           |  Access    |(2)  Mark Task as blocked    |
  |           |            |(3)  Choose a Ready Task     |
  |___________|            |(4)    Task Switching        |
                           |_____________________________|
                                        |
                                        |
  |           |                         |
  |           |                         |
  |   Task 2  |<-------------------------
  |           |
  |           |
  |___________|

      Changement de Tche bas sur l'Attente d'une Ressource


3.5 Micronoyau vs SE Monolithique

  Vue d'ensemble

   Jusqu' maintenant nous avons vus le SE appel Monolithique, mais il y a
   aussi une autre sorte de SE: ''Micronoyau''.

   Un Micronoyau utilise des Tches, pas seulement pour les processus en mode
   utilisateur, mais aussi comme un vrai gestionnaire de noyau, comme
   Tche-Disquette, Tche-DD, Tche-Rseau etc. Quelques exemples sont
   Amoeba, et Mach.

  POURS et CONTRES le SE Micronoyau

   POURS:

     * Le SE est plus simple  maintenir parce que chaque Tche gre un seul
       type d'opration. Aussi si vous voulez modifier le rseau, vous
       modifiez Tche-Rseau (idalement, si une mise  jour structurelle
       n'est pas ncessaire).

   CONTRES:

     * Les performances sont pires que pour un SE Monolithique, parce que
       vous devez ajouter 2*TASK_SWITCH temps ou temps de changement (le
       premier pour entrer dans la Tche spcifique, le second pour en
       sortir)

   Mon opinion personnelle est que, les Micronoyaux sont un bon exemple
   didactique (comme Minix) mais ils ne sont pas "optimums", aussi ils ne
   sont pas rellement convenables. Linux utilise quelques Tches, appeles
   "Fils Noyau" pour implmenter une petite structure Micronoyau (comme
   kswapd, qui est utilis pour rcuprer les pages mmoire du stockage de
   masse). Dans ce cas il n'y a aucun problme de performance parce que le
   glissement (swapping) est un travail trs lent.

3.6 Rseau

  Niveaux ISO OSI

   Le standard ISO-OSI dcrit une architecture rseau avec les niveaux
   suivants:

    1. Niveau physique (exemples: PPP et Ethernet)
    2. Niveau lien-donne (Data-link) (exemples: PPP et Ethernet)
    3. Niveau rseau (Network) (exemples: IP, et X.25)
    4. Niveau transport (exemples: TCP, UDP)
    5. Niveau session (SSL)
    6. Niveau prsentation (FTP cod binaire-ascii)
    7. Niveau application (applications comme Netscape)

   Les 2 premiers niveaux lits ci-dessus sont souvent implments dans le
   matriel. Les niveaux suivants sont dans le logiciel (ou firmware
   (matriel spcifiques?) pour les routeurs).

   Plusieurs protocoles sont utiliss par un SE: un d'eux est TCP/IP (le plus
   important qui rside aux niveaux 3-4).

  Que fait le noyau?

   Le noyau ne sait rien faire des 2 premiers niveaux de ISO-OSI.

   Au RX il:

    1. Il gre (handshake) les priphriques de bas niveau (comme carte
       ethernet ou modem) en recevant des "cadres" (frames) de leur part.
    2. Il construit des "paquets" TCP/IP  partir des "cadres" (comme ceux
       d'Ethernet ou de PPP).
    3. Convertit des ''paquets'' dans des ''connexions'' en les passant  la
       bonne application (grce au numro de port) ou
    4. Transmet des paquets  la bonne queue

 (cadres)       (paquets)            (connexions)
 frames         packets              sockets
 NIC ---------> Kernel ----------> Application
                  (Noyau)
                   |    packets
                   --------------> Forward
                         - RX -       (Transmission)

   Au stage TX il:

    1. Convertit des connexions ou
    2. Des donnes de queues (Queues datas) dans des ''paquets'' TCP/IP
    3. Partage des ''packets" en "cadres" (comme ceux d'Ethernet ou de PPP)
    4. Envoie des ''cadres'' en utilisant des pilotes HW

 (connexion)   (paquets)                   (cadres)
 sockets       packets                     frames
 Application ---------> Kernel ----------> NIC
               packets     /|\
 Forward  -------------------
 (Transmission)          - TX -



3.7 Mmoire virtuelle

  Segmentation

   La segmentation est la premire mthode pour rsoudre les problmes
   d'allocation mmoire: il vous permet de compiler du code source sans se
   soucier d'o l'application sera place dans la mmoire. En fait, cette
   caractristique aide les dveloppeurs d'application  dvelopper de faon
   indpendante du SE et aussi du matriel.


             |       Stack        |
             |          |         |
             |         \|/        |
             |        Free        |
             |         /|\        |     Segment <---> Process
             |          |         |
             |        Heap        |
             | Data uninitialized |
             |  Data initialized  |
             |       Code         |
             |____________________|

                    Segment


   Nous pouvons dire qu'un segment est l'entit logique d'une application, ou
   l'image de l'application en mmoire.

   Quand on programme, on ne se soucie pas de o nos donnes sont mises en
   mmoire, on ne s'intresse qu' l'offset  l'intrieur de notre segment
   (notre application). (the offset inside our segment (our application))

   On a l'habitude d'assigner un Segment  chaque processus et vice-versa.
   Avec Linux ce n'est pas vrai. Linux utilise seulement 4 segments pour
   chaque Noyau et tous les Processus.

  Problme de Segmentation


                                  ____________________
                           ----->|                    |----->
                           | IN  |     Segment A      | OUT
  ____________________     |     |____________________|
 |                    |____|     |                    |
 |     Segment B      |          |     Segment B      |
 |                    |____      |                    |
 |____________________|    |     |____________________|
                           |     |     Segment C      |
                           |     |____________________|
                           ----->|     Segment D      |----->
                             IN  |____________________| OUT

                      Segmentation problem



   Dans le diagramme au-dessus, nous voulons sortir des processus A et D et
   entrer dans le processus B. Comme on peut voir il y a assez d'espace pour
   B, mais nous ne pouvons pas le partager en 2 morceaux, aussi nous NE
   POUVONS PAS le charger (plus de mmoire).

   La raison de ce problme est les purs segments sont des zones continues
   (parce que ce sont des zones logiques) et ne peuvent pas tre partages.

  Pagination


              ____________________
             |     Page 1         |
             |____________________|
             |     Page 2         |
             |____________________|
             |      ..            |     Segment <---> Process
             |____________________|
             |     Page n         |
             |____________________|
             |                    |
             |____________________|
             |                    |
             |____________________|

                    Segment


   La Pagination partage la mmoire en "n" morceaux, chacun d'eux avec une
   longueur fixe.

   Un processus peut tre charg en une ou plusieurs pages. Quand la mmoire
   est libre, toutes les pages sont libres (voir Problme de
   Segmentation, avant).

   La Pagination est aussi utilise dans un autre but important, le
   "Swapping" (glissement). Si une page n'est pas prsente dans la mmoire
   physique, il gnre une EXCEPTION, qui poussera le Noyau  chercher une
   nouvelle page dans la mmoire de stockage. Ce mcanisme permet au SE de
   charger plus d'applications que celles permises seulement par la mmoire
   physique.

  Problme de Pagination

              ____________________
    Page   X |     Process Y      |
             |____________________|
             |                    |
             |       WASTE        |
             |       SPACE        |
             |____________________|

             Problme de Pagination


   Dans le diagramme qu-dessus, nous pouvons voir ce qui ne va pas dans la
   politique de pagination: quand un Processus Y se charge dans la Page X,
   TOUT l'espace mmoire de la Page est allou, aussi l'espace restant  la
   fin de la page est perdu.

  Segmentation et Pagination

   Comment peut-on rsoudre les problmes de segmentation et de pagination?
   En utilisant les 2 politiques.


                                   |      ..            |
                                   |____________________|
                             ----->|      Page 1        |
                             |     |____________________|
                             |     |      ..            |
  ____________________       |     |____________________|
 |                    |      |---->|      Page 2        |
 |      Segment X     |  ----|     |____________________|
 |                    |      |     |       ..           |
 |____________________|      |     |____________________|
                             |     |       ..           |
                             |     |____________________|
                             |---->|      Page 3        |
                                   |____________________|
                                   |       ..           |


   Le Processus X, identifi par le Segment X, est partag en 3 morceaux et
   chacun d'eux est charg dans une page.

   Nous n'avons pas de:

    1. Problme de Segmentation: nous allouons par Pages, ainsi nous librons
       aussi les Pages, et nous grons l'espace libre de faon optimise.
    2. Problme de Pagination: seule la dernire page perd de l'espace, mais
       nous pouvons dcider d'utiliser de trs petites pages, par exemple
       4096 octets de long (perdant au maximum 4096*N_Tches octets) et grer
       une pagination hierarchise (manage hierarchical paging) (en utilisant
       2 ou 3 niveaux de pagination)




                           |         |           |         |
                           |         |   Offset2 |  Value  |
                           |         |        /|\|         |
                   Offset1 |         |-----    | |         |
                       /|\ |         |    |    | |         |
                        |  |         |    |   \|/|         |
                        |  |         |    ------>|         |
                       \|/ |         |           |         |
  Base Paging Address ---->|         |           |         |
                           | ....... |           | ....... |
                           |         |           |         |

                      Hierarchical Paging

4. Dmarrage De Linux

   Nous dmarrons le noyau Linux par du code de C excut  partir de
   l'tiquette asm ''startup_32:

 |startup_32:
    |start_kernel
       |lock_kernel
       |trap_init
       |init_IRQ
       |sched_init
       |softirq_init
       |time_init
       |console_init
       |#ifdef CONFIG_MODULES
          |init_modules
       |#endif
       |kmem_cache_init
       |sti
       |calibrate_delay
       |mem_init
       |kmem_cache_sizes_init
       |pgtable_cache_init
       |fork_init
       |proc_caches_init
       |vfs_caches_init
       |buffer_init
       |page_cache_init
       |signals_init
       |#ifdef CONFIG_PROC_FS
         |proc_root_init
       |#endif
       |#if defined(CONFIG_SYSVIPC)
          |ipc_init
       |#endif
       |check_bugs
       |smp_init
       |rest_init
          |kernel_thread
          |unlock_kernel
          |cpu_idle

     * startup_32 [arch/i386/kernel/head.S]
     * start_kernel [init/main.c]
     * lock_kernel [include/asm/smplock.h]
     * trap_init [arch/i386/kernel/traps.c]
     * init_IRQ [arch/i386/kernel/i8259.c]
     * sched_init [kernel/sched.c]
     * softirq_init [kernel/softirq.c]
     * time_init [arch/i386/kernel/time.c]
     * console_init [drivers/char/tty_io.c]
     * init_modules [kernel/module.c]
     * kmem_cache_init [mm/slab.c]
     * sti [include/asm/system.h]
     * calibrate_delay [init/main.c]
     * mem_init [arch/i386/mm/init.c]
     * kmem_cache_sizes_init [mm/slab.c]
     * pgtable_cache_init [arch/i386/mm/init.c]
     * fork_init [kernel/fork.c]
     * proc_caches_init
     * vfs_caches_init [fs/dcache.c]
     * buffer_init [fs/buffer.c]
     * page_cache_init [mm/filemap.c]
     * signals_init [kernel/signal.c]
     * proc_root_init [fs/proc/root.c]
     * ipc_init [ipc/util.c]
     * check_bugs [include/asm/bugs.h]
     * smp_init [init/main.c]
     * rest_init
     * kernel_thread [arch/i386/kernel/process.c]
     * unlock_kernel [include/asm/smplock.h]
     * cpu_idle [arch/i386/kernel/process.c]

   La dernire fonction ''rest_init'' fait ceci:

    1. lance le fil ''init'' du noyau
    2. appelle unlock_kernel
    3. fait tourner la routine de cpu_idle par le noyau, celle sera la boucle
        vide s'excutant quand rien n'est programm

   En fait la procdure start_kernel ne finit jamais. Elle excutera la
   routine de cpu_idle sans fin.

   Suit la description de ''d'init'', qui est le premier fil du noyau:

 |init
    |lock_kernel
    |do_basic_setup
       |mtrr_init
       |sysctl_init
       |pci_init
       |sock_init
       |start_context_thread
       |do_init_calls
          |(*call())-> kswapd_init
    |prepare_namespace
    |free_initmem
    |unlock_kernel
    |execve

5. Particularits De Linux

5.1 Vue d'ensemble

   Linux a quelques particularits qui le distinguent d'autre SE. Ces
   particularits incluent:

    1. Paginations seules
    2. Softirq
    3. Fils du noyau
    4. Modules du noyau
    5. Dossier ''Proc''

  Elments De Flexibilit

   Les points 4 et 5 donnent une norme flexibilit aux administrateurs
   systme sur la configuration systme du Mode Utilisateur leur permettant
   de rsoudre galement des erreurs de noyau critiques ou des problmes
   spcifiques sans relancer la machine. Par exemple, si vous devez changer
   quelque chose sur un gros serveur et vous ne voulez pas faire une
   rinitialisation, vous pourriez prparer le noyau  dialoguer avec un
   module, que vous crirez.

5.2 Paginations seules

   Linux n'utilise pas la segmentation pour distinguer les Tches les unes
   des autres; il utilise la pagination. (seulement 2 segments sont utiliss
   pour tous les Tches, CODE et DATA/stack)

   Nous pouvons galement dire qu'un dfaut de page interTask ne se produit
   jamais, parce que chaque Tche utilise un ensemble de Tables de Page
   diffrents pour chaque Tche. Il y a quelques cas o des Tches
   diffrentes pointent vers les mmes Tables de page, comme les
   bibliothques partages: c'est ncessaire pour rduire l'utilisation de la
   mmoire; rappelez-vous que les bibliothques partages sont seulement du
   CODE parce que toutes les donnes sont stockes dans la pile actuelle de
   la Tche.

  Segments de Linux

   Sous le noyau Linux seulement 4 segments existent:

    1. Kernel Code [0x10] (Code Noyau)
    2. Kernel Data / Stack [0x18] (Donnes Noyau / Pile)
    3. User Code [0x23] (Code Utilisateur)
    4. User Data / Stack [0x2b] (Donnes D'Utilisateur / Pile)

   [ la syntaxe est ''But [Segment]'']

   Sous architecture Intel, les registres de segment utiliss sont:

     * CS pour Code Segment
     * DS pour Data Segment (Segment Donnes)
     * SS pour Stack Segment (Segment Pile)
     * ES pour Alternative Segment (Segment Alternatif) (par exemple utilis
       pour faire une copie de mmoire entre 2 segments)

   Ainsi, chaque Tche utilise 0x23 pour le code et le 0x2b pour donnes/pile

  Pagination Linux

   Sous Linux 3 niveaux des pages sont utiliss, selon l'architecture. Sous
   Intel seulement 2 niveaux sont supports. Linux supporte aussi la Copie
   sur mcanismes Ecriture (voir Chap.10 pour plus d'information).

  Pourquoi les conflits d'adresse interTasks n'existent-ils pas?

   La rponse est trs trs simple: les conflits d'adresse interTask ne
   peuvent pas exister parce qu'ils sont impossibles. Le traage linaire ->
   physique est fait par "Pagination", ainsi il a juste besoin d'assigner les
   pages physiques de manire univoque.

  Avons-nous besoin de dfragmenter la mmoire?

   Le numro d'Assignement de page est un processus dynamique. Nous avons
   besoin d'une seule page quand une Tche le demande, ainsi nous la
   choisissons dans les pages libres de manire ordonne. Quand nous voulons
   librer la page, nous devons seulement l'ajouter  la liste des pages
   libres.

  Et au sujet des pages noyau?

   Les pages noyau ont un problme: elles peuvent tre assignes de faon
   dynamique mais nous ne pouvons pas avoir de garantie qu'elles sont dans
   une zone alloue continue, parce que l'espace linaire du noyau est
   quivalent  l'espace physique du noyau.

   Pour le Segment Code il n'y a pas de problme. Le code de dmarrage est
   assign lors du dmarrage (aussi nous avons une quantit fixe de mmoire 
   assigner), et sur les modules nous devons seulement allouer une zone
   mmoire qui pourrait contenir le code du module.

   Le vrai problme est le segment de pile parce que chaque Tche utilise des
   pages de pile noyau. Les segments de pile doivent tre contigus (selon la
   dfinition de pile), ainsi nous devons tablir une limite maximum pour la
   dimension de pile de chaque Tche. Si nous dpassons cette limite, de
   mauvaises choses se produisent. Nous recouvrons des structures de donnes
   de processus en Mode Noyau.

   La structure du noyau nous aide, parce que les fonctions du noyau ne sont
   jamais:

     * recursives
     * intercalling plus de N fois.

   Une fois que nous connaissons N, et que nous connaissons la moyenne des
   variables statiques pour toutes les fonctions noyau, nous pouvons estimer
   une limite de pile.

   Si vous voulez tester le problme, vous pouvez crer un module avec une
   fonction qui s'appelle plusieurs fois. Aprs un nombre fix de fois, le
   module du noyau abandonnera en raison d'une faute du gestionnaire de page
   d'exception (typiquement crire  une page lecture-seule).

5.3 Softirq

   Quand un IRQ arrive, la commutation de Tche est reporte  plus tard pour
   obtenir de meilleures performances. Quelques travaux de Tche (qui
   pourrait devoir tre fait juste aprs l'IRQ et qui pourraient prendre
   beaucoup de processeur dans le temps d'interruption, comme accumuler un
   paquet de TCP/IP) sont mis en queue (aligns) et seront faits au temps
   programm (une fois qu'un temps-tranche (time-slice) finit).

   Dans les noyaux rcents (2.4.x) les mcanismes de softirq sont passs  un
   kernel_thread (fil de noyau): ''ksoftirqd_CPUn''. n reprsente le nombre
   processeur excutant le kernel_thread (dans systme monoprocessor
   ''ksoftirqd_CPU0'' utilise PID 3).

  Prparation De Softirq

  Autoriser Softirq

   Le ''cpu_raise_softirq'' est une routine qui rveille le fil du noyau
   ''ksoftirqd_CPU0'', pour le laisser contrler le travail mis en file
   d'attente.

 |cpu_raise_softirq
    |__cpu_raise_softirq
    |wakeup_softirqd
       |wake_up_process

     * cpu_raise_softirq [kernel/softirq.c]
     * __cpu_raise_softirq [include/linux/interrupt.h]
     * wakeup_softirq [kernel/softirq.c]
     * wake_up_process [kernel/sched.c]

   la routine ''__de cpu_raise_softirq__'' placera le bon octet dans le
   vecteur dcrivant le softirq en suspens.

   ''wakeup_softirq'' utilise le ''wakeup_process'' pour rveiller le fil du
   noyau ''ksoftirqd_CPU0''.

  Excution De Softirq

   A FAIRE: dcrire les structures de donnes impliques dans le mcanisme de
   softirq.

   Quand le fil noyau ''ksoftirqd_CPU0'' a t rveill, il excute les
   travaux de la file.

   Le code de ''ksoftirqd_CPU0'' est (boucle principale sans fin):

 for (;;) {
    if (!softirq_pending(cpu))
       schedule();
       __set_current_state(TASK_RUNNING);
    while (softirq_pending(cpu)) {
       do_softirq();
       if (current->need_resched)
          schedule
    }
    __set_current_state(TASK_INTERRUPTIBLE)
 }

     * ksoftirqd [kernel/softirq.c]

5.4 Fils Du Kernel

   Quoique Linux soit un OS monolithique, quelques ''fils du noyau'' existent
   pour faire le mnage.

   Ces Tches n'utilisent pas la mmoire Utilisateur; elles partagent la
   mmoire NOYAU. Elles oprent galement avec le privilge le plus lev
   (ANNEAU 0 sur une architecture i386) comme tout autre bout de code Mode
   Noyau.

   Des fils du noyau sont crs par la fonction ''kernel_thread [
   arch/i386/kernel/process ]'', qui appelle un appel systme ''clone'' [
   arch/i386/kernel/process.c ] de l'assembleur (qui est ''une fourche''
   comme l'appel systme):

 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
         long retval, d0;

         __asm__ __volatile__(
                 "movl %%esp,%%esi\n\t"
                 "int $0x80\n\t"         /* Linux/i386 system call */
                 "cmpl %%esp,%%esi\n\t"  /* child or parent? */
                 "je 1f\n\t"             /* parent - jump */
                 /* Load the argument into eax, and push it.  That way, it does
                  * not matter whether the called function is compiled with
                  * -mregparm or not.  */
                 "movl %4,%%eax\n\t"
                 "pushl %%eax\n\t"
                 "call *%5\n\t"          /* call fn */
                 "movl %3,%0\n\t"        /* exit */
                 "int $0x80\n"
                 "1:\t"
                 :"=&a" (retval), "=&S" (d0)
                 :"0" (__NR_clone), "i" (__NR_exit),
                  "r" (arg), "r" (fn),
                  "b" (flags | CLONE_VM)
                 : "memory");
         return retval;
 }

   Une fois appele, nous avons une nouvelle Tche (habituellement avec un
   nombre trs bas de PID, comme 2.3, etc...) attendant une ressource trs
   lente, comme un vnement change ou usb. Une ressource trs lente est
   utilise parce qu'autrement nous aurions une commutation de Tche coteuse
   (overhead).

   Au-dessous une liste de la plupart des fils du noyau courants (avec ''ps
   x''):

 PID      COMMAND
  1        init
  2        keventd
  3        kswapd
  4        kreclaimd
  5        bdflush
  6        kupdated
  7        kacpid
 67        khubd


   Le fil noyau ''init'' est le premier processus cr, au dmarrage. Il
   appellera toutes autres Tches Mode Utilisateur ( partir du fichier
   /etc/inittab) comme les dmons console, les dmons tty et les dmons
   rseau (''rc'' scripts).

  Exemple de fils noyau: kswapd [ mm/vmscan.c ].

   ''kswapd'' est cr par ''clone() [arch/i386/kernel/process.c]''

   Routines d'initialisation:

 |do_initcalls
    |kswapd_init
       |kernel_thread
          |syscall fork (in assembler)

   do_initcalls [init/main.c]

   kswapd_init [mm/vmscan.c]

   kernel_thread [arch/i386/kernel/process.c]

5.5 Modules Du Kernel

  Vue d'ensemble

   Les modules du noyau Linux sont des bouts de code (exemples: fs, net, et
   pilotes hw) fonctionnant en Mode Noyau que vous pouvez ajouter  chaud.

   Le coeur de Linux ne peut pas tre modularis: programmation et gestion
   d'interruption ou noyau du rseau, etc...

   Sous "/lib/modules/KERNEL_VERSION/" vous pouvez trouver tous les modules
   installs sur votre systme.

  Chargement et dchargement de module

   Pour charger un module, tapez ce qui suit:

 insmod MODULE_NAME parameters

 exemple: insmod ne io=0x300 irq=9

   NOTE: Vous pouvez utiliser modprobe  la place d'insmod si vous voulez que
   le noyau recherche automatiquement certains paramtres (par exemple en
   utilisant le pilote de PCI, ou si vous avez indiqu un paramtre dans le
   fichier /etc/conf.modules).

   Pour dcharger un module, tapez ce qui suit:

  rmmod MODULE_NAME

  Dfinition de module

   Un module contient toujours:

    1. fonction "init_module", excute  la commande d'insmod (ou modprobe)
    2. fonction "cleanup_module", excute  la commande de rmmod

   Si ces fonctions ne sont pas dans le module, vous devez ajouter 2 macros
   pour indiquer quelles fonctions agiront en tant qu'init et sortie du
   module:

    1. module_init(FUNCTION_NAME)
    2. module_exit(FUNCTION_NAME)

   NOTE: un module peut "voir" une variable du noyau seulement si elle a t
   exporte (avec la macro EXPORT_symbol).

  Un truc utile pour ajouter de la flexibilit  votre noyau

 // kernel sources side
 void (*foo_function_pointer)(void *);

 if (foo_function_pointer)
   (foo_function_pointer)(parameter);




 // module side
 extern void (*foo_function_pointer)(void *);

 void my_function(void *parameter) {
   //My code
 }

 int init_module() {
   foo_function_pointer = &my_function;
 }

 int cleanup_module() {
   foo_function_pointer = NULL;
 }

   Cette simple astuce vous permet d'avoir une flexibilit trs leve dans
   le noyau, parce que ne ferez excuter la routine "ma_fonction" que quand
   vous chargerez le module. Cette routine fera tout ce que vous voulez
   faire: par exemple le module ''rshaper'', qui commande le trafic d'entre
   de bande passante du rseau, fonctionne dans ce cas de figure.

   Notez que le mcanisme entier de module est possible grce  quelques
   variables globales exportes vers les modules, telles qu'une liste entte
   (vous permettant d'tendre la liste autant que vous voulez). Les exemples
   typiques sont fs, pilotes gnriques (caractre, bloc, rseau,
   tlphonie). Vous devez prparer le noyau  accepter votre nouveau module;
   dans certains cas vous devez crer une infrastructure (comme celle de la
   tlphonie, cre rcemment) pour tre aussi standard que possible.

5.6 Le dossier Proc

   Proc fs (systme de fichiers) est situ dans le dossier /proc, qui est un
   dossier spcial vous permettant de dialoguer directement avec le noyau.

   Linux utilise le dossier ''proc'' pour supporter les communications
   directes du noyau: c'est ncessaire dans plusieurs de cas, par exemple
   quand vous voulez voir les structures de donnes de processus principaux
   ou autoriser le dispositif ''proxy-arp'' pour une interface et pas pour
   d'autres, vous voulez changer le nombre maximum de fils, ou si vous voulez
   corriger certains tats de bus, comme ISA ou PCI, pour savoir quelles
   cartes sont installes et quelles adresses E/S et IRQs leur sont
   assignes.

 |-- bus
 |   |-- pci
 |   |   |-- 00
 |   |   |   |-- 00.0
 |   |   |   |-- 01.0
 |   |   |   |-- 07.0
 |   |   |   |-- 07.1
 |   |   |   |-- 07.2
 |   |   |   |-- 07.3
 |   |   |   |-- 07.4
 |   |   |   |-- 07.5
 |   |   |   |-- 09.0
 |   |   |   |-- 0a.0
 |   |   |   `-- 0f.0
 |   |   |-- 01
 |   |   |   `-- 00.0
 |   |   `-- devices
 |   `-- usb
 |-- cmdline
 |-- cpuinfo
 |-- devices
 |-- dma
 |-- dri
 |   `-- 0
 |       |-- bufs
 |       |-- clients
 |       |-- mem
 |       |-- name
 |       |-- queues
 |       |-- vm
 |       `-- vma
 |-- driver
 |-- execdomains
 |-- filesystems
 |-- fs
 |-- ide
 |   |-- drivers
 |   |-- hda -> ide0/hda
 |   |-- hdc -> ide1/hdc
 |   |-- ide0
 |   |   |-- channel
 |   |   |-- config
 |   |   |-- hda
 |   |   |   |-- cache
 |   |   |   |-- capacity
 |   |   |   |-- driver
 |   |   |   |-- geometry
 |   |   |   |-- identify
 |   |   |   |-- media
 |   |   |   |-- model
 |   |   |   |-- settings
 |   |   |   |-- smart_thresholds
 |   |   |   `-- smart_values
 |   |   |-- mate
 |   |   `-- model
 |   |-- ide1
 |   |   |-- channel
 |   |   |-- config
 |   |   |-- hdc
 |   |   |   |-- capacity
 |   |   |   |-- driver
 |   |   |   |-- identify
 |   |   |   |-- media
 |   |   |   |-- model
 |   |   |   `-- settings
 |   |   |-- mate
 |   |   `-- model
 |   `-- via
 |-- interrupts
 |-- iomem
 |-- ioports
 |-- irq
 |   |-- 0
 |   |-- 1
 |   |-- 10
 |   |-- 11
 |   |-- 12
 |   |-- 13
 |   |-- 14
 |   |-- 15
 |   |-- 2
 |   |-- 3
 |   |-- 4
 |   |-- 5
 |   |-- 6
 |   |-- 7
 |   |-- 8
 |   |-- 9
 |   `-- prof_cpu_mask
 |-- kcore
 |-- kmsg
 |-- ksyms
 |-- loadavg
 |-- locks
 |-- meminfo
 |-- misc
 |-- modules
 |-- mounts
 |-- mtrr
 |-- net
 |   |-- arp
 |   |-- dev
 |   |-- dev_mcast
 |   |-- ip_fwchains
 |   |-- ip_fwnames
 |   |-- ip_masquerade
 |   |-- netlink
 |   |-- netstat
 |   |-- packet
 |   |-- psched
 |   |-- raw
 |   |-- route
 |   |-- rt_acct
 |   |-- rt_cache
 |   |-- rt_cache_stat
 |   |-- snmp
 |   |-- sockstat
 |   |-- softnet_stat
 |   |-- tcp
 |   |-- udp
 |   |-- unix
 |   `-- wireless
 |-- partitions
 |-- pci
 |-- scsi
 |   |-- ide-scsi
 |   |   `-- 0
 |   `-- scsi
 |-- self -> 2069
 |-- slabinfo
 |-- stat
 |-- swaps
 |-- sys
 |   |-- abi
 |   |   |-- defhandler_coff
 |   |   |-- defhandler_elf
 |   |   |-- defhandler_lcall7
 |   |   |-- defhandler_libcso
 |   |   |-- fake_utsname
 |   |   `-- trace
 |   |-- debug
 |   |-- dev
 |   |   |-- cdrom
 |   |   |   |-- autoclose
 |   |   |   |-- autoeject
 |   |   |   |-- check_media
 |   |   |   |-- debug
 |   |   |   |-- info
 |   |   |   `-- lock
 |   |   `-- parport
 |   |       |-- default
 |   |       |   |-- spintime
 |   |       |   `-- timeslice
 |   |       `-- parport0
 |   |           |-- autoprobe
 |   |           |-- autoprobe0
 |   |           |-- autoprobe1
 |   |           |-- autoprobe2
 |   |           |-- autoprobe3
 |   |           |-- base-addr
 |   |           |-- devices
 |   |           |   |-- active
 |   |           |   `-- lp
 |   |           |       `-- timeslice
 |   |           |-- dma
 |   |           |-- irq
 |   |           |-- modes
 |   |           `-- spintime
 |   |-- fs
 |   |   |-- binfmt_misc
 |   |   |-- dentry-state
 |   |   |-- dir-notify-enable
 |   |   |-- dquot-nr
 |   |   |-- file-max
 |   |   |-- file-nr
 |   |   |-- inode-nr
 |   |   |-- inode-state
 |   |   |-- jbd-debug
 |   |   |-- lease-break-time
 |   |   |-- leases-enable
 |   |   |-- overflowgid
 |   |   `-- overflowuid
 |   |-- kernel
 |   |   |-- acct
 |   |   |-- cad_pid
 |   |   |-- cap-bound
 |   |   |-- core_uses_pid
 |   |   |-- ctrl-alt-del
 |   |   |-- domainname
 |   |   |-- hostname
 |   |   |-- modprobe
 |   |   |-- msgmax
 |   |   |-- msgmnb
 |   |   |-- msgmni
 |   |   |-- osrelease
 |   |   |-- ostype
 |   |   |-- overflowgid
 |   |   |-- overflowuid
 |   |   |-- panic
 |   |   |-- printk
 |   |   |-- random
 |   |   |   |-- boot_id
 |   |   |   |-- entropy_avail
 |   |   |   |-- poolsize
 |   |   |   |-- read_wakeup_threshold
 |   |   |   |-- uuid
 |   |   |   `-- write_wakeup_threshold
 |   |   |-- rtsig-max
 |   |   |-- rtsig-nr
 |   |   |-- sem
 |   |   |-- shmall
 |   |   |-- shmmax
 |   |   |-- shmmni
 |   |   |-- sysrq
 |   |   |-- tainted
 |   |   |-- threads-max
 |   |   `-- version
 |   |-- net
 |   |   |-- 802
 |   |   |-- core
 |   |   |   |-- hot_list_length
 |   |   |   |-- lo_cong
 |   |   |   |-- message_burst
 |   |   |   |-- message_cost
 |   |   |   |-- mod_cong
 |   |   |   |-- netdev_max_backlog
 |   |   |   |-- no_cong
 |   |   |   |-- no_cong_thresh
 |   |   |   |-- optmem_max
 |   |   |   |-- rmem_default
 |   |   |   |-- rmem_max
 |   |   |   |-- wmem_default
 |   |   |   `-- wmem_max
 |   |   |-- ethernet
 |   |   |-- ipv4
 |   |   |   |-- conf
 |   |   |   |   |-- all
 |   |   |   |   |   |-- accept_redirects
 |   |   |   |   |   |-- accept_source_route
 |   |   |   |   |   |-- arp_filter
 |   |   |   |   |   |-- bootp_relay
 |   |   |   |   |   |-- forwarding
 |   |   |   |   |   |-- log_martians
 |   |   |   |   |   |-- mc_forwarding
 |   |   |   |   |   |-- proxy_arp
 |   |   |   |   |   |-- rp_filter
 |   |   |   |   |   |-- secure_redirects
 |   |   |   |   |   |-- send_redirects
 |   |   |   |   |   |-- shared_media
 |   |   |   |   |   `-- tag
 |   |   |   |   |-- default
 |   |   |   |   |   |-- accept_redirects
 |   |   |   |   |   |-- accept_source_route
 |   |   |   |   |   |-- arp_filter
 |   |   |   |   |   |-- bootp_relay
 |   |   |   |   |   |-- forwarding
 |   |   |   |   |   |-- log_martians
 |   |   |   |   |   |-- mc_forwarding
 |   |   |   |   |   |-- proxy_arp
 |   |   |   |   |   |-- rp_filter
 |   |   |   |   |   |-- secure_redirects
 |   |   |   |   |   |-- send_redirects
 |   |   |   |   |   |-- shared_media
 |   |   |   |   |   `-- tag
 |   |   |   |   |-- eth0
 |   |   |   |   |   |-- accept_redirects
 |   |   |   |   |   |-- accept_source_route
 |   |   |   |   |   |-- arp_filter
 |   |   |   |   |   |-- bootp_relay
 |   |   |   |   |   |-- forwarding
 |   |   |   |   |   |-- log_martians
 |   |   |   |   |   |-- mc_forwarding
 |   |   |   |   |   |-- proxy_arp
 |   |   |   |   |   |-- rp_filter
 |   |   |   |   |   |-- secure_redirects
 |   |   |   |   |   |-- send_redirects
 |   |   |   |   |   |-- shared_media
 |   |   |   |   |   `-- tag
 |   |   |   |   |-- eth1
 |   |   |   |   |   |-- accept_redirects
 |   |   |   |   |   |-- accept_source_route
 |   |   |   |   |   |-- arp_filter
 |   |   |   |   |   |-- bootp_relay
 |   |   |   |   |   |-- forwarding
 |   |   |   |   |   |-- log_martians
 |   |   |   |   |   |-- mc_forwarding
 |   |   |   |   |   |-- proxy_arp
 |   |   |   |   |   |-- rp_filter
 |   |   |   |   |   |-- secure_redirects
 |   |   |   |   |   |-- send_redirects
 |   |   |   |   |   |-- shared_media
 |   |   |   |   |   `-- tag
 |   |   |   |   `-- lo
 |   |   |   |       |-- accept_redirects
 |   |   |   |       |-- accept_source_route
 |   |   |   |       |-- arp_filter
 |   |   |   |       |-- bootp_relay
 |   |   |   |       |-- forwarding
 |   |   |   |       |-- log_martians
 |   |   |   |       |-- mc_forwarding
 |   |   |   |       |-- proxy_arp
 |   |   |   |       |-- rp_filter
 |   |   |   |       |-- secure_redirects
 |   |   |   |       |-- send_redirects
 |   |   |   |       |-- shared_media
 |   |   |   |       `-- tag
 |   |   |   |-- icmp_echo_ignore_all
 |   |   |   |-- icmp_echo_ignore_broadcasts
 |   |   |   |-- icmp_ignore_bogus_error_responses
 |   |   |   |-- icmp_ratelimit
 |   |   |   |-- icmp_ratemask
 |   |   |   |-- inet_peer_gc_maxtime
 |   |   |   |-- inet_peer_gc_mintime
 |   |   |   |-- inet_peer_maxttl
 |   |   |   |-- inet_peer_minttl
 |   |   |   |-- inet_peer_threshold
 |   |   |   |-- ip_autoconfig
 |   |   |   |-- ip_conntrack_max
 |   |   |   |-- ip_default_ttl
 |   |   |   |-- ip_dynaddr
 |   |   |   |-- ip_forward
 |   |   |   |-- ip_local_port_range
 |   |   |   |-- ip_no_pmtu_disc
 |   |   |   |-- ip_nonlocal_bind
 |   |   |   |-- ipfrag_high_thresh
 |   |   |   |-- ipfrag_low_thresh
 |   |   |   |-- ipfrag_time
 |   |   |   |-- neigh
 |   |   |   |   |-- default
 |   |   |   |   |   |-- anycast_delay
 |   |   |   |   |   |-- app_solicit
 |   |   |   |   |   |-- base_reachable_time
 |   |   |   |   |   |-- delay_first_probe_time
 |   |   |   |   |   |-- gc_interval
 |   |   |   |   |   |-- gc_stale_time
 |   |   |   |   |   |-- gc_thresh1
 |   |   |   |   |   |-- gc_thresh2
 |   |   |   |   |   |-- gc_thresh3
 |   |   |   |   |   |-- locktime
 |   |   |   |   |   |-- mcast_solicit
 |   |   |   |   |   |-- proxy_delay
 |   |   |   |   |   |-- proxy_qlen
 |   |   |   |   |   |-- retrans_time
 |   |   |   |   |   |-- ucast_solicit
 |   |   |   |   |   `-- unres_qlen
 |   |   |   |   |-- eth0
 |   |   |   |   |   |-- anycast_delay
 |   |   |   |   |   |-- app_solicit
 |   |   |   |   |   |-- base_reachable_time
 |   |   |   |   |   |-- delay_first_probe_time
 |   |   |   |   |   |-- gc_stale_time
 |   |   |   |   |   |-- locktime
 |   |   |   |   |   |-- mcast_solicit
 |   |   |   |   |   |-- proxy_delay
 |   |   |   |   |   |-- proxy_qlen
 |   |   |   |   |   |-- retrans_time
 |   |   |   |   |   |-- ucast_solicit
 |   |   |   |   |   `-- unres_qlen
 |   |   |   |   |-- eth1
 |   |   |   |   |   |-- anycast_delay
 |   |   |   |   |   |-- app_solicit
 |   |   |   |   |   |-- base_reachable_time
 |   |   |   |   |   |-- delay_first_probe_time
 |   |   |   |   |   |-- gc_stale_time
 |   |   |   |   |   |-- locktime
 |   |   |   |   |   |-- mcast_solicit
 |   |   |   |   |   |-- proxy_delay
 |   |   |   |   |   |-- proxy_qlen
 |   |   |   |   |   |-- retrans_time
 |   |   |   |   |   |-- ucast_solicit
 |   |   |   |   |   `-- unres_qlen
 |   |   |   |   `-- lo
 |   |   |   |       |-- anycast_delay
 |   |   |   |       |-- app_solicit
 |   |   |   |       |-- base_reachable_time
 |   |   |   |       |-- delay_first_probe_time
 |   |   |   |       |-- gc_stale_time
 |   |   |   |       |-- locktime
 |   |   |   |       |-- mcast_solicit
 |   |   |   |       |-- proxy_delay
 |   |   |   |       |-- proxy_qlen
 |   |   |   |       |-- retrans_time
 |   |   |   |       |-- ucast_solicit
 |   |   |   |       `-- unres_qlen
 |   |   |   |-- route
 |   |   |   |   |-- error_burst
 |   |   |   |   |-- error_cost
 |   |   |   |   |-- flush
 |   |   |   |   |-- gc_elasticity
 |   |   |   |   |-- gc_interval
 |   |   |   |   |-- gc_min_interval
 |   |   |   |   |-- gc_thresh
 |   |   |   |   |-- gc_timeout
 |   |   |   |   |-- max_delay
 |   |   |   |   |-- max_size
 |   |   |   |   |-- min_adv_mss
 |   |   |   |   |-- min_delay
 |   |   |   |   |-- min_pmtu
 |   |   |   |   |-- mtu_expires
 |   |   |   |   |-- redirect_load
 |   |   |   |   |-- redirect_number
 |   |   |   |   `-- redirect_silence
 |   |   |   |-- tcp_abort_on_overflow
 |   |   |   |-- tcp_adv_win_scale
 |   |   |   |-- tcp_app_win
 |   |   |   |-- tcp_dsack
 |   |   |   |-- tcp_ecn
 |   |   |   |-- tcp_fack
 |   |   |   |-- tcp_fin_timeout
 |   |   |   |-- tcp_keepalive_intvl
 |   |   |   |-- tcp_keepalive_probes
 |   |   |   |-- tcp_keepalive_time
 |   |   |   |-- tcp_max_orphans
 |   |   |   |-- tcp_max_syn_backlog
 |   |   |   |-- tcp_max_tw_buckets
 |   |   |   |-- tcp_mem
 |   |   |   |-- tcp_orphan_retries
 |   |   |   |-- tcp_reordering
 |   |   |   |-- tcp_retrans_collapse
 |   |   |   |-- tcp_retries1
 |   |   |   |-- tcp_retries2
 |   |   |   |-- tcp_rfc1337
 |   |   |   |-- tcp_rmem
 |   |   |   |-- tcp_sack
 |   |   |   |-- tcp_stdurg
 |   |   |   |-- tcp_syn_retries
 |   |   |   |-- tcp_synack_retries
 |   |   |   |-- tcp_syncookies
 |   |   |   |-- tcp_timestamps
 |   |   |   |-- tcp_tw_recycle
 |   |   |   |-- tcp_window_scaling
 |   |   |   `-- tcp_wmem
 |   |   `-- unix
 |   |       `-- max_dgram_qlen
 |   |-- proc
 |   `-- vm
 |       |-- bdflush
 |       |-- kswapd
 |       |-- max-readahead
 |       |-- min-readahead
 |       |-- overcommit_memory
 |       |-- page-cluster
 |       `-- pagetable_cache
 |-- sysvipc
 |   |-- msg
 |   |-- sem
 |   `-- shm
 |-- tty
 |   |-- driver
 |   |   `-- serial
 |   |-- drivers
 |   |-- ldisc
 |   `-- ldiscs
 |-- uptime
 `-- version


   Dans ce dossier il y a aussi les Tches qui utilisent le PID comme nom de
   fichier (vous avez accs  toutes les informations sur les Tches, comme
   le chemin du fichier binaire, la mmoire utilise, etc...).

   Ce qui est intressant c'est que non seulement vous pouvez voir les
   valeurs du noyau (par exemple, voir l'information sur toute Tche ou sur
   les options actives du rseau de votre pile TCP/IP) mais vous pouvez aussi
   en modifier certaines, typiquement ceux qui sont dans le dossier
   /proc/sys:

 /proc/sys/
           acpi
           dev
           debug
           fs
           proc
           net
           vm
           kernel

  /proc/sys/kernel

   Suivent des valeurs du noyau trs importantes et bien connues, prtes 
   tre modifies:

 overflowgid
 overflowuid
 random
 threads-max // Nombre maximum de fils, typiquement 16384
 sysrq // hachage noyau: vous pouvez voir les valeurs du registre istant (istant) et plus
 sem
 msgmnb
 msgmni
 msgmax
 shmmni
 shmall
 shmmax
 rtsig-max
 rtsig-nr
 modprobe // emplacement fichier modprobe
 printk
 ctrl-alt-del
 cap-bound
 panic
 domainname // nom de domaine de votre poste Linux
 hostname // nom d'hte de votre poste Linux
 version // informations sur la date de compilation de votre noyau
 osrelease // version du noyau (i.e. 2.4.5)
 ostype // Linux!

  /proc/sys/net

   Il peut tre considr comme le sous-dossier le plus utile de proc. Il
   vous parmet de changer des paramtres trs importants de la configuration
   rseau de votre noyau.

 core
 ipv4
 ipv6
 unix
 ethernet
 802

  /proc/sys/net/core

   La liste suivante est la configuration gnrale du rseau, comme
   netdev_max_backlog" (typiquement 300), la longueur de tous les paquets
   rseau. Cette valeur peut limiter la bande passante du rseau quand il
   reoit des paquets. Linux doit attendre pour programmer le temps de vider
   les tampons (du aux mcanismes de la moiti d'en bas), envirn 1000/HZ ms
   (Listed below are general net settings, like "netdev_max_backlog"
   (typically 300), the length of all your network packets. This value can
   limit your network bandwidth when receiving packets, Linux has to wait up
   to scheduling time to flush buffers (due to bottom half mechanism), about
   1000/HZ ms)

   300    *        100             =     30 000
 packets     HZ(Timeslice freq)         packets/s

 30 000   *       1000             =      30 M
 packets     average (Bytes/packet)   throughput Bytes/s

   Si vous voulez un plus gros dbit, vous pouvez augmenter
   netdev_max_backlog,en tapant:

 echo 4000 > /proc/sys/net/core/netdev_max_backlog

   Note: Attention  certaines valeurs HZ: sous certaines architectures
   (comme alpha ou arm-tbox) c'est 1000, aussi vous pouvez avoir un dbit
   moyen de 300 Mo/s.

  /proc/sys/net/ipv4

   "ip_forward", active ou dsactive la rexpdition ou transmission ip (ip
   forwarding) dans votre poste Linux. C'est une configuration gnrique pour
   tous les priphriques, que vous pouvez spcifier pour chaque priphrique
   que vous choisissez.

  /proc/sys/net/ipv4/conf/interface

   Je pense que c'est l'entre de /proc la plus utile, parce qu'elle permet
   de modifier la configuration rseau pour supporter les rseaux sans fils
   (voir [10]Wireless-HOWTO pour plus d'informations, ou le guide pratique
   officiel Wireless-HOWTO).

   Quelques exemples o vous pouvez utiliser ces rglages:

     * "forwarding", pour activer la rexpdition ip pour votre interface
     * "proxy_arp", pour activer les lments arp interposs (proxy arp
       feature). Pour en savoir plus voir Proxy arp HOWTO sur [11]Linux
       Documentation Project et [12]Wireless-HOWTO ou le guide pratique
       officiel, pour les Proxy arp qui utilisent les rseaux sans fils.
     * "send_redirects" pour viter que l'interface envoie ICMP_REDIRECT
       (voir comme avant [13]Wireless-HOWTO ou le guide pratique officiel
       pour en savoir plus).

6. Traitement MultiTche Linux

6.1 Vue d'ensemble

   Cette section va analyser les structures de donnes -- le mcanisme
   utilis pour contrler l'environnement de traitement multitche sous
   Linux.

  tats de Tche

   Une Tche Linux peut avoir (can be) un des tats suivants (selon [
   include/linux.h ]):

    1. TASK_RUNNING, signifie qu'elle est dans "la liste prte" ("Ready
       List")
    2. TASK_INTERRUPTIBLE, Tche attendant un signal ou une ressource
       (sommeil)
    3. TASK_UNINTERRUPTIBLE, Tche attendant une ressource (sommeil), elle
       est dans la mme "file d'attente d'attente"
    4. TASK_ZOMBIE, enfant de Tche sans pre
    5. TASK_STOPPED, Tche  corriger (task being debugged)

  Interaction Graphique

        ______________     CPU Disponible    ______________
       |              |  ---------------->  |              |
       | TASK_RUNNING |                     | Real Running |
       |______________|  <----------------  |______________|
                            CPU Occupe
             |   /|\
   Attend     |    | Ressource
  Ressource   |    | Disponible
            \|/   |
     ______________________
    |                      |
    | TASK_INTERRUPTIBLE / |
    | TASK-UNINTERRUPTIBLE |
    |______________________|

                      Flot Multitche Principal

6.2 Timeslice (glissement de temps)

  Programmation PIT 8253

   Toutes les 10ms (selon la valeur de HZ) un IRQ0 se produit, qui nous aide
   en environnement multitche. Ce signal vient de PIC 8259 (en arch 386+)
   qui est reli  PIT 8253 avec une horloge de 1,19318 mgahertz.

     _____         ______        ______
    | CPU |<------| 8259 |------| 8253 |
    |_____| IRQ0  |______|      |___/|\|
                                     |_____ CLK 1.193.180 MHz

 // From include/asm/param.h
 #ifndef HZ
 #define HZ 100
 #endif

 // From include/asm/timex.h
 #define CLOCK_TICK_RATE 1193180 /* Underlying HZ */

 // From include/linux/timex.h
 #define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */

 // From arch/i386/kernel/i8259.c
 outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
 outb_p(LATCH & 0xff , 0x40); /* LSB */
 outb(LATCH >> 8 , 0x40); /* MSB */


   Ainsi nous programmons 8253 (PIT, Programmable Interval Timer ou Compteur
    intervalle programmable) avec LATCH (VERROU) = (1193180/hz) = 11931,8
   quand HZ=100 (dfaut). LATCH indique le facteur divisant la frquence.

   LATCH = 11931,8 donne  8253 (en sortie) une frquence de 1193180/11931,8
   = 100 Hz, ainsi la priode = 10ms

   Ainsi Timeslice = 1/hz.

   Avec chaque Timeslice nous interrompons temporairement l'excution du
   processus courant (sans commutation de Tche), et nous faisons du mnage,
   aprs quoi nous retournerons de nouveau  notre processus prcdent.

  Linux Timer (Compteur) IRQ ICA

 Linux Timer IRQ
 IRQ 0 [Timer]
  |
 \|/
 |IRQ0x00_interrupt        //   wrapper IRQ handler
    |SAVE_ALL              ---
       |do_IRQ                |   wrapper routines
          |handle_IRQ_event  ---
             |handler() -> timer_interrupt  // registered IRQ 0 handler
                |do_timer_interrupt
                   |do_timer
                      |jiffies++;
                      |update_process_times
                      |if (--counter <= 0) { // if time slice ended then
                         |counter = 0;        //   reset counter
                         |need_resched = 1;   //   prepare to reschedule
                      |}
          |do_softirq
          |while (need_resched) { // if necessary
             |schedule             //   reschedule
             |handle_softirq
          |}
    |RESTORE_ALL


   Des fonctions peuvent tre trouves sous:

     * IRQ0x00_interrupt, SAVE_ALL [include/asm/hw_irq.h]
     * do_IRQ, handle_IRQ_event [arch/i386/kernel/irq.c]
     * timer_interrupt, do_timer_interrupt [arch/i386/kernel/time.c]
     * do_timer, update_process_times [kernel/timer.c]
     * do_softirq [kernel/soft_irq.c]
     * RESTORE_ALL, while loop [arch/i386/kernel/entry.S]

   Notes:

    1. La fonction "IRQ0x00_interrupt" (comme d'autres IRQ0xXY_interrupt) est
       directement dirige par IDT (Interrupt Descriptor Table ou Tableau de
       descripteur d'interruption, semblable au Real Mode Interrupt Vector
       Table, voir chap 11), ainsi CHAQUE interruption arrivant au processeur
       est contrle par la routine "IRQ0x#NR_interrupt", o #NR est le
       numro d'interruption. Nous nous rfrons  elle en tant que
       "gestionnaire d'irq d'emballage" ("wrapper irq handler").
    2. des routines d'emballage sont excutes, comme
       "do_IRQ","handle_IRQ_event" [arch/i386/kernel/irq.c].
    3. Aprs ceci, la main est passe  la routine IRQ officielle (pointe
       par "handler()"), prcdemment enregistr avec "request_irq"
       [arch/i386/kernel/irq.c], dans ce cas "timer_interrupt"
       [arch/i386/kernel/time.c].
    4. la routine "timer_interrupt" [arch/i386/kernel/time.c] est excute,
       et quand elle se termine,
    5. le contrle revient  des routines assembleur
       [arch/i386/kernel/entry.S].

   Description:

   Pour grer le Multitche, Linux (comme chaque autre Unix) utilise un
   ''compteur'' variable pour suivre combien de CPU (processeur) a t
   utilise par la Tche. Ainsi,  chaque IRQ 0, le compteur est dcrment
   (point 4) et, quand il atteint 0, nous devons commuter la Tche de grer
   le temps partag (point 4 la variable "need_resched" est mise  1, puis,
   au point 5 les routines assembleur contrlent "need_resched" et appellent,
   si besoin, "le programme" [kernel/sched.c]).

6.3 Programmateur

   Le programmateur est le bout de code qui choisit quelle Tche doit tre
   excute  un moment donn (chooses what Task has to be executed at a
   given time).

   A chaque fois que vous devez changer la Tche courante, choisissez un
   candidat. Ci-dessous il y a la fonction ''programme [kernel/sched.c]''.

 |schedule
    |do_softirq // manages post-IRQ work
    |for each task
       |calculate counter
    |prepare_to__switch // does anything
    |switch_mm // change Memory context (change CR3 value)
    |switch_to (assembler)
       |SAVE ESP
       |RESTORE future_ESP
       |SAVE EIP
       |push future_EIP *** push parameter as we did a call
          |jmp __switch_to (it does some TSS work)
          |__switch_to()
           ..
          |ret *** ret from call using future_EIP in place of call address
       new_task


6.4 Moiti infrieure, files d'attente de Tche et Tasklets

  Vue d'ensemble

   En Unix classique, quand un IRQ se produit (par un priphrique), Unix
   fait la "commutation de Tche" pour interroger la Tche qui a demand le
   priphrique.

   Pour amliorer les performances, Linux peut remettre le travail non urgent
    plus tard, pour mieux grer la grande vitesse des vnements.

   Ce dispositif est gr depuis le noyau 1.x par "la moiti infrieure" (BH
   pour Bottom Half). Le gestionnaire d'irq "marque" une moiti infrieure,
   pour tre excut plus tard, le temps de programm (scheduling time).

   Dans les derniers noyaus il y a une "queue de tche" qui est plus
   dynamique que BH et il y a aussi une petite tche ("tasklet") pour grer
   les environnements multiprocesseur.

   Le schma BH est:

    1. Dclaration
    2. Marque
    3. Excution

  Dclaration

 #define DECLARE_TASK_QUEUE(q) LIST_HEAD(q)
 #define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)
 struct list_head {
    struct list_head *next, *prev;
 };
 #define LIST_HEAD_INIT(name) { &(name), &(name) }

       ''DECLARE_TASK_QUEUE'' [include/linux/tqueue.h, include/linux/list.h]

   La macro "DECLARE_TASK_QUEUE(q)" est utilise pour dclarer une structure
   appele file d'attente de tche qui gre "q" (managing task queue).

  Marque

   Voici le schma Ica pour la fonction "mark_bh"
   [include/linux/interrupt.h]:

 |mark_bh(NUMBER)
    |tasklet_hi_schedule(bh_task_vec + NUMBER)
       |insert into tasklet_hi_vec
          |__cpu_raise_softirq(HI_SOFTIRQ)
             |soft_active |= (1 << HI_SOFTIRQ)

                    ''mark_bh''[include/linux/interrupt.h]

   Par exemple, quand un gestionnaire d'IRQ veut "remettre" du travail, il
   ferait "mark_bh(NOMBRE)", o NOMBRE est un BH dclar (voir la section
   prcdente).

  Excution

   Nous pouvons voir ceci appel par la fonction "do_IRQ"
   [arch/i386/kernel/irq.c]:

 |do_softirq
    |h->action(h)-> softirq_vec[TASKLET_SOFTIRQ]->action -> tasklet_action
       |tasklet_vec[0].list->func



   "h->action(h);" est la fonction qui a t prcdemment aligne.

6.5 Routines de trs bas niveau

   set_intr_gate

   set_trap_gate

   set_task_gate (non utilis).

   (*interrupt)[NR_IRQS](void) = { IRQ0x00_interrupt, IRQ0x01_interrupt, ..}

   NR_IRQS = 224 [kernel 2.4.2]

6.6 Commutation de Tche

  Quand la commutation de Tche se passe-t-elle?

   Maintenant nous allons voir comment le noyau de Linux permute d'une Tche
    l'autre.

   La permutation de Tche est ncessaire dans beaucoup de cas, comme le
   suivant:

     * quand TimeSlice finit, nous devons donner accs  d'autres Tches
     * quand une Tche dcide d'accder  une ressource, elle dort en
       l'attendant, ainsi nous devons choisir une autre tche
     * quand une Tche attend une tube, nous devons donner accs  une autre
       Tche, qui crirait dans la tube

  Commutation de Tche

                            TASK SWITCHING TRICK
 #define switch_to(prev,next,last) do {                                  \
         asm volatile("pushl %%esi\n\t"                                  \
                      "pushl %%edi\n\t"                                  \
                      "pushl %%ebp\n\t"                                  \
                      "movl %%esp,%0\n\t"        /* save ESP */          \
                      "movl %3,%%esp\n\t"        /* restore ESP */       \
                      "movl $1f,%1\n\t"          /* save EIP */          \
                      "pushl %4\n\t"             /* restore EIP */       \
                      "jmp __switch_to\n"                                \
                      "1:\t"                                             \
                      "popl %%ebp\n\t"                                   \
                      "popl %%edi\n\t"                                   \
                      "popl %%esi\n\t"                                   \
                      :"=m" (prev->thread.esp),"=m" (prev->thread.eip),  \
                       "=b" (last)                                       \
                      :"m" (next->thread.esp),"m" (next->thread.eip),    \
                       "a" (prev), "d" (next),                           \
                       "b" (prev));                                      \
 } while (0)

   L'astuce c'est:

    1. ''pushl %4'' qui met future_EIP dans la pile
    2. ''jmp __switch_to'' qui excute la fonction''__switch_to'', mais au
       contraire de ''call'' nous reviendrons  la valeur suivante (to valued
       pushed in point 1) du poiint 1 (donc une nouvelle tche!)

       U S E R   M O D E                 K E R N E L     M O D E

  |          |     |          |       |          |     |          |
  |          |     |          | Timer |          |     |          |
  |          |     |  Normal  |  IRQ  |          |     |          |
  |          |     |   Exec   |------>|Timer_Int.|     |          |
  |          |     |     |    |       | ..       |     |          |
  |          |     |    \|/   |       |schedule()|     | Task1 Ret|
  |          |     |          |       |_switch_to|<--  |  Address |
  |__________|     |__________|       |          |  |  |          |
                                      |          |  |S |          |
 Task1 Data/Stack   Task1 Code        |          |  |w |          |
                                      |          | T|i |          |
                                      |          | a|t |          |
  |          |     |          |       |          | s|c |          |
  |          |     |          | Timer |          | k|h |          |
  |          |     |  Normal  |  IRQ  |          |  |i |          |
  |          |     |   Exec   |------>|Timer_Int.|  |n |          |
  |          |     |     |    |       | ..       |  |g |          |
  |          |     |    \|/   |       |schedule()|  |  | Task2 Ret|
  |          |     |          |       |_switch_to|<--  |  Address |
  |__________|     |__________|       |__________|     |__________|

 Task2 Data/Stack   Task2 Code        Kernel Code  Kernel Data/Stack

6.7 Fourche

  Vue d'ensemble

   La fourche est utilise pour crer une autre Tche. Nous commenons par
   une Tche Parent, et nous copions plusieurs structures de donnes vers
   l'Enfant de la Tche.


                                |         |
                                | ..      |
          Task Parent           |         |
          |         |           |         |
          |  fork   |---------->|  CREATE |
          |         |          /|   NEW   |
          |_________|         / |   TASK  |
                             /  |         |
              ---           /   |         |
              ---          /    | ..      |
                          /     |         |
          Task Child     /
          |         |   /
          |  fork   |<-/
          |         |
          |_________|

                        Fork SysCall

  Ce qui n'est pas copi

   La nouvelle Tche juste cre (''Enfant de Tche '') est presque gale au
   parent (''Parent de Tche''), il y a seulement quelques diffrences:

    1. videmment le PID
    2. l'enfant ''fork()'' renverra 0, alors que le parent ''fork()
       ''renverra le PID de la Tche Enfant, pour les distinguer en Mode
       Utilisateur
    3. Toutes les pages de donnes de l'enfant sont marques ''LECTURE +
       EXCUTION'', aucune "CRITURE'' (tandis que le parent a droit
       d'CRITURE sur ses propres pages) ainsi, quand une demande d'criture
       se produit, une exception de ''Faute de page'' est gnre qui crera
       une nouvelle page indpendante: ce mcanisme s'appelle ''Copy on
       Write'' (copie sur criture) (voir Chap.10).

  Fourche ICA

 |sys_fork
    |do_fork
       |alloc_task_struct
          |__get_free_pages
        |p->state = TASK_UNINTERRUPTIBLE
        |copy_flags
        |p->pid = get_pid
        |copy_files
        |copy_fs
        |copy_sighand
        |copy_mm // should manage CopyOnWrite (I part)
           |allocate_mm
           |mm_init
              |pgd_alloc -> get_pgd_fast
                 |get_pgd_slow
           |dup_mmap
              |copy_page_range
                 |ptep_set_wrprotect
                    |clear_bit // set page to read-only
           |copy_segments // For LDT
        |copy_thread
           |childregs->eax = 0
           |p->thread.esp = childregs // child fork returns 0
           |p->thread.eip = ret_from_fork // child starts from fork exit
        |retval = p->pid // parent fork returns child pid
        |SET_LINKS // insertion of task into the list pointers
        |nr_threads++ // Global variable
        |wake_up_process(p) // Now we can wake up just created child
        |return retval

                fork ICA


     * sys_fork [arch/i386/kernel/process.c]
     * do_fork [kernel/fork.c]
     * alloc_task_struct [include/asm/processor.c]
     * __get_free_pages [mm/page_alloc.c]
     * get_pid [kernel/fork.c]
     * copy_files
     * copy_fs
     * copy_sighand
     * copy_mm
     * allocate_mm
     * mm_init
     * pgd_alloc -> get_pgd_fast [include/asm/pgalloc.h]
     * get_pgd_slow
     * dup_mmap [kernel/fork.c]
     * copy_page_range [mm/memory.c]
     * ptep_set_wrprotect [include/asm/pgtable.h]
     * clear_bit [include/asm/bitops.h]
     * copy_segments [arch/i386/kernel/process.c]
     * copy_thread
     * SET_LINKS [include/linux/sched.h]
     * wake_up_process [kernel/sched.c]

  Copy on Write (Copie sur Ecriture)

   Pour implmenter la Copie sur Ecriture pour Linux:

    1. Marquez toutes les pages copies en lecture-seule, entranant une
       Faute de Page quand une Tche essaye d'y crire.
    2. Le gestionnaire de Faute de page cr une nouvelle page.


  | Page
  | Fault
  | Exception
  |
  |
  -----------> |do_page_fault
                  |handle_mm_fault
                     |handle_pte_fault
                        |do_wp_page
                           |alloc_page      // Alloue une nouvelle page
                           |break_cow
                              |copy_cow_page // Copie l'ancienne page vers une nouvelle
                              |establish_pte // reconfigure les pointeurs de la Table de Page
                                 |set_pte

               Page Fault ICA


     * do_page_fault [arch/i386/mm/fault.c]
     * handle_mm_fault [mm/memory.c]
     * handle_pte_fault
     * do_wp_page
     * alloc_page [include/linux/mm.h]
     * break_cow [mm/memory.c]
     * copy_cow_page
     * establish_pte
     * set_pte [include/asm/pgtable-3level.h]

7. Gestion de Mmoire de Linux

7.1 Vue d'ensemble

   Linux utilise segmentation + pagination, ce qui simplifie la notation.

  Segments

   Linux utilise seulement 4 segments:

     * 2 segments (code and data/stack ou code et donne/pile) pour l'ESPACE
       NOYAU de [0xC000 0000] (3 Go)  [0xFFFF FFFF] (4 Go)
     * 2 segments (code et donne/pile) pour l'ESPACE UTILISATEUR de [0] (0
       Go)  [0xBFFF FFFF] (3 Go)

                                __
    4 Go--->|                |    |
            |     Noyau      |    |  Espace Noyau (Code + Donne/Pile)
            |                |  __|
    3 Go--->|----------------|  __
            |                |    |
            |                |    |
    2 Go--->|                |    |
            |     Tche      |    |  Espace Utilisateur (Code + Donne/Pile)
            |                |    |
    1 Go--->|                |    |
            |                |    |
            |________________|  __|
  0x00000000
           Adresses Linaires Noyau/Utilisateur


7.2 Implmentation i386 spcifique

   A nouveau, Linux implmente la Pagination en utilisant 3 Niveaux de
   Pagination, mais dans l'architecture i386 seulement 2 d'entre elles sont
   vraiment utilises:


    ------------------------------------------------------------------
      A   D   R   E   S   S   E       L   I   N   E   A   I   R   E
    ------------------------------------------------------------------
         \___/                 \___/                     \_____/

      PD offset              PF offset                 Frame offset
      [10 bits]              [10 bits]                 [12 bits]
           |                     |                          |
           |                     |     -----------          |
           |                     |     |  Value  |----------|---------
           |     |         |     |     |---------|   /|\    |        |
           |     |         |     |     |         |    |     |        |
           |     |         |     |     |         |    | Frame offset |
           |     |         |     |     |         |   \|/             |
           |     |         |     |     |---------|<------            |
           |     |         |     |     |         |      |            |
           |     |         |     |     |         |      | x 4096     |
           |     |         |  PF offset|_________|-------            |
           |     |         |       /|\ |         |                   |
       PD offset |_________|-----   |  |         |          _________|
             /|\ |         |    |   |  |         |          |
              |  |         |    |  \|/ |         |         \|/
  _____       |  |         |    ------>|_________|   PHYSICAL ADDRESS
 |     |     \|/ |         |    x 4096 |         |
 | CR3 |-------->|         |           |         |
 |_____|         | ....... |           | ....... |
                 |         |           |         |

                Dossier Page           Fichier Page

                        Pagination Linux i386




7.3 Traage Mmoire

   Linux gre le Contrle d'Accs seulement avec des paginations, ainsi les
   diffrentes Tches auront les mmes adresses de segment, mais un CR3
   diffrent (registre utilis pour stocker l'Adresse de Page du Dossier),
   pointant vers une Page diffrente.

   En Mode Utilisateur une Tche ne peut pas dpasser la limite de 3 Go (0 x
   C0 00 00 00), ainsi seulement les 768 premires entres de rpertoire de
   page sont significative (768*4mb = 3Go).

   Quand une Tche passe en Mode Noyau (par Appel System ou par IRQ) d'autres
   entres de rpertoire de 256 pages deviennent importantes, et elles
   pointent vers les mmes fichiers de page que toutes autres Tches (qui
   sont les mme que le noyau).

   Notez que l'Espace Linaire du Noyau (et seulement du noyau) est gal 
   l'Espace Physique du Noyau, ainsi:


             ________________ _____
            |Other KernelData|___  |  |                |
            |----------------|   | |__|                |
            |     Kernel     |\  |____|   Real Other   |
   3 GB --->|----------------| \      |   Kernel Data  |
            |                |\ \     |                |
            |              __|_\_\____|__   Real       |
            |      Tasks     |  \ \   |     Tasks      |
            |              __|___\_\__|__   Space      |
            |                |    \ \ |                |
            |                |     \ \|----------------|
            |                |      \ |Real KernelSpace|
            |________________|       \|________________|

            Adresses Logiques          Adresses Physiques


   L'Espace Linaire du Noyau correspond  l'Espace Physique du Noyau
   transfr 3 Go plus bas (translated 3GB down) (en fait les tables de page
   sont quelque chose comme { "00000000", "00000001" }, ainsi elles
   n'effectuent aucune virtualisation, elles reportent seulement des adresses
   physiques qu'elles prennent des linaires).

   Notez que vous n'aurez pas un "conflit d'adresses" entre les espaces Noyau
   et Utilisateur parce que nous pouvons grer des adresses physiques avec
   les Tableaux de Page.

7.4 Attribution de mmoire de bas niveau

  Initialisation du Dmarrage

   Nous commenons  partir du kmem_cache_init (lanc par start_kernel [
   init/main.c ] au dmarrage).

 |kmem_cache_init
    |kmem_cache_estimate


   kmem_cache_init [mm/slab.c]

   kmem_cache_estimate

   Maintenant nous continuons avec mem_init (galement lanc par
   start_kernel[init/main.c ])

 |mem_init
    |free_all_bootmem
       |free_all_bootmem_core

   mem_init [arch/i386/mm/init.c]

   free_all_bootmem [mm/bootmem.c]

   free_all_bootmem_core

  Allocation du temps d'excution

   Sous Linux, quand nous voulons allouer de la mmoire, par exemple pendant
   le mcanisme "copy_on_write" (voir Chap.10), nous appelons:

 |copy_mm
    |allocate_mm = kmem_cache_alloc
       |__kmem_cache_alloc
          |kmem_cache_alloc_one
             |alloc_new_slab
                |kmem_cache_grow
                   |kmem_getpages
                      |__get_free_pages
                         |alloc_pages
                            |alloc_pages_pgdat
                               |__alloc_pages
                                  |rmqueue
                                  |reclaim_pages


   Les fonctions peuvent tre trouves ci-dessous:

     * copy_mm [kernel/fork.c]
     * allocate_mm [kernel/fork.c]
     * kmem_cache_alloc [mm/slab.c]
     * __kmem_cache_alloc
     * kmem_cache_alloc_one
     * alloc_new_slab
     * kmem_cache_grow
     * kmem_getpages
     * __get_free_pages [mm/page_alloc.c]
     * alloc_pages [mm/numa.c]
     * alloc_pages_pgdat
     * __alloc_pages [mm/page_alloc.c]
     * rm_queue
     * reclaim_pages [mm/vmscan.c]

   TODO: Comprendre les Zones

7.5 change (Swap ou glissement)

  Vue d'ensemble

   L'change est gr par le service kswapd (fil du noyau).

  kswapd

   Comme d'autres fils du noyau, le kswapd a une boucle principale qui attend
   de se rveiller.

 |kswapd
    |// initialization routines
    |for (;;) { // Main loop
       |do_try_to_free_pages
       |recalculate_vm_stats
       |refill_inactive_scan
       |run_task_queue
       |interruptible_sleep_on_timeout // on dort en attendant une nouvelle demande d'change
    |}

     * kswapd [mm/vmscan.c]
     * do_try_to_free_pages
     * recalculate_vm_stats [mm/swap.c]
     * refill_inactive_scan [mm/vmswap.c]
     * run_task_queue [kernel/softirq.c]
     * interruptible_sleep_on_timeout [kernel/sched.c]

  Quand avons-nous besoin d'changer?

   L'change est ncessaire quand nous devons accder  une page qui n'est
   pas en mmoire physique.

   Linux utilise le fil du noyau ''kswapd'' pour ce faire. Quand la Tche
   reoit une faute d'exception de page nous faisons ce qui suit:


  | Faute d'Execption de Page
  | cause par toutes ces conditions:
  |   a-) Page Utilisateur
  |   b-) Accs lecture ou criture
  |   c-) Page non prsente
  |
  |
  -----------> |do_page_fault
                  |handle_mm_fault
                     |pte_alloc
                        |pte_alloc_one
                           |__get_free_page = __get_free_pages
                              |alloc_pages
                                 |alloc_pages_pgdat
                                    |__alloc_pages
                                       |wakeup_kswapd // Nous rveillons le fil de noyau kswapd

                    Page Fault ICA


     * do_page_fault [arch/i386/mm/fault.c]
     * handle_mm_fault [mm/memory.c]
     * pte_alloc
     * pte_alloc_one [include/asm/pgalloc.h]
     * __get_free_page [include/linux/mm.h]
     * __get_free_pages [mm/page_alloc.c]
     * alloc_pages [mm/numa.c]
     * alloc_pages_pgdat
     * __alloc_pages
     * wakeup_kswapd [mm/vmscan.c]

8. Rseau Linux Linux Networking

8.1 Comment le rseau Linux est-il gr?

   Il existe un pilote de priphrique pour chaque type de NIC. De
   l'intrieur, Linux appellera TOUJOURS une routine standard de haut niveau:
   "netif_rx [net/core/dev.c]", qui contrlera  quel protocole de niveau 3
   le cadre appartient, et il appellera la bonne fonction de niveau 3 (ainsi
   nous utiliserons un pointeur vers la fonction pour dterminer laquelle est
   la bonne). (There exists a device driver for each kind of NIC. Inside it,
   Linux will ALWAYS call a standard high level routing: "netif_rx
   [net/core/dev.c]", which will controls what 3 level protocol the frame
   belong to, and it will call the right 3 level function (so we'll use a
   pointer to the function to determine which is right).

8.2 Exemple TCP

   Nous allons voir maintenant un exemple de ce qui se produit quand nous
   envoyons un paquet TCP  Linux,  partir de l'appel ''netif_rx
   [net/core/dev.c] ''.

  Gestion d'interruption: "netif_rx"

 |netif_rx
    |__skb_queue_tail
       |qlen++
       |* simple pointer insertion *
    |cpu_raise_softirq
       |softirq_active(cpu) |= (1 << NET_RX_SOFTIRQ) // met l'octet NET_RX_SOFTIRQ dans le vecteur BH


   Fonctions:

     * __skb_queue_tail [include/linux/skbuff.h]
     * cpu_raise_softirq [kernel/softirq.c]

  Gestion de Post Interruption: "net_rx_action"

   Une fois que l'interaction d'IRQ est finie, nous devons suivre la
   prochaine partie de la vie du cadre et examiner ce que fait
   NET_RX_SOFTIRQ.

   Nous appellerons ensuite ''net_rx_action [net/core/dev.c]'' selon
   "net_dev_init [net/core/dev.c]".

 |net_rx_action
    |skb = __skb_dequeue (the exact opposite of __skb_queue_tail)
    |for (ptype = first_protocol; ptype < max_protocol; ptype++) // Determine
       |if (skb->protocol == ptype)                               // what is the network protocol
          |ptype->func -> ip_rcv // according to ''struct ip_packet_type [net/ipv4/ip_output.c]''

     **** MAINTENANT NOUS SAVONS QUEL PAQUET EST IP ****
          |ip_rcv
             |NF_HOOK (ip_rcv_finish)
                |ip_route_input // cherche dans la table de routage pour dterminer la fonction  appeler
                   |skb->dst->input -> ip_local_deliver // selon la prcdente vrification de la table de routage, la destination est la machine locale
                      |ip_defrag // rassemble les fragments IP
                         |NF_HOOK (ip_local_deliver_finish)
                            |ipprot->handler -> tcp_v4_rcv // selon ''tcp_protocol [include/net/protocol.c]''

      **** MAINTENANT NOUS SAVONS QUEL PAQUET EST TCP ****
                            |tcp_v4_rcv
                               |sk = __tcp_v4_lookup
                               |tcp_v4_do_rcv
                                  |switch(sk->state)

      *** Le paquet peut tre envoy  la tche qui utilise une connexion (socket) relative ***
                                  |case TCP_ESTABLISHED:
                                     |tcp_rcv_established
                                        |__skb_queue_tail // enfile le packet vers la connexion
                                        |sk->data_ready -> sock_def_readable
                                           |wake_up_interruptible


      *** Le packet est toujours pris en main par le 3-way TCP handshake ***
                                  |case TCP_LISTEN:
                                     |tcp_v4_hnd_req
                                        |tcp_v4_search_req
                                        |tcp_check_req
                                           |syn_recv_sock -> tcp_v4_syn_recv_sock
                                        |__tcp_v4_lookup_established
                                  |tcp_rcv_state_process

                     *** 3-Way TCP Handshake ***
                                     |switch(sk->state)
                                     |case TCP_LISTEN: // We received SYN
                                        |conn_request -> tcp_v4_conn_request
                                           |tcp_v4_send_synack // Send SYN + ACK
                                              |tcp_v4_synq_add // set SYN state
                                     |case TCP_SYN_SENT: // we received SYN + ACK
                                        |tcp_rcv_synsent_state_process
                                           tcp_set_state(TCP_ESTABLISHED)
                                              |tcp_send_ack
                                                 |tcp_transmit_skb
                                                    |queue_xmit -> ip_queue_xmit
                                                       |ip_queue_xmit2
                                                          |skb->dst->output
                                     |case TCP_SYN_RECV: // We received ACK
                                        |if (ACK)
                                           |tcp_set_state(TCP_ESTABLISHED)


   Fonctions ci-dessous:

     * net_rx_action [net/core/dev.c]
     * __skb_dequeue [include/linux/skbuff.h]
     * ip_rcv [net/ipv4/ip_input.c]
     * NF_HOOK -> nf_hook_slow [net/core/netfilter.c]
     * ip_rcv_finish [net/ipv4/ip_input.c]
     * ip_route_input [net/ipv4/route.c]
     * ip_local_deliver [net/ipv4/ip_input.c]
     * ip_defrag [net/ipv4/ip_fragment.c]
     * ip_local_deliver_finish [net/ipv4/ip_input.c]
     * tcp_v4_rcv [net/ipv4/tcp_ipv4.c]
     * __tcp_v4_lookup
     * tcp_v4_do_rcv
     * tcp_rcv_established [net/ipv4/tcp_input.c]
     * __skb_queue_tail [include/linux/skbuff.h]
     * sock_def_readable [net/core/sock.c]
     * wake_up_interruptible [include/linux/sched.h]
     * tcp_v4_hnd_req [net/ipv4/tcp_ipv4.c]
     * tcp_v4_search_req
     * tcp_check_req
     * tcp_v4_syn_recv_sock
     * __tcp_v4_lookup_established
     * tcp_rcv_state_process [net/ipv4/tcp_input.c]
     * tcp_v4_conn_request [net/ipv4/tcp_ipv4.c]
     * tcp_v4_send_synack
     * tcp_v4_synq_add
     * tcp_rcv_synsent_state_process [net/ipv4/tcp_input.c]
     * tcp_set_state [include/net/tcp.h]
     * tcp_send_ack [net/ipv4/tcp_output.c]

   Description:

     * D'abord nous dterminons le type de protocole (IP, puis TCP)
     * NF_hook (fonction) est une routine d'emballage (wrapper) qui gre
       d'abord le filtre rseau (par exemple mur de feu), puis lui appelle la
       ''fonction''.
     * Aprs que nous contrlions 3-way TCP Handshake qui se compose de:

 SERVEUR (ECOUTE)                          CLIENT (CONNECTING)
                            SYN
                    <-------------------


                         SYN + ACK
                    ------------------->


                            ACK
                    <-------------------

                     3-Way TCP handshake


     *  la fin que nous devons seulement lancer "tcp_rcv_established
       [net/ipv4/tcp_input.c]" qui donne le paquet  la connexion utilisateur
       et le rveille.

9. Systme de fichier Linux

   TODO

10. Trucs utiles

10.1 Pile et tas (Stack and Heap)

  Vue d'ensemble

   Ici nous regardons comment la "pile" et le "tas" sont allous en mmoire

  Allocation mmoire


 FF..        |                 | <-- bas de la pile
        /|\  |                 |   |
  valeurs|   |                 |   |   pile
  leves|   |                 |  \|/  grandit
             |                 |
 XX..        |                 | <-- haut de la pile [Pointeur de pile]
             |                 |
             |                 |
             |                 |
 00..        |_________________| <-- fin de pile [Segment de pile]

                    Pile


   Les valeurs d'adresse de mmoire commencent  00. (qui est aussi l o le
   Segment de Pile commence) et ils vont jusqu' la valeur FF..

   XX.. est la valeur relle du pointeur de pile.

   La pile est utilise par les fonctions pour:

    1. les variables globales
    2. les variables locales
    3. l'adresse de retour

   Par exemple, pour une fonction classique:


  |int foo_function (parameter_1, parameter_2, ..., parameter_n) {
     |variable_1 declaration;
     |variable_2 declaration;
       ..
     |variable_n declaration;

     |// Body function
     |dynamic variable_1 declaration;
     |dynamic variable_2 declaration;
      ..
     |dynamic variable_n declaration;

     |// Le code est  l'intrieur du Segment Code, pas le segment Donne/Pile!

     |return (ret-type) value; // souvent c'est  l'intrieur d'un registre, pour l'i386 le registre eax est utilis.
  |}
 nous avons

           |                       |
           | 1. parameter_1 pushed | \
     P     | 2. parameter_2 pushed |  | Avant
     I     | ...................   |  | l'appel
     L     | n. parameter_n pushed | /
     E     | ** Return address **  | -- Appel
           | 1. local variable_1   | \
           | 2. local variable_2   |  | Aprs
           | .................     |  | l'appel
           | n. local variable_n   | /
           |                       |
          ...                     ...   Pile
          ...                     ...   libre
           |                       |
     T     | n. dynamic variable_n | \
     A     | ...................   |  | Allou par
     S     | 2. dynamic variable_2 |  | malloc & kmalloc
           | 1. dynamic variable_1 | /
           |_______________________|

            Usage typique de la pile

 Note: l'ordre des variables peut tre diffrent selon l'architecture du matriel.

10.2 Application vs Processus

  Dfinition basse

   Nous devons distinguer 2 concepts:

     * Application: c'est le code utile que nous voulons excuter
     * Processus: c'est l'IMAGE en mmoire de l'application (elle dpend de
       la stratgie mmoire utilise, de la segmentation et/ou de la
       Pagination).

   Souvent le Processus s'appelle galement Tche ou Fil.

10.3 Bloquages (Locks)

  Vue d'ensemble

   2 genre de serrures:

    1. intraCPU
    2. interCPU

10.4 Copy_on_write

   Copy_on_write est un mcanisme utilis pour rduire l'utilisation de
   mmoire. Il remet l'allocation mmoire  plus tard de mmoire jusqu' ce
   que la mmoire soit vraiment ncessaire.

   Par exemple, quand une Tche excute l'Appel Systme "fork()" (pour crer
   une autre Tche), nous utilisons toujours les mmes pages de mmoire que
   le parent, en mode lecture seule. Quand une Tche CRIT dans la page, elle
   cause une exception et la page est copie et marque "rw" (lecture,
   criture).


 1-) la page X est partage entre la Tche parent et la Tche enfant
  Tche Parent
  |         | Accs RO   ______
  |         |---------->|Page X|
  |_________|           |______|
                           /|\
                            |
  Tche Enfant              |
  |         | Accs RO      |
  |         |----------------
  |_________|


 2-) Write request
  Task Parent
  |         | Accs RO   ______
  |         |---------->|Page X|    Trying to write
  |_________|           |______|
                           /|\
                            |
  Task Child                |
  |         | Accs RO      |
  |         |----------------
  |_________|


 3-) Final Configuration: Either Task Parent and Task Child have an independent copy of the Page, X and Y
  Task Parent
  |         | Accs RW   ______
  |         |---------->|Page X|
  |_________|           |______|


  Task Child
  |         | Accs RW   ______
  |         |---------->|Page Y|
  |_________|           |______|

11. Dtails spcifiques 80386

11.1 Procdure de dmarrage

 bbootsect.s [arch/i386/boot]
 setup.S (+video.S)
 head.S (+misc.c) [arch/i386/boot/compressed]
 start_kernel [init/main.c]

11.2 Descripteurs 80386 (et plus)

  Vue d'ensemble

   Les descripteurs sont des structure de donnes utilises par le
   microprocesseur Intel i386+ pour rendre la mmoire virtuelle.

  Types de descripteurs

     * GDT (Table Globale de Descripteur)
     * LDT (Table Locale de Descripteur)
     * IDT (Table de Descripteur d'Interruption)

12. IRQ

12.1 Vue d'ensemble

   IRQ est un signal asyncrone envoy au microprocesseur pour annoncer qu'une
   requte est complte

12.2 Schma d'interaction

                                  |<-->  IRQ(0) [Timer]
                                  |<-->  IRQ(1) [Device 1]
                                  | ..
                                  |<-->  IRQ(n) [Device n]
     _____________________________|
      /|\      /|\          /|\
       |        |            |
      \|/      \|/          \|/

     Tche(1)  Tche(2) ..   Tche(N)


              IRQ - Schma d'Interaction de Tches



  Que se produit?

   Un SE typique utilise beaucoup de signaux IRQ pour interrompre l'excution
   normale de processus et fait le mnage. Ainsi:

    1. IRQ (i) se produit et Tche(j) est interrompue
    2. IRQ(i)_handler est excut
    3. le contrle revient  la Tche(j) interrompue

   Sous Linux, quand un IRQ survient, d'abord la routine d'emballage IRQ
   (appele "interrupt0x??") est appelle, puis l'IRQ(i)_handler "officiel"
   est excut. Ceci permet certains droits comme la premption de timeslice.

13. Fonctions utilitaires

13.1 list_entry [include/linux/list.h]

   Definition:

 #define list_entry(ptr, type, member) \
 ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

   Signification:

   La macro "list_entry" est utilise pour retrouver un pointeur de struct
   parent, en utilisant seulement un pointeur de struct interne.

   Exemple:

 struct __wait_queue {
    unsigned int flags;
    struct task_struct * task;
    struct list_head task_list;
 };
 struct list_head {
    struct list_head *next, *prev;
 };

 // et avec la dfinition type:
 typedef struct __wait_queue wait_queue_t;

 // nous aurons
 wait_queue_t *out list_entry(tmp, wait_queue_t, task_list);

 // o tmp pointe vers list_head

   Ainsi, dans ce cas, au moyen du pointeur *tmp [list_head] nous retrouvons
   le pointeur *out [wait_queue_t].


  ____________ <---- *out [nous calculons que]
 |flags       |             /|\
 |task *-->   |              |
 |task_list   |<----    list_entry
 |  prev * -->|    |         |
 |  next * -->|    |         |
 |____________|    ----- *tmp [nous avons a]


13.2 Sommeil

  Code de sommeil

   Fichiers:

     * kernel/sched.c
     * include/linux/sched.h
     * include/linux/wait.h
     * include/linux/list.h

   Fonctions:

     * interruptible_sleep_on
     * interruptible_sleep_on_timeout
     * sleep_on
     * sleep_on_timeout

   Fonctions appeles:

     * init_waitqueue_entry
     * __add_wait_queue
     * list_add
     * __list_add
     * __remove_wait_queue

   Analyse D'InterCallings:

 |sleep_on
    |init_waitqueue_entry  --
    |__add_wait_queue        |   enqueuing request to resource list
       |list_add              |
          |__list_add        --
    |schedule              ---     waiting for request to be executed
       |__remove_wait_queue --
       |list_del              |   dequeuing request from resource list
          |__list_del        --



   Description:

   Sous Linux chaque ressource (idalement un objet partag par plusieurs
   utilisateurs et plusieurs processus), a une file pour grer TOUTES les
   Tches qui la demandant.

   Cette file s'appelle l"file d'attente" et elle consiste en plusieurs
   lments que nous appellerons l"lment de file d'attente":

 ***   structure de file d'attente [include/linux/wait.h]  ***


 struct __wait_queue {
    unsigned int flags;
    struct task_struct * task;
    struct list_head task_list;
 }
 struct list_head {
    struct list_head *next, *prev;
 };

   Fonctionnement de graphique:

         ***  lment de file d'attente  ***

                              /|\
                               |
        <--[prc *, drapeau, tchesk *, suiv *]-->




                  ***  liste de file d'attente ***

           /|\           /|\           /|\                /|\
            |             |             |                  |
 --> <--[tch1]--> <--[tch2]--> <--[tche3]--> .... <--[tcheN]--> <--
 |                                                                  |
 |__________________________________________________________________|



               ***   tte de file d'attente ***

        tche1 <--[prc *, blocage, suiv *]--> tcheN



   "tte de file d'attente d'attente" pointe vers premier (avec suiv *) et
   dernier (avec prc *) lments de la "liste de file d'attente".

   Quand un nouvel lment doit tre ajout, "__add_wait_queue"
   [include/linux/wait.h] est appell, aprs quoi la routine gnrique
   "list_add" [include/linux/wait.h], est excute:

 ***   function list_add [include/linux/list.h]  ***

 // classic double link list insert
 static __inline__ void __list_add (struct list_head * new,  \
                                    struct list_head * prev, \
                                    struct list_head * next) {
    next->prev = new;
    new->next = next;
    new->prev = prev;
    prev->next = new;
 }

   Pour complter la description, nous voyons aussi la fonction "__list_del"
   [include/linux/list.h] appele par "list_del" [include/linux/list.h] dans
   "remove_wait_queue" [include/linux/wait.h]:

 ***   fonction list_del [include/linux/list.h]  ***


 // classic double link list delete
 static __inline__ void __list_del (struct list_head * prev, struct list_head * next) {
    next->prev = prev;
    prev->next = next;
 }

  Consideration sur la pile

   Une liste type (ou la file) est habituellement gre en l'allouant dans le
   Tas (voir le Chap.10 pour la dfinition de Tas et Pile au sujet et voir o
   les variables sont assignes). Autrement ici, nous allouons statiquement
   les donnes File d'Attente dans une variable locale (Pile), puis la
   fonction est interrompue par le programme,  la fin, (retournant du
   programme (returning from scheduling)) effacera la variable locale.

   new task <----|          task1 <------|          task2 <------|
                 |                       |                       |
                 |                       |                       |
 |..........|    |       |..........|    |       |..........|    |
 |wait.flags|    |       |wait.flags|    |       |wait.flags|    |
 |wait.task_|____|       |wait.task_|____|       |wait.task_|____|
 |wait.prev |-->         |wait.prev |-->         |wait.prev |-->
 |wait.next |-->         |wait.next |-->         |wait.next |-->
 |..        |            |..        |            |..        |
 |schedule()|            |schedule()|            |schedule()|
 |..........|            |..........|            |..........|
 |__________|            |__________|            |__________|

    Stack                   Stack                   Stack

14. Variables statiques

14.1 Vue d'ensemble

   Linux est crit en ''langue C'', et toutes les applications ont:

    1. Des variables locales
    2. Des modules variables (dans le fichier source et relatif seulement 
       ce module)
    3. Des variables Globales/Statiques prsentent dans seulement 1 copie (la
       mme pour tous les modules)

   Quand une variable statique est modifie par un module, tous autres
   modules voient la nouvelle valeur.

   Les variables statiques sous Linux sont trs importantes, parce qu'elles
   sont la seule faon d'ajouter un nouveau support au noyau: elles sont
   typiquement des pointeurs en tte d'une liste d'lments enregistrs, qui
   peuvent tre:

     * ajout
     * supprim
     * peut-tre modifi

                            _______      _______      _______
 Variable globale  -------> |Item(1)| -> |Item(2)| -> |Item(3)|  ..
                           |_______|    |_______|    |_______|

14.2 Variables principales

  Current (Courant)

                            ________________
 Current ----------------> | Actual process |
                           |________________|

   Current pointe vers la structure ''task_struct'' , qui contient toutes les
   donnes sur un processus:

     * pid, name, state, counter, policy of scheduling (pid, nom, tat,
       compteur, politique de programmation)
     * les pointeurs vers plusieurs structures de donnes comme: fichiers,
       vfs, autres processus, signaux...

   Current n'est pas une vraie variable, c'est

 static inline struct task_struct * get_current(void) {
    struct task_struct *current;
    __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL));
    return current;
 }
 #define current get_current()

   Les lignes au-dessus prennent juste la valeur du registre ''esp''
   (pointeur de pile) et le rendent disponible comme une variable, de
   laquelle nous pouvons pointer vers la structure task_struct.

   De l'lment ''curent'' nous pouvons accder directement  n'importe quel
   autre processus (prt, arrt ou dans tout autre tat) de la structure de
   donnes noyau, par exemple en changeant l'ETAT (comme un pilote E/S le
   ferait), le PID, la prsence dans la liste prt ou la liste bloqu, etc...

  Systmes de fichiers enregistrs

                        ______      _______      ______
 file_systems  ------> | ext2 | -> | msdos | -> | ntfs |
  [fs/super.c]         |______|    |_______|    |______|

   Quand vous utilisez une commande comme ''modprobe un_fs'' vous ajoutez une
   nouvelle entre  la liste des systmes de fichiers, ds que vous
   l'enlevez (avec ''rmmod'') il est supprim.

  Systmes de fichiers monts

                         ______      _______      ______
 mount_hash_table  ---->|   /  | -> | /usr  | -> | /var |
 [fs/namespace.c]       |______|    |_______|    |______|

   Quand vous utilisez la commande ''mount'' pour ajouter un fs, la nouvelle
   entre est insre dans la liste, jusqu' ce que la commande ''umount''
   supprime l'entre.

  Type de Paquet Rseau Enregistr

                         ______      _______      ______
      ptype_all  ------>|  ip  | -> |  x25  | -> | ipv6 |
 [net/core/dev.c]       |______|    |_______|    |______|

   Par exemple, si vous ajoutez le support IPv6 (en chargeant le module
   relatif) une nouvelle entre est ajoute  la liste.

  Protocole de Rseau Internet Enregistr

                           ______      _______      _______
 inet_protocol_base ----->| icmp | -> |  tcp  | -> |  udp  |
 [net/ipv4/protocol.c]    |______|    |_______|    |_______|

   Aussi d'autres types de paquet ont plusieurs protocoles internes dans
   chaque liste (comme IPv6).

                           ______      _______      _______
 inet6_protos ----------->|icmpv6| -> | tcpv6 | -> | udpv6 |
 [net/ipv6/protocol.c]    |______|    |_______|    |_______|

  Priphrique Rseau Enregistr

                           ______      _______      _______
 dev_base --------------->|  lo  | -> |  eth0 | -> |  ppp0 |
 [drivers/core/Space.c]   |______|    |_______|    |_______|

  Priphrique Caractre (Char) Enregistr

                           ______      _______      ________
 chrdevs ---------------->|  lp  | -> | keyb  | -> | serial |
 [fs/devices.c]           |______|    |_______|    |________|

   ''chrdevs'' n'est pas un pointeur vers une vraie liste, mais c'est un
   vecteur standard.

  Priphrique Bloc Enregistr

                           ______      ______      ________
 bdev_hashtable --------->|  fd  | -> |  hd  | -> |  scsi  |
 [fs/block_dev.c]         |______|    |______|    |________|

   ''bdev_hashtable'' est un vecteur de hachage.

15. Glossaire

16. Liens

   [14]Site de tlchargemet du Noyau Linux Officiel et de patches

   [15]Grosse documentation sur le Noyau Linux

   [16]Liste de diffusion Officielle du Noyau

   [17]Guides du Project de Documentation Linux

References

   Visible links
   1. http://www.bertolinux.com/
   2. mailto:berto%20chez%20bertolinux%20point%20com
   3. http://www.traduc.org/
   4. http://www.traduc.org/
   5. http://www.bertolinux.com/
   6. mailto:berto%20chez%20bertolinux%20point%20com
   7. http://www.gnu.org/copyleft/gpl.html
   8. http://www.lyx.org/
   9. http://www.tldp.org/
  10. http://www.bertolinux.com/
  11. http://www.tldp.org/
  12. http://www.bertolinux.com/
  13. http://www.bertolinux.com/
  14. http://www.kernel.org/
  15. http://jungla.dit.upm.es/~jmseyas/linux/kernel/hackers-docs.html
  16. http://www.uwsg.indiana.edu/hypermail/linux/kernel/index.html
  17. http://www.tldp.org/guides.html
