1 points par GN⁺ 2 시간 전 | 1 commentaires | Partager sur WhatsApp
  • BusyBox est un binaire multicall qui fournit plusieurs commandes dans un seul exécutable, et le wget par défaut d’Alpine est lui aussi exécuté via BusyBox
  • Dans un conteneur Alpine, /usr/bin/wget n’était pas un vrai binaire mais un lien symbolique pointant vers /bin/busybox
  • Lors de l’exécution, BusyBox lit le nom d’appel dans argv[0] et détermine quelle applet exécuter à partir du dernier élément du chemin
  • Chaque applet est recherchée par son nom puis entre dans sa fonction main correspondante ; wget est implémenté dans wget.c et exécute finalement wget_main
  • busybox --list permet de voir les commandes compilées ; dans l’exemple Alpine, 304 sont affichées, et chaque utilitaire ressemble à une version allégée

Fonctionnement de BusyBox

  • BusyBox utilise une architecture de binaire multicall (multicall binary) qui fournit plusieurs commandes dans un seul exécutable
  • Dans un conteneur Alpine, /usr/bin/wget n’était pas un véritable exécutable mais un lien symbolique pointant vers /bin/busybox
    docker run --rm -it alpine sh
    / # which wget
    /usr/bin/wget
    / # ls -lah /usr/bin/wget
    lrwxrwxrwx    1 root     root          12 Apr 15 04:51 /usr/bin/wget -> /bin/busybox
    
  • Dans /usr/bin, plus de 130 exécutables semblent provenir d’un seul binaire, ce qui est lié à l’architecture multicall de BusyBox
  • Lors de l’exécution, BusyBox récupère le nom invoqué depuis argv[0], puis n’en extrait que le dernier élément du chemin pour déterminer quelle applet exécuter
    applet_name = argv[0];
    if (applet_name[0] == '-')
      applet_name++;
    applet_name = bb_basename(applet_name);
    
  • Il fonctionne aussi si l’on passe explicitement le nom de l’applet, comme avec busybox ls -1 ; si on fournit un nom inexistant, applet not found s’affiche
    / # busybox ls -1
    bin
    dev
    etc
    home
    
    / # busybox meheh
    meheh: applet not found
    

Organisation des applets et méthode d’installation

  • BusyBox recherche l’applet par son nom, puis exécute la fonction main correspondante
    int applet = find_applet_by_name(name);
    // ...
    run_applet_no_and_exit(applet, name, argv);
    // ...
    xfunc_error_retval = applet_main[applet_no](argc, argv);
    
  • Chaque applet possède son propre fichier C ; wget est implémenté dans wget.c
  • La configuration de chaque applet est définie sous forme de commentaires dans le code ; pour WGET, on y trouve wget (41 kb), son activation par défaut, un texte d’aide indiquant qu’il s’agit d’un utilitaire de téléchargement non interactif depuis des serveurs HTTP et FTP, ainsi que la cible de build wget.o
    //config:config WGET
    //config:	bool "wget (41 kb)"
    //config:	default y
    //config:	help
    //config:	wget is a utility for non-interactive download of files from HTTP
    //config:	and FTP servers.
    //applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP))
    //kbuild:lib-$(CONFIG_WGET) += wget.o
    
  • Au final, l’applet wget entre dans wget_main
    int wget_main(int argc UNUSED_PARAM, char **argv)
    
  • BusyBox prend aussi en charge les liens physiques, et dans busybox --install -s, -s signifie création de liens symboliques
    busybox --install -s
    
  • La liste des commandes incluses à la compilation peut être affichée avec busybox --list ; dans l’environnement Alpine de l’exemple, 304 sont affichées
    / # busybox --list | wc -l
    304
    
  • De nombreuses commandes d’Alpine fonctionnent comme une interface vers un binaire basé sur BusyBox, et chaque utilitaire ressemble à une version allégée de son équivalent complet

1 commentaires

 
GN⁺ 2 시간 전
Avis sur Lobste.rs
  • La réponse à la question citée est plus proche d’une réimplémentation
    Une présentation de BusyBox se trouve sur https://busybox.net/about.html, et le code source sur https://github.com/vda-linux/busybox_mirror

  • Le fait qu’un programme prétende porter un autre nom que le sien est assez agaçant
    Le pire, c’est quand on exécute gcc sur macOS et qu’on obtient en réalité clang ; PowerShell fonctionne aussi un peu comme ça. Ce serait mieux d’utiliser simplement un autre nom

    • Cela vient aussi du fait que beaucoup de développeurs ne connaissaient pas clang, n’avaient pas de Mac pour tester, ou n’avaient pas d’alternative réaliste à l’époque où le problème a commencé
      Nixpkgs doit appliquer beaucoup de correctifs comme https://github.com/NixOS/nixpkgs/…, et même un projet connu comme sqlite n’y échappe pas. À l’inverse, macOS a simplement choisi la voie du chemin trompeur
    • Certaines personnes qui écrivent les makefiles de nombreux logiciels ne connaissent pas cc
    • Je comprends la frustration, mais si c’est suffisamment compatible pour faire tourner la plupart des scripts de build, cela a probablement aidé sa diffusion, car on peut ainsi réutiliser dans une certaine mesure les mêmes scripts entre Linux et divers Unix
    • Parfois, ce n’est tout simplement pas réaliste
      Il existe sans doute beaucoup de makefiles où gcc est codé en dur, et on retrouve le même genre de problème ailleurs. Par exemple, de nombreux programmes existants vérifient xterm-* dans la variable d’environnement TERM au lieu d’utiliser la base de données terminfo, qui est pourtant la bonne solution ; dans ce cas, choisir un autre nom ne fonctionne pas
  • Quand je dois diagnostiquer un problème étrange dans un conteneur, j’utilise souvent podman cp /usr/bin/busybox-static somecontainer:/bin

  • toybox a une structure similaire
    Certains outils semblent repris ou portés depuis ailleurs, mais un grand nombre ont été réimplémentés pour BusyBox, avec pour objectif de rester petits et de n’utiliser qu’un sous-ensemble limité des fonctions de libc afin de produire de petits binaires en liaison statique. Un autre avantage est qu’on peut utiliser ces outils dans des scripts shell comme s’il s’agissait de commandes intégrées. Certains s’exécutent avec fork+jump plutôt qu’avec fork+exec, et d’autres peuvent même s’exécuter comme de simples appels de fonction sans fork

    • Si je me souviens bien, toybox a été créé à l’origine comme alternative sous licence BSD à BusyBox, qui est sous GPL
      À noter que, d’après Toybox sur Wikipedia, « Toybox a été lancé début 2006 par Rob Landley après qu’il a cessé d’être mainteneur de BusyBox à la suite d’un différend avec Bruce Perens, le créateur original de BusyBox »
  • En pratique, c’est bien une réimplémentation. Cela dit, si la licence l’autorise, il ne serait pas surprenant que du code ait été repris en partie depuis l’implémentation originale plus volumineuse
    D’après Wikipédia : BusyBox a été écrit pour la première fois en 1995 par Bruce Perens, et déclaré terminé pour son usage prévu en 1996. L’objectif initial était de faire tenir sur une seule disquette un système entièrement amorçable servant à la fois de disque de secours et d’installateur pour la distribution Debian. Il s’est ensuite imposé comme la collection standard de base d’outils user space pour les appareils Linux embarqués et les installateurs de distributions Linux ; comme chaque exécutable Linux entraîne quelques kilo-octets de surcharge, fusionner plus de 200 programmes en un seul permet d’économiser considérablement de l’espace disque et de la mémoire
    À ce sujet, Toybox a lui aussi une structure et une philosophie similaires, mais sous licence BSD. Il me semble que son développeur principal, Rob Landley, pensait qu’avec une licence plus acceptable commercialement, il pourrait être inclus dans les appareils Android ; et que, dans ce cas, tous les téléphones et tablettes Android auraient le potentiel de devenir une sorte d’environnement de développement proche d’Unix. Toybox semble toujours faire partie d’Android, mais sans outils de surcouche comme Termux, Android n’est pas vraiment simple à utiliser comme un système Unix

    • Il serait difficile de trouver un exemple plus parfait montrant comment faire du travail gratuit pour une entreprise comme Google peut finir par se retourner contre soi
      C’est encore plus vrai quand on pense au fait que Google menace depuis des années de bloquer Termux
  • Il existe aussi un portage Windows : https://github.com/rmyorston/busybox-w32
    La petite taille de BusyBox rend ce genre de portage plus réaliste. Cela dit, on peut désormais simplement exécuter Linux dans Windows, donc cela semble un peu moins pertinent aujourd’hui