Come funziona putenv () / setenv () senza spostare l'intero stack utente?

Aug 20 2020

Ho letto diversi post qui e sono ancora confuso su come setenv()funziona:

  • linux-dove-sono-memorizzate-le-variabili-d'ambiente
  • dove-è-la-stringa-ambiente-effettivamente memorizzata
  • come-programma-il-mio-setenv

La mia comprensione è che le variabili di ambiente sono memorizzate come un gruppo di stringhe "foo = bar \ 0" continuamente nella parte inferiore dello stack utente, e quindi c'è un array envp[]di puntatori che puntano a queste stringhe, anche vicino alla parte inferiore del stack utente. Lo stack utente cresce sopra questi byte, il che significa che non è banale aggiungere più cose all'area delle stringhe o all'array di puntatori. Quindi come setenv()funziona se una nuova variabile è impostata (è necessario aggiungere un elemento a envp[]), o una variabile viene modificata ma la nuova stringa del valore è più lunga di quella vecchia (rendendo impossibile la modifica sul posto), senza spostare (quasi) il intero stack utente per fare spazio ai nuovi arrivati?

Una domanda in qualche modo correlata è, bashmantiene un elenco interno di variabili impostate localmente, e quando si utilizza exportla variabile impostata localmente, la bashrimuove semplicemente da questo elenco gestito localmente e aggiungerla nella parte inferiore dell'area delle stringhe dello stack sopra menzionata e inserire il suo puntatore a l'array di puntatori envp[], in modo che i suoi processi figli ereditino automaticamente le variabili esportate?

Risposte

KurtisRader Aug 20 2020 at 12:35

La mia comprensione è che le variabili di ambiente sono archiviate come ...

La tua comprensione è solo parzialmente corretta. :Sorridi:

... senza spostare (quasi) l'intero stack utente per fare spazio ai nuovi arrivati?

Sarebbe impossibile. Indipendentemente dal fatto che la lingua in cui è stato scritto il programma sia C o il sistema operativo UNIX. Ad esempio, perché i puntatori nello stack possono fare riferimento ad altre posizioni nello stack.

La prima cosa da notare è che la posizione in cui vengono archiviate le env var in un nuovo processo dipende dall'architettura. La maggior parte delle implementazioni UNIX, sulla maggior parte delle architetture CPU, lo memorizzano nello stack come descritto. Ma non c'è letteralmente nulla nella specifica C che imponga tale soluzione. Inoltre, se si modifica l'ambiente, l'implementazione è libera di copiare il blocco delle variabili di ambiente esistenti in una nuova posizione in memoria. L'implementazione C è libera di spostare il blocco di env vars e aggiornare la magic __environvar.

Una domanda in qualche modo correlata è, bash mantiene un elenco interno di variabili impostate localmente ...

Non nel modo in cui descrivi. Mantiene un "elenco interno" di variabili impostate localmente. Ma non lo usa nel modo che suggerisci.

Sono curioso di sapere cosa ti ha spinto ad aprire questo numero