NetBSD et boot PVH : du néant à init(8)

Magazine
Marque
GNU/Linux Magazine
Numéro
271
Mois de parution
septembre 2024
Spécialité(s)


Résumé

Dans GLMF 270, nous avons intégré au code de démarrage du noyau NetBSD, locore.S, les modifications nécessaires pour permettre à ce dernier de trouver les informations relatives à une VM et ainsi booter en mode PVH. Muni de ces informations et de cette nouvelle fonctionnalité, le code plus haut niveau du noyau va pouvoir avancer dans le processus de boot.


Body

La question que je me suis posée le plus souvent pendant l’avancée dans cette aventure fut « où sommes-nous ? ». En effet, ici nous travaillons à la pince à épiler, en corrigeant ou modifiant des composants très bas niveau qui pourraient avoir des conséquences indéterminées dans la suite du déroulement du programme « noyau ». Aussi, après avoir a priori réussi à copier les données fournies par l’hôte au système invité, là où le noyau s’attend à les trouver : où atterrit-on ?

1. Gawwwww (bruit d’un rebond sur un millier d’élastiques)

Après avoir compilé notre noyau avec les modifications effectuées dans le précédent article, nous allons constater jusqu’où cela nous permet d’avancer. Pour rappel, on démarre qemu de cette façon :

# noyau muni des symboles de débogage
$ KERNEL=sys/arch/amd64/compile/obj/MICROVM/netbsd.gdb
$ qemu-system-x86_64 -M microvm,accel=kvm -m 128 -cpu host \
-kernel ${KERNEL} -append "root=ld0a console=com rw -v" \
-display none -serial stdio -S -s

Inutile de préciser un média disque, nous n’en sommes pas encore là. Les drapeaux -S et -s servent respectivement à démarrer la machine virtuelle en mode « pause » de façon à pouvoir avancer pas à pas dans le serveur gdb, invoqué grâce au drapeau -s.

Le démarrage de qemu s’effectue sur un hôte GNU/Linux, pour déboguer un noyau NetBSD nous avons besoin d’un gdb fonctionnant sur un système NetBSD qui va se connecter au serveur gdb précédemment démarré.

Si l’opération de copie de start_info, le nom de la structure de données qui contient les informations de démarrage, a porté ses fruits, nous devrions pouvoir traverser les étapes d’initialisation de l’espace d’adressage virtuel du noyau, et par conséquent, poursuivre notre route en 64 bits, finalisée au label longmode_hi de locore.S.

Attachons nos ceintures, car là où on va, il n’y a pas... de route.

Livre de chevet

Pour la suite de la lecture de cet article, il sera judicieux d’avoir le fichier sys/arch/amd64/amd64/locore.S ouvert non loin de vous [1].

Voici le code que nous allons traverser :

compat:
 
    /*
     * 5. Not quite done yet, we're now in a
     * compatibility segment, in legacy mode.
     * We must jump to a long mode segment.
     * Need to set up a temporary GDT with a
     * long mode segment in it to do that.
     */
    movl    $RELOC(gdt64_lo),%eax
    lgdt    (%eax)
    movl    $RELOC(farjmp64),%eax
    ljmp    *(%eax)
 
    .code64
longmode:
    /*
     * 6. Finally, we're in long mode. However,
     * we're still in the identity mapped area
     * (could not jump out of that earlier because
     * it would have been a > 32bit jump).
     * We can do that now, so here we go.
     */
    movabsq $longmode_hi,%rax
    jmp *%rax
 
longmode_hi:
 
    /*
     * We left the identity mapped area. Base
     * address of the temporary gdt64 should
     * now be in high memory.
     */
    movq    $RELOC(gdt64_hi),%rax
    lgdt    (%rax)
 
    /*
     * We have arrived. There's no need anymore
     * for the identity mapping in low memory,
     * remove it.
     */
    movq    $KERNBASE,%r8

On passe d’abord par le label compat:, car nous ne pouvons pour le moment pas directement sauter sur une adresse 64 bits depuis notre programme démarré en 32 bits :

(gdb) p &compat
$2 = (<text variable, no debug info> *) 0xffffffff8020b37f <start+895>
(gdb) b *0x20b37f
Breakpoint 2 at 0x20b37f
(gdb) c
Continuing.
 
Breakpoint 3, 0x000000000020b37f in ?? ()
(gdb)

Arriver à cette étape signifie que notre précédent patch a fonctionné, nous ne nous arrêtons plus dans une boucle qui vient écraser les données du noyau, l’étape de l’initialisation des adresses virtuelles de ce dernier a réussi.

On constate par ailleurs que le code à venir correspond bien au code source :

(gdb) x/16i 0x20b37f
=> 0x20b37f:    mov    $0x800040,%eax
   0x20b384:    lgdt   (%rax)
   0x20b387:    mov    $0x8000d8,%eax
   0x20b38c:    ljmp   *(%rax)
   0x20b38e:    movabs $0xffffffff8020b39a,%rax
   0x20b398:    jmp    *%rax
   0x20b39a:    mov    $0x800080,%rax
   0x20b3a1:    lgdt   (%rax)
   0x20b3a4:    mov    $0xffffffff80000000,%r8

Dans la perspective où nous allons passer dans un autre mode d’adressage, il convient d’effacer notre breakpoint 32 bits qui n’aura plus de sens si tout se déroule comme prévu :

(gdb) d
Delete all breakpoints? (y or n) y
(gdb)

Tentons maintenant d’exécuter les 9 instructions précédentes afin de passer en mode 64 bits :

(gdb) si 9
0xffffffff8020b3ab in start ()

Gagné ! On voit maintenant que KERNBASE, soit 0xffffffff80000000, a bien été ajouté à l’adresse 32 bits. On remarque également que puisque nous sommes désormais en mode 64 bits, gdb « reconnaît » que nous sommes dans la fonction start(), dont le symbole a une adresse 64 bits.

Mais alors… est-ce à dire que nous pouvons placer un breakpoint sur la première fonction en C appelée depuis locore.S, voire mieux, y rentrer ?

(gdb) b init_bootspace
Breakpoint 2 at 0xffffffff802341e5: file /home/imil/src/NetBSD-src/sys/arch/amd64/amd64/machdep.c, line 1543.
(gdb) c
Continuing.
 
Breakpoint 2, init_bootspace () at /home/imil/src/NetBSD-src/sys/arch/amd64/amd64/machdep.c:1543
1543            memset(&bootspace, 0, sizeof(bootspace));

C’est pour des moments comme celui-là que je suis prêt à voir des heures et des jours partir en fumée ; concrètement, nous avons réussi, nous avons bien branché sur le boot PVH, et les instructions bas niveau de mise en place de la mémoire virtuelle ainsi que le passage en 64 bits sont un succès, nous pouvons continuer avec les étapes de démarrage.

2. Le nouvel invité

Il est temps de mettre un nom sur notre nouvelle fonctionnalité ! E que s’apelerio GENPVH.

Le choix de ce nom fut simple, on dérive du type VM_GUEST_XENPVH, mais GENérique, c.-à-d. pas tributaire d’un hyperviseur Xen.

On ajoute ce nouveau type dans le fichier sys/arch/x86/include/cpu.h, où sont définis les différents types de VM invités dans un type enum :

typedef enum vm_guest {
    VM_GUEST_NO = 0,
    VM_GUEST_VM,
    VM_GUEST_XENPV,
    VM_GUEST_XENPVH,
    VM_GUEST_XENHVM,
    VM_GUEST_XENPVHVM,
    VM_GUEST_HV,
    VM_GUEST_VMWARE,
    VM_GUEST_KVM,
    VM_GUEST_VIRTUALBOX,
    VM_GUEST_GENPVH, /* ici */
    VM_LAST
} vm_guest_t;

L’utilité de ce type est de pouvoir identifier le boot PVH générique tout au long du démarrage du noyau, aussi est-il impératif de renseigner locore.S lorsqu’il est identifié. Nous ferons cela dans la fonction start_xen32 en remplaçant :

movl    $VM_GUEST_XENPVH, RELOC(vm_guest)

par :

movl    $VM_GUEST_GENPVH, RELOC(vm_guest)

Attention ! Lorsque nous sortirons de la phase de prototypage, il faudra bien entendu réaliser les tests nécessaires pour vérifier que nous démarrons via Xen ou un autre hyperviseur. Ici, nous remplaçons le type pour poursuivre le périple rapidement.

Afin de pouvoir utiliser ce nouveau symbole, nous le déclarons également dans le fichier sys/arch/amd64/amd64/genassym.cf :

define VM_GUEST_GENPVH     VM_GUEST_GENPVH

Voilà, nous pouvons désormais faire référence à notre type de machine virtuelle dans le reste du code du noyau.

3. Non-Xen

Il faut comprendre que dans le processus de démarrage de notre machine virtuelle, nous utilisons 90 % de code prévu pour le boot Xen PVH, plus particulièrement le code qui gère le rangement des variables du fameux start_info. A contrario, toute la mécanique liée à la gestion de l’invité, et en particulier les demandes d’accès à des ressources privilégiées, est gérée nativement par l’hyperviseur, KVM dans notre cas. La surcouche de gestion des syscalls, appelés hypercalls dans Xen, est donc superflue.

De façon assez surprenante, les modifications à apporter furent assez minimales. Tout d’abord, nous ajoutons dans sys/arch/xen/include/hypervisor.h une variable qui pourra être accédée par l’ensemble du code du noyau, qui permettra de savoir si nous avons démarré en mode PVH :

extern bool pvh_boot;

Cette variable sera renseignée dans sys/arch/xen/xen/hypervisor.c, code que nous allons réorganiser pour prendre en compte une plateforme non-Xen. La fonction init_xen_early() est l’une des premières fonctions C invoquées par locore.S, voici un pseudopatch commenté pour cette fonction :

init_xen_early(void)
{
        const char *cmd_line;
 
+   /* On étend le test à VM_GUEST_GENPVH */
-       if (vm_guest != VM_GUEST_XENPVH)
 
+       if (vm_guest != VM_GUEST_XENPVH && vm_guest != VM_GUEST_GENPVH)
+       /* Nous n'avons pas démarré via PVH */
                return;
 
+   /* On déplace ce test plus bas pour le cas où nous n'utilisons pas Xen */
-       xen_init_hypercall_page();
+
+   /* On va utiliser cette information à plusieurs endroits du noyau */
+       pvh_boot = true;
+
    /* Ici on "cast" la structure d'informations reçue dans locore.S */
        hvm_start_info = (void *)((uintptr_t)hvm_start_paddr + KERNBASE);
 
    /*
     * Ce morceau de code permet de sauvegarder la chaîne de caractères
     * contenant les paramètres passés au noyau
     */
+       if (hvm_start_info->cmdline_paddr != 0) {
+               cmd_line =
+                   (void *)((uintptr_t)hvm_start_info->cmdline_paddr + KERNBASE);
+               strlcpy(xen_start_info.cmd_line, cmd_line,
+                   sizeof(xen_start_info.cmd_line));
+       } else {
+               xen_start_info.cmd_line[0] = '\0';
+       }
+       xen_start_info.flags = hvm_start_info->flags;
+
+   /* Et si nous ne sommes pas un invité Xen, c'est tout pour nous ! */
+       if (vm_guest != VM_GUEST_XENPVH) /* non Xen PVH boot */
+               return;
+
+   /* Ici, l'invité est un domU Xen */
+       xen_init_hypercall_page();
 
[...]
 
    /* Ce bout de code a été déplacé plus haut */
-       if (hvm_start_info->cmdline_paddr != 0) {
-               cmd_line =
-                   (void *)((uintptr_t)hvm_start_info->cmdline_paddr + KERNBASE);
-               strlcpy(xen_start_info.cmd_line, cmd_line,
-                   sizeof(xen_start_info.cmd_line));
-       } else {
-               xen_start_info.cmd_line[0] = '\0';
-       }
-       xen_start_info.flags = hvm_start_info->flags;
}

4. Une nouvelle façon de démarrer

Notre noyau démarrant sur une machine virtuelle doit maintenant globalement emprunter le même chemin qu’un noyau sur un invité de type VM_GUEST_XENPVH, mais en ignorant les subtilités propres à Xen, ainsi, un brutal grep -r VM_GUEST_XENPVH sys/ nous informe des fichiers à considérer.

Nous allons comprendre l’importance de cette fameuse structure start_info. Techniquement, nous sommes en train de démarrer une machine x86, qui anciennement recevait ses informations du bootloader (qui lui-même en recevait une partie du BIOS), parmi ces informations cruciales se trouve le périphérique de démarrage, rien que ça ! Ce paramètre, dans notre cas, est passé comme argument au noyau : -append "root=ld0a", et une fonction existe déjà dans sys/arch/xen/xen/xen_machdep.c pour décoder les informations passées en ligne de commande, il s’agit de xen_parse_cmdline(), dont voici la section qui nous intéresse :

void
xen_parse_cmdline(int what, union xen_cmdline_parseinfo *xcp)
{
[...]
    while (cmd_line && *cmd_line) {
        opt = cmd_line;
        cmd_line = strchr(opt, ' ');
        if (cmd_line)
            *cmd_line = 0;
 
        switch (what) {
        case XEN_PARSE_BOOTDEV:
            if (strncasecmp(opt, "bootdev=", 8) == 0) {
                strncpy(xcp->xcp_bootdev, opt + 8,
                    sizeof(xcp->xcp_bootdev));
                break;
            }
            if (strncasecmp(opt, "root=", 5) == 0) {
                strncpy(xcp->xcp_bootdev, opt + 5,
                    sizeof(xcp->xcp_bootdev));
                break;
            }
            break;
[...]
    }
[...]
}

Ce scénario est présent dans sys/arch/x86/x86/x86_autoconf.c à la fonction cpu_bootconf, mais ne prend en compte que VM_GUEST_XENPVH, or, nous disposons maintenant d’une variable, pvh_boot, qui couvre les cas de figure VM_GUEST_XENPVH et VM_GUEST_GENPVH, il suffit donc d’appliquer ce patch pour connaître notre device de boot :

+#ifdef XENPVHVM
+#include <xen/hypervisor.h>
+#endif
+
struct disklist *x86_alldisks;
int x86_ndisks;
int x86_found_console;
@@ -540,7 +544,7 @@ void
cpu_bootconf(void)
{
#ifdef XEN
-   if (vm_guest == VM_GUEST_XENPVH) {
+   if (pvh_boot) {
        xen_bootconf();
        return;
    }

Les autres éléments incontournables habituellement délivrés par le BIOS sont les zones mémoire disponibles pour l’invité, leur préparation pour être utilisées par le noyau est effectuée dans sys/arch/x86/x86/x86_machdep.c dans la fonction init_x86_clusters(). Là encore, le cas est prévu pour Xen, et utilise x86_add_xen_clusters() au lieu de x86_parse_clusters(), le patch est trivial :

@@ -911,7 +911,7 @@ init_x86_clusters(void)
         * the boot program).
         */
#ifdef XEN
-       if (vm_guest == VM_GUEST_XENPVH) {
+       if (pvh_boot) {
                x86_add_xen_clusters();
        }
#endif /* XEN */

Il manque également une zone mémoire dont les informations sont normalement fournies par le BIOS ou l’UEFI : les tables ACPI. Et si vous vous souvenez de la liste des informations fournies par start_info vues dans le précédent épisode, on y trouve effectivement ces adresses. Même cause, même conséquence, cette fois dans la fonction acpi_md_OsGetRootPointer dans le fichier sys/arch/x86/acpi/acpi_machdep.c :

#ifdef XEN
-       if (vm_guest == VM_GUEST_XENPVH) {
+       if (pvh_boot) {
                PhysicalAddress = hvm_start_info->rsdp_paddr;
                if (PhysicalAddress)
                        return PhysicalAddress;

Nous y sommes presque, il nous manque encore une information classiquement passée par le bootloader, ce sont les drapeaux passés au noyau pour lui indiquer son mode de démarrage, par exemple -s pour démarrer en mode utilisateur unique, habituellement pour déboguer son système, -v pour être verbeux, -z pour afficher le minimum…

Ce patch ciblera la fonction init_x86_64() dans sys/arch/amd64/amd64/machdep.c, et nous allons à nouveau utiliser la fonction xen_parse_cmdline() :

#ifdef XEN
-       if (vm_guest == VM_GUEST_XENPVH)
+       if (pvh_boot)
                xen_parse_cmdline(XEN_PARSE_BOOTFLAGS, NULL);
#endif

5. Y fait tout noir ici !

Afin de visualiser les premiers pas de notre noyau sur la console série, nous pouvons forcer cette dernière à l’aide de l’option CONSDEVNAME du noyau, qui se déclare de cette façon :

options    CONSDEVNAME="\"com\""

Néanmoins, il est bien plus pratique et portable de spécifier ces informations comme des paramètres du noyau, typiquement dans la ligne de commande qemu : -kernel ${KERNEL} -append "console=com". Seulement voilà, à ce stade, ce paramètre n’a aucun effet, et pour cause, nous nous trouvons dans une situation bâtarde, en effet, d’un côté, les informations sur le type de console à utiliser pour l’affichage sont typiquement transmises par le bootloader, qui est absent de notre amorce ; de l’autre, lorsque l’hyperviseur est Xen, sys/arch/xen/x86/consinit.c implémente bien l’interprétation de start_info, mais est truffé de spécificités liées à Xen, et dans la mesure du possible, j’aimerais éviter l’inclusion de trop de symboles et conditions inutiles.

La solution : modifier sys/arch/x86/x86/consinit.c, le code responsable de l’initialisation de la console pour une plateforme x86, pour y implémenter l’interprétation des paramètres passés au noyau dans un boot PVH.

void
consinit(void)
{
+   /*
+    * On déclare une courte chaîne de caractères pour
+    * recevoir le nom de la console
+    */
+   char console_devname[16] = "";
 
[...]
 
+   if (pvh_boot) {
+       union xen_cmdline_parseinfo xcp;
+       /*
+        * On utilise la fonction xen_parse_cmdline()
+        * pour récupérer les paramètres dans la structure
+        * de données xcp
+        */
+       xen_parse_cmdline(XEN_PARSE_CONSOLE, &xcp);
+       /* et on copie le nom de la console ("pc", "com", ...) */
+       strncpy(console_devname, xcp.xcp_console,
+           sizeof(console_devname));
+   }
 
[...]
 
+   /* Si console_devname[0] est vide, on va utiliser
       les paramètres passés par le bootloader */
+   if (!console_devname[0])
+       strncpy(console_devname, consinfo->devname,
+           sizeof(console_devname));
 
[...]
 
    /* Et dans la suite de la fonction,
       on utilise notre chaîne */
 
-   if (!strcmp(consinfo->devname, "pc")) {
+   if (!strcmp(console_devname, "pc")) {
 
[...]
 
-   if (!strcmp(consinfo->devname, "com")) {
+   if (!strcmp(console_devname, "com")) {
 
-   if (!strcmp(consinfo->devname, "nullcons")) {
+   if (!strcmp(console_devname, "nullcons")) {
 
[...]
 
-   panic("invalid console device %s", consinfo->devname);
+   panic("invalid console device %s", console_devname);
}

Et en effet, après application de ce dernier patch, enfin, le résultat de plusieurs mois de travail s’affiche sous nos yeux humides :

$ qemu-system-x86_64 -M microvm,accel=kvm -m 128 -cpu host -kernel ${KERNEL} -append "console=com rw -v" -display none -serial stdio
[   1.0000000] cpu_rng: rdrand/rdseed
[   1.0000000] entropy: ready
[   1.0000000] Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
[   1.0000000]     2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013,
[   1.0000000]     2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023,
[   1.0000000]     2024
[   1.0000000]     The NetBSD Foundation, Inc. All rights reserved.
[   1.0000000] Copyright (c) 1982, 1986, 1989, 1991, 1993
[   1.0000000]     The Regents of the University of California. All rights reserved.
 
[   1.0000000] NetBSD 10.99.10 (MICROVM) #312: Thu Jun 20 07:29:44 CEST 2024
[   1.0000000] imil@tatooine:/home/imil/src/NetBSD-src/sys/arch/amd64/compile/obj/MICROVM
[   1.0000000] total memory = 127 MB
[   1.0000000] avail memory = 114 MB
[   1.0000000] timecounter: Timecounters tick every 10.000 msec
[   1.0000000] RTC BIOS diagnostic error 0xff<clock_battery,ROM_cksum,config_unit,memory_size,fixed_disk,
invalid_time>
[   1.0000000] timecounter: Timecounter "i8254" frequency 1193182 Hz quality 100
[   1.0000030] mainbus0 (root)
[   1.0000030] cpu0 at mainbus0
[   1.0000030] cpu0: Use lfence to serialize rdtsc
[   1.0000030] cpu0: Intel(R) Core(TM) i5-7600K CPU @ 3.80GHz, id 0x906e9
[   1.0000030] cpu0: node 0, package 0, core 0, smt 0
[   1.0000030] isa0 at mainbus0
[   1.0000030] com0 at isa0 port 0x3f8-0x3ff irq 4: ns16550a, 16-byte FIFO
[   1.0000030] com0: console
[   1.0000030] allocated pic pic0 type edge pin 4 level 8 to cpu0 slot 4 idt entry 36
[   1.0000030] allocated pic pic0 type level pin 0 level 7 to cpu0 slot 0 idt entry 32
[   1.0000030] timecounter: Timecounter "clockinterrupt" frequency 100 Hz quality 0
[   1.0000030] timecounter: Timecounter "TSC" frequency 3870900700 Hz quality -100
[   1.0000030] boot device: <unknown>
[   1.0000030] root device:

Le noyau démarre en mode PVH, invoqué par le drapeau -kernel de qemu.

smolBSD 4 figure 01-s

Fig. 1 : Mic drop!

6. FASTER!

Notre noyau boote vite. Relativement. Une centaine de millisecondes. Mais nous pouvons faire mieux, beaucoup mieux. Et puis, il y a autre chose, ce noyau démarre avec qemu, qui est capable d’utiliser un bus PCI pour attacher disques et cartes réseau virtuelles de type VirtIO, seulement voilà, un autre gestionnaire léger de machine virtuelle, Firecracker [2], ne dispose pas de support PCI, il utilise à sa place un bus virtuel, MMIO, plus léger et plus rapide, qui a le bon goût d’être supporté par qemu.

Vous l’aurez compris, la série n’est pas terminée. Alors on se retrouve bientôt pour l’implémentation d’un bus virtuel, et l’utilisation de MMIO avec VirtIO. Tout un programme…

7. Épilogue

À l’heure où j’écris ces lignes, le patchset complet de l’ajout de ces fonctionnalités au noyau NetBSD est en cours de review, en effet, ces patchs modifient des éléments fondamentaux du démarrage du noyau, il est donc important qu’ils soient bien revus et analysés par plusieurs yeux expérimentés. Si tout se passe bien, cette feature fera partie de NetBSD 11 !

Références

[1] https://github.com/NetBSDfr/NetBSD-src/blob/trunk/sys/arch/amd64/amd64/locore.S

[2] https://github.com/firecracker-microvm/firecracker



Article rédigé par

Par le(s) même(s) auteur(s)

smolBSD : UNIX façon « Ikea »

Magazine
Marque
Linux Pratique
Numéro
141
Mois de parution
janvier 2024
Spécialité(s)
Résumé

Dans les séries américaines, on appelle ce genre d’histoire un crossover, les premières occurrences ont démarré dans Linux Pratique, puis une partie plus profonde sur l’amincissement d’un noyau NetBSD, pas nécessairement utile pour la finalité de notre produit, a fait son apparition dans GNU/Linux Magazine. Aujourd’hui, nous allons apprendre à construire un système BSD UNIX, NetBSD, From Scratch.

SmolBSD : un système UNIX de 7 mégaoctets qui démarre en moins d’une seconde

Magazine
Marque
GNU/Linux Magazine
Numéro
265
Mois de parution
septembre 2023
Spécialité(s)
Résumé

Que de racolage en si peu de mots. Et pourtant si, c’est bien la promesse de cet article, comment parvenir à construire un système d’exploitation fonctionnel en moins de… 10 mégabits. Quelle est cette sorcellerie ? En utilisant une fonctionnalité prévue, mais pas utilisée à cet escient par le noyau NetBSD, nous allons lui faire subir un régime drastique !

La grande migration, Épisode II

Magazine
Marque
Linux Pratique
Numéro
138
Mois de parution
juillet 2023
Spécialité(s)
Résumé

Dans l’épisode précédent [1], nous avons posé les premières briques d’une infrastructure d’auto-hébergement : vm-bhyve comme solution de virtualisation, sous FreeBSD donc, Wireguard comme gestionnaire de tunnel, une petite instance t4g.nano, 2 cœurs ARM64 et 512M de RAM chez AWS et un premier succès de déplacement de machine virtuelle hébergeant un simple serveur web d’un serveur dédié vers notre infrastructure personnelle. Nous allons voir maintenant comment migrer en douceur une machine virtuelle concentrant les services de base d’une architecture à l’autre.

Les derniers articles Premiums

Les derniers articles Premium

Bun.js : l’alternative à Node.js pour un développement plus rapide

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Dans l’univers du développement backend, Node.js domine depuis plus de dix ans. Mais un nouveau concurrent fait de plus en plus parler de lui, il s’agit de Bun.js. Ce runtime se distingue par ses performances améliorées, sa grande simplicité et une expérience développeur repensée. Peut-il rivaliser avec Node.js et changer les standards du développement JavaScript ?

PostgreSQL au centre de votre SI avec PostgREST

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Dans un système d’information, il devient de plus en plus important d’avoir la possibilité d’échanger des données entre applications. Ce passage au stade de l’interopérabilité est généralement confié à des services web autorisant la mise en œuvre d’un couplage faible entre composants. C’est justement ce que permet de faire PostgREST pour les bases de données PostgreSQL.

La place de l’Intelligence Artificielle dans les entreprises

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

L’intelligence artificielle est en train de redéfinir le paysage professionnel. De l’automatisation des tâches répétitives à la cybersécurité, en passant par l’analyse des données, l’IA s’immisce dans tous les aspects de l’entreprise moderne. Toutefois, cette révolution technologique soulève des questions éthiques et sociétales, notamment sur l’avenir des emplois. Cet article se penche sur l’évolution de l’IA, ses applications variées, et les enjeux qu’elle engendre dans le monde du travail.

Petit guide d’outils open source pour le télétravail

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Ah le Covid ! Si en cette période de nombreux cas resurgissent, ce n’est rien comparé aux vagues que nous avons connues en 2020 et 2021. Ce fléau a contraint une large partie de la population à faire ce que tout le monde connaît sous le nom de télétravail. Nous avons dû changer nos habitudes et avons dû apprendre à utiliser de nombreux outils collaboratifs, de visioconférence, etc., dont tout le monde n’était pas habitué. Dans cet article, nous passons en revue quelques outils open source utiles pour le travail à la maison. En effet, pour les adeptes du costume en haut et du pyjama en bas, la communauté open source s’est démenée pour proposer des alternatives aux outils propriétaires et payants.

Les listes de lecture

9 article(s) - ajoutée le 01/07/2020
Vous désirez apprendre le langage Python, mais ne savez pas trop par où commencer ? Cette liste de lecture vous permettra de faire vos premiers pas en découvrant l'écosystème de Python et en écrivant de petits scripts.
11 article(s) - ajoutée le 01/07/2020
La base de tout programme effectuant une tâche un tant soit peu complexe est un algorithme, une méthode permettant de manipuler des données pour obtenir un résultat attendu. Dans cette liste, vous pourrez découvrir quelques spécimens d'algorithmes.
10 article(s) - ajoutée le 01/07/2020
À quoi bon se targuer de posséder des pétaoctets de données si l'on est incapable d'analyser ces dernières ? Cette liste vous aidera à "faire parler" vos données.
Voir les 68 listes de lecture

Abonnez-vous maintenant

et profitez de tous les contenus en illimité

Je découvre les offres

Déjà abonné ? Connectez-vous