Возникло пару вопросы касательно fork/exec:
1.Вызываются ли деструкторы текущего C++ кода при вызове exec? Или это что-то типа kill+reuse_pid+inherit_handles? «..does not return on success, and the text, data, bss, and stack of the calling process are overwritten by that of the program loaded» — ИМХО это мало согласуется с корректным освобождением ресурсов
2.Что происходит с потоками (threads) после форка?
3.Имеем CORBA объект, что с ним будет после форка? Удаленному объекту может не понравится такое разделение его проксей.
Помогите линками на внятные доки, не дайте вернуться в такой уютный и понятный мирок CreateProcess
Igor_G wrote:
> Возникло пару вопросы касательно fork/exec: > 1.Вызываются ли деструкторы текущего C++ кода при вызове exec?
Нет, т.к. успешный вызова exec управления не возвращает. В точности как с
exit/abort.
> Или это > что-то типа kill+reuse_pid+inherit_handles? «..does not return on > success, and the text, data, bss, and stack of the calling process are > overwritten by that of the program loaded» — ИМХО это мало согласуется с > корректным освобождением ресурсов
Как считаешь должно быть?
> 2.Что происходит с потоками (threads) после форка?
Остается только один поток.
> 3.Имеем CORBA объект, что с ним будет после форка? Удаленному объекту > может не понравится такое разделение его проксей.
Объекты exec не переживут, их не будет существовать после exec, т.к. адрессное
пр-во процесса создано заново.
-- Maxim Yegorushkin
No Microsoft product was used in any way to write or send this text.
If you use a Microsoft product to read it, you're doing so at your own risk
Здравствуйте, MaximE, Вы писали:
>> 1.Вызываются ли деструкторы текущего C++ кода при вызове exec? ME>Нет, т.к. успешный вызова exec управления не возвращает. В точности как с ME>exit/abort.
exit вроде как performs standard cleanup, да и 'return status;' в main() ИМХО в C++ более "правильно". Ну а abort на то и abort что он '_abnormal_ program termination'.
>> overwritten by that of the program loaded» — ИМХО это мало согласуется с >> корректным освобождением ресурсов ME>Как считаешь должно быть?
Что-то типа: разматываем стек до entry point, что _корректно_ освобождает все RAII ресуры, после чего можно и замещать новым кодом :)
То есть все что мне надо, так это банальный аналог виндового CreateProcess без всякого затирания еще не освобожденных ресурсов.
>> 2.Что происходит с потоками (threads) после форка? ME>Остается только один поток.
Имеем много "протекших" ресурсов?
>> 3.Имеем CORBA объект, что с ним будет после форка? Удаленному объекту >> может не понравится такое разделение его проксей.
ME>Объекты exec не переживут, их не будет существовать после exec, т.к. адрессное ME>пр-во процесса создано заново.
А предположим, что нет никакого exec после fork, что будет? Предполагаю, что такие внешние ресурсы должен разруливать сам разработчик.
Здравствуйте, Igor_G, Вы писали:
I_G>Эх, что-то я концептуально fork/exec не пойму
Сначала забудь C++.
Все очень банально. fork — создает точную копию текущего процесса в новом адресном пространстве. Все объекты ядра также копируются новому процессу (замечу, объект ядра и объект C++ ничего общего не имеют!). Что может банальнее?
exec — замена одного процесса другим в том же адресном пространстве. Объекты ядра сохраняются.
Вот только что с потоками происходит не скажу...
Все претензии по поводу неосвобожденных ресурсов вообще мне непонятны... Смотри на exec как на abort как уже было сказано... Почему компилятор должен сам ставить какие-то костыли для работы того или иного системного вызова?
Re[3]: fork/exec
От:
Аноним
Дата:
21.11.06 08:06
Оценка:
Здравствуйте, Igor_G, Вы писали:
I_G>То есть все что мне надо, так это банальный аналог виндового CreateProcess без всякого затирания еще не освобожденных ресурсов.
Если всё что нужно — это запускать другую программу, то смотри man 3 system
Здравствуйте, Igor_G, Вы писали:
>>> overwritten by that of the program loaded» — ИМХО это мало согласуется с >>> корректным освобождением ресурсов ME>>Как считаешь должно быть? I_G>Что-то типа: разматываем стек до entry point, что _корректно_ освобождает все RAII ресуры, после чего можно и замещать новым кодом I_G>То есть все что мне надо, так это банальный аналог виндового CreateProcess без всякого затирания еще не освобожденных ресурсов.
fork() + exec() и есть аналог CreateProcess. Все твои объекты остаются валидными в родительском процессе.
>>> 2.Что происходит с потоками (threads) после форка? ME>>Остается только один поток. I_G>Имеем много "протекших" ресурсов?
http://www.opengroup.org/onlinepubs/009695399/functions/pthread_atfork.html
>>> 3.Имеем CORBA объект, что с ним будет после форка? Удаленному объекту >>> может не понравится такое разделение его проксей.
ME>>Объекты exec не переживут, их не будет существовать после exec, т.к. адрессное ME>>пр-во процесса создано заново.
I_G>А предположим, что нет никакого exec после fork, что будет? Предполагаю, что такие внешние ресурсы должен разруливать сам разработчик.
Какая у тебя конкретно проблема?
I_G>Эх, что-то я концептуально fork/exec не пойму
Здравствуйте, DOOM, Вы писали:
DOO>Все очень банально. fork — создает точную копию текущего процесса в новом адресном пространстве. Все объекты ядра также копируются новому процессу (замечу, объект ядра и объект C++ ничего общего не имеют!). Что может банальнее? DOO>exec — замена одного процесса другим в том же адресном пространстве. Объекты ядра сохраняются.
Чуть уточню на будущее — и по fork не всё копируется (например, kqueues принципиально не копируются), и по exec те что имеют FD_CLOEXEC не копируются. Но в общем всё так.
DOO>Вот только что с потоками происходит не скажу...
При exec() новый бинарь запускается, конечно, с одним потоком.
При fork() в новом процессе остаётся только текущий поток. fork() с сохранением всех потоков если и возможен, то резко нестандартен.
DOO>Все претензии по поводу неосвобожденных ресурсов вообще мне непонятны... Смотри на exec как на abort как уже было сказано... Почему компилятор должен сам ставить какие-то костыли для работы того или иного системного вызова?
Ну причину вопроса я понимаю. Хочется вначале всё прочистить Впрочем, это можно и руками написать.
А тем более что в варианте fork+exec это делать просто НЕЛЬЗЯ — копии памяти с объектами в дочернем процессе попросту невалидны.
Кстати, по Posix есть (хоть и необязательна) posix_spawn().
Здравствуйте, MaximE, Вы писали:
ME>fork() + exec() и есть аналог CreateProcess. Все твои объекты остаются валидными в родительском процессе.
С той лишь разницей, что CreateProcess никого не убивает, а наоборот, создает новую жил площадь.
ME>Какая у тебя конкретно проблема?
Проблема в том, что мне не нравиться когда валидный процесс тупо убивается и на его "трупике" запускается новый квартирант.
Здравствуйте, Igor_G, Вы писали:
ME>>Какая у тебя конкретно проблема? I_G>Проблема в том, что мне не нравиться когда валидный процесс тупо убивается и на его "трупике" запускается новый квартирант.
Что ж... терпи. Здесь новые программы запускаются именно так.
Здравствуйте, Igor_G, Вы писали:
I_G>Здравствуйте, MaximE, Вы писали:
ME>>fork() + exec() и есть аналог CreateProcess. Все твои объекты остаются валидными в родительском процессе. I_G>С той лишь разницей, что CreateProcess никого не убивает, а наоборот, создает новую жил площадь.
fork() + exec() также никого не убивает. У тебя появляется новехонький процесс, процесс который вызвал fork также остается.
ME>>Какая у тебя конкретно проблема? I_G>Проблема в том, что мне не нравиться когда валидный процесс тупо убивается и на его "трупике" запускается новый квартирант.
Т.е. конкретно проблема в том, что тебе просто непривычно?
Здравствуйте, netch80, Вы писали:
ME>>>Какая у тебя конкретно проблема? I_G>>Проблема в том, что мне не нравиться когда валидный процесс тупо убивается и на его "трупике" запускается новый квартирант. N>Что ж... терпи. Здесь новые программы запускаются именно так.
Здравствуйте, MaximE, Вы писали:
ME>>>fork() + exec() и есть аналог CreateProcess. Все твои объекты остаются валидными в родительском процессе. I_G>>С той лишь разницей, что CreateProcess никого не убивает, а наоборот, создает новую жил площадь. ME>fork() + exec() также никого не убивает. У тебя появляется новехонький процесс, процесс который вызвал fork также остается.
После форка имеем родителя и ребенка, после exec ребенок здыхает, те убивается. Формально, да, никто никого не убивает, просто ребенок сам совершает харакири, что не есть естественно, ИМХО.
ME>>>Какая у тебя конкретно проблема? I_G>>Проблема в том, что мне не нравиться когда валидный процесс тупо убивается и на его "трупике" запускается новый квартирант.
ME>Т.е. конкретно проблема в том, что тебе просто непривычно?
Ну, типа да, бред в принципе должен быть непривычен, но, я так понял, что это unix way и ничего тут не поделаешь
Здравствуйте, DOOM, Вы писали:
I_G>>Ну, типа да, бред в принципе должен быть непривычен, но, я так понял, что это unix way и ничего тут не поделаешь DOO>Бред — это то, что в винде fork'а нету. То что тебя выдрессировали на подход MS это не есть проблема Unix way.
Форка много где нет, а если и есть то как бонус для имитации unix way DOO>Мои студенты ставят домой Linux и FreeBSD только для того, чтобы получить в перле полноценный fork. Так что...
Ну если _твои_ студенты ...
Здравствуйте, Igor_G, Вы писали:
I_G>После форка имеем родителя и ребенка, после exec ребенок здыхает, те убивается. Формально, да, никто никого не убивает, просто ребенок сам совершает харакири, что не есть естественно, ИМХО.
Ребенок не совершает себе харакири, он (точнее, ядро по вызову execve()) замещает содержимое своего адресного пространства данными и кодом из другого бинарика.
Кстати, в posix draft описан вызов vfork(), который блокирует родительский процесс, пока дочерний не вызовет execve(). Таким образом, уменьшаются накладные расходы на возможное копирование страниц при записи в них родителем. Но это пока еще не портабельно.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, ДимДимыч, Вы писали:
ДД>Кстати, в posix draft описан вызов vfork(), который блокирует родительский процесс, пока дочерний не вызовет execve(). Таким образом, уменьшаются накладные расходы на возможное копирование страниц при записи в них родителем. Но это пока еще не портабельно.
Если говорить о непортабельных средствах, то в Linux есть clone()там столько всего... не меньше чем в CreateProcess
Здравствуйте, DerBober, Вы писали:
DB>Если говорить о непортабельных средствах, то в Linux есть clone()там столько всего... не меньше чем в CreateProcess
Угу, даже Таненбаум его за clone() хвалил
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, Igor_G, Вы писали:
ME>>>>Какая у тебя конкретно проблема? I_G>>>Проблема в том, что мне не нравиться когда валидный процесс тупо убивается и на его "трупике" запускается новый квартирант.
Типичный код:
if (fork() == 0) {
exec( "" );
}
Если между fork() и exec() ни один объект (в терминах С++) не создастся и не уничтожится тогда проблем будет. Совершенно равносильно простому созданию процесса.
Если между их вызовами насоздавал объектов взаимодействующих с внешним миром то сам себе буратина.
Основная фича fork-exec как раз таки в возможности производить действия после fork но до exec. Порой это очень удобно. В винде такой возможности нет.
DB>Основная фича fork-exec как раз таки в возможности производить действия после fork но до exec. Порой это очень удобно. В винде такой возможности нет.
Поддерживая аналогию.
Это подготовка квартиры под нужды нового квартиранта. Причем силами выезжающего (а не убитого) квартиросъемщика.
Здравствуйте, ДимДимыч, Вы писали:
ДД>Здравствуйте, Igor_G, Вы писали:
I_G>>После форка имеем родителя и ребенка, после exec ребенок здыхает, те убивается. Формально, да, никто никого не убивает, просто ребенок сам совершает харакири, что не есть естественно, ИМХО.
ДД>Ребенок не совершает себе харакири, он (точнее, ядро по вызову execve()) замещает содержимое своего адресного пространства данными и кодом из другого бинарика. ДД>Кстати, в posix draft описан вызов vfork(), который блокирует родительский процесс, пока дочерний не вызовет execve(). Таким образом, уменьшаются накладные расходы на возможное копирование страниц при записи в них родителем. Но это пока еще не портабельно.
Не стоит пользовать vfork на современных системах.
Conforming applications are recommended not to depend on vfork(), but to use fork() instead. The vfork() function may be withdrawn in a future version.
man vfork
...
HISTORIC DESCRIPTION
Under Linux, fork() is implemented using copy-on-write pages, so the
only penalty incurred by fork() is the time and memory required to
duplicate the parent's page tables, and to create a unique task struc-
ture for the child. However, in the bad old days a fork() would
require making a complete copy of the caller's data space, often need-
lessly, since usually immediately afterwards an exec() is done. Thus,
for greater efficiency, BSD introduced the vfork() system call, that
did not fully copy the address space of the parent process, but bor-
rowed the parent's memory and thread of control until a call to
execve() or an exit occurred. The parent process was suspended while
the child was using its resources. The use of vfork() was tricky: for
example, not modifying data in the parent process depended on knowing
which variables are held in a register.
BUGS It is rather unfortunate that Linux revived this spectre from the past.
The BSD manpage states: "This system call will be eliminated when
proper system sharing mechanisms are implemented. Users should not
depend on the memory sharing semantics of vfork() as it will, in that
case, be made synonymous to fork()."
Formally speaking, the standard description given above does not allow
one to use vfork() since a following exec() might fail, and then what
happens is undefined.
Details of the signal handling are obscure and differ between systems.
The BSD manpage states: "To avoid a possible deadlock situation, pro-
cesses that are children in the middle of a vfork() are never sent
SIGTTOU or SIGTTIN signals; rather, output or ioctls are allowed and
input attempts result in an end-of-file indication."
Здравствуйте, MaximE, Вы писали:
ME>Здравствуйте, ДимДимыч, Вы писали:
ДД>>Кстати, в posix draft описан вызов vfork(), который блокирует родительский процесс, пока дочерний не вызовет execve(). Таким образом, уменьшаются накладные расходы на возможное копирование страниц при записи в них родителем. Но это пока еще не портабельно.
ME>Не стоит пользовать vfork на современных системах.
Иногда приходится. Не ради накладных, естественно. Семантика полноценного форка предполагает управление памятью. Если нет MMU, то (семантика) vfork — единственный выход из положения.
Здравствуйте, Igor_G, Вы писали:
DOO>>Мои студенты ставят домой Linux и FreeBSD только для того, чтобы получить в перле полноценный fork. Так что... I_G>Ну если _твои_ студенты ...
А что такого?
Я их перлу учу... Они у меня на занятиях под виндой сидят...
Конечно, иногда я вынужден объяснить, что та или иная некрасивая запись — это костыли, чтобы под виндой работало...
К тому же я MCSA... Так что не надо считать меня оголтелыим линуксоидом.
Здравствуйте, ДимДимыч, Вы писали:
ДД>Здравствуйте, vnp, Вы писали:
vnp>>Если нет MMU, то (семантика) vfork — единственный выход из положения.
ДД>Blackfin ?
vnp wrote:
> ДД>>Кстати, в posix draft описан вызов vfork(), который блокирует > родительский процесс, пока дочерний не вызовет execve(). Таким образом, > уменьшаются накладные расходы на возможное копирование страниц при > записи в них родителем. Но это пока еще не портабельно. > > ME>Не стоит пользовать vfork на современных системах. > > Иногда приходится. Не ради накладных, естественно. Семантика > полноценного форка предполагает управление памятью. Если нет MMU, то > (семантика) vfork — единственный выход из положения.