Как работает putenv () / setenv () без смещения всего пользовательского стека?

Aug 20 2020

Я прочитал здесь несколько сообщений и все еще не понимаю, как setenv()работает:

  • Linux-где-находятся-переменные-среды-хранятся
  • где-это-окружающая-строка-фактическое-хранится
  • как-я-программировать-мой-собственный-setenv

Насколько я понимаю, переменные среды хранятся в виде группы строк "foo = bar \ 0" непрерывно внизу пользовательского стека, а затем есть массив envp[]указателей, которые указывают на эти строки, также близко к нижней части пользовательский стек. Пользовательский стек растет поверх этих байтов, а это означает, что нетривиально добавлять что-то в область строк или массив указателей. Итак, как setenv()работает, если установлена ​​новая переменная (необходимо добавить элемент envp[]) или переменная изменена, но строка нового значения длиннее старой (что делает невозможным изменение на месте), без смещения (почти) весь стек пользователей, чтобы освободить место для новичков?

В некоторой степени связанный с этим вопрос заключается в том, bashсохраняет ли внутренний список локально установленных переменных, и когда пользователь exportиспользует локально установленную переменную, bashпросто удаляет ее из этого локально управляемого списка и добавляет ее в вышеупомянутую нижнюю часть области строки стека и вставляет указатель массив указателей envp[], чтобы его дочерние процессы автоматически наследовали экспортируемые переменные?

Ответы

KurtisRader Aug 20 2020 at 12:35

Насколько я понимаю, переменные среды хранятся как ...

Ваше понимание верно лишь отчасти. :улыбка:

... без перемещения (почти) всего пользовательского стека, чтобы освободить место для новичков?

Это было бы невозможно. Независимо от того, на каком языке написана программа, был C или операционная система UNIX. Например, потому что указатели в стеке могут ссылаться на другие места в стеке.

Первое, что следует отметить, это то, что где env vars хранятся в новом процессе, зависит от архитектуры. Большинство реализаций UNIX на большинстве архитектур ЦП хранят его в стеке, как вы описали. Но в спецификации C буквально нет ничего, что требовало бы этого решения. Кроме того, если вы измените среду, реализация может скопировать блок существующих переменных среды в новое место в памяти. Реализация C может перемещать блок переменных env и обновлять magic __environvar.

Несколько связанный вопрос: хранит ли bash внутренний список локально установленных переменных ...

Не так, как вы описываете. Он действительно ведет «внутренний список» локально установленных переменных. Но он не использует его так, как вы предлагаете.

Мне любопытно, что побудило вас открыть этот выпуск