Euh...
"Le noyau BSD a une architecture robuste" ca ne veut pas dire grand chose concretement.
En pratique, programmer des trucs sur le noyau Linux est beaucoup plus agreable que sur un noyau BSD. Sous Linux, il y a des couches d'abstraction pour tout, qui sont bien compartimentees et bien documentees. Il y a d'office plein de fonctions a disposition pour gerer les structures de donnees courantes, implementer un cache, effectuer des operations asynchrones, placer des verrous sans risque de deadlock, etc. Toutes ces fonctions sont reentrantes, prevues pour fonctionner en SMP, elles peuvent etre utilisees dans des gestionnaire d'interruption sans precaution particuliere, etc. Pareil, quand on a besoin de memoire, il y a une batterie de fonction generiques pour repondre a tous les besoins. Au niveau debogguage, quand un thread du noyau plante, c'est sans consequence. Quand un spinlock s'eternise, il peut finir par etre automatiquement deverouille. Quand on essaye d'acceder a une page deja liberee, le noyau peut continuer a fonctionner quand meme.
Sous BSD (du moins Open/Micro), c'est plus limite. Les fondations sont reduites au strict minimum. Pour les allocations de memoire courantes, le seul truc a disposition c'est les fonctions pool* qui sont pourries pour les trucs dynamiques. La couche d'abstraction des systemes de fichiers est tres basique et oblige a reinventer la roue a chaque fois pour les locks. Si l'on veut faire un truc un peu particulier (comme de ne pas passer par le cache, comme O_DIRECT sous Linux), c'est un travail de cingle, il faut completement revoir les vfsops. Ca ne facilite pas du tout l'integration d'un systeme journalise par exemple. Et quand il y a un truc incoherent dans un test, il est difficile de dire au noyau d'essayer de continuer son boulot, la seule fonction que l'on peut appeler c'est panic() qui cause un kernel panic. Une merde dans un driver, ca fait tout planter, c'est chiant pour debugguer.
Un autre truc super gonflant dans les noyaux BSD : le manque de typage. Dans Linux il y a un type pour chaque truc. C'est un peu gonflant au debut et on s'y paume rapidement, mais d'une part ca permet d'etendre les trucs facilement, d'autre part ca permet d'eviter des erreurs betes. Dans un noyau BSD, pour n'importe quoi, on utilise un peu arbitrairement toujours les memes types : int, u_int et u_int32_t. Quand on melange deux variables sans rapport sans faire gaffe, le compilateur est incapable de nous prevenir. Et quand on se plante sur le type (on a pris un type non signe alors que l'utilisateur peut passer des trucs signe), c'est tres chiant a corriger, il faut vraiment faire gaffe a changer les bons int en u_int et pas les autres. Il y a eu pas mal de failles de secu sur les BSD a cause de ca (dans le filesystem sous FreeBSD, dans des appels comme itimer sous OpenBSD, etc) .
Autant les couches d'abstraction et les types dans tous les sens sous Linux sont reloues au debut (et en plus ca change sans arret, il faut suivre...), autant ca permet d'eviter du bricolage intempestif comme sous BSD. Deplacer ou recopier une partie d'un filesystem (mount --bind, mount --move) sous Linux, ca prend trois lignes (et ca fonctionne en smp) car la vfs est suffisemment generique pour ca. Sous BSD il faut reimplementer un nouveau filesystem virtuel qui va lui-meme lire les donnees d'un autre filesystem deja present, tout en trafiquant pour qu'il ne soit jamais possible d'ecrire dans les deux au meme moment. C'est du bricolage, et d'ailleurs ca ne fonctionne toujours pas correctement.
Bon, tout ca c'est bien gentil, mais c'est du blabla. Dans les faits, et malgre une architecture beaucoup plus propre dans Linux que dans les noyaux BSD, il n'y a pas tellement de difference. Sous Linux, c'est simple de changer completement une partie importante comme le gestionnaire de memoire virtuelle, le scheduler, etc. sans toucher au reste. Du coup, bein... ca n'arrete pas. L'infrastructure ne bouge pas trop, mais tout ce qui va au dessus change sans cesse, pour implementer de nouvelles idees, pour essayer des trucs plus performants, etc. Et on obtient un ensemble pas forcement hyper solide a cause de ca.
Et quand l'infrastructure bouge sous Linux, c'est la panique. Quand j'ai fait le filesystem de QNX, c'etait a l'epoque des noyaux 2.2.X et 2.3.X, et quelques semaines plus tard, l'interface de la vfs (la colle entre les filesystems et les drivers) a change. L'ext2 a ete adapte a la nouvelle interface, mais les autres filesystems ont eu enormement de mal a completement migrer. Pour le qnx4fs, j'avais vaguement modifie le code d'apres celui de l'ext2, mais il restait des appels a des fonctions de l'"ancienne" infrastructure qui donnaient un truc instable. Ca a ete la meme merde plus tard puissance 10 pour ReiserFS et c'etait d'ailleurs l'une des raisons qui a retarde son integration dans le noyau.
Sous BSD, ce genre de changement est necessaire tout le temps. Par exemple l'introduction du cache unifie (UBC) dans NetBSD et OpenBSD, ca a necessite de reprendre fichier par fichier tout ce qui faisait appel de pres ou de loin au gestionnaire de memoire. Il y a eu des oublis qui ont cause des bogues aleatoires impossibles a localiser. C'est pour ca que l'UBC est integre depuis 1 ans dans OpenBSD, mais toujours pas utilise. Art s'est remis au boulot recemment, en rechangeant tout, et en se resynchronisant sur NetBSD, car les bogues etaient vraiment trop chiants a trouver... trop disperses (encore une fois a cause du manque de compartimentation et de couches d'abstraction sous BSD. Sous Linux, c'est beaucoup plus simple de localiser ce type de bogue) .