Здравствуйте.Начал мутить демона. Сам в linux'e работал только в качестве SysAdmin'a. Решил попробывать свои силы в programming'е. В ДОС'e в свое время программил на C/C++ :)
Вообщем САБЖ.
[cut]
...
pid_t pid = fork();
int i = kill(pid, SIG_HUP);
...
[cut]
А когда пишу что делать при сигнале HUP вызываю action(); (к примеру)...
void action(void)
{
while (1) { ...
};
}
...Интересует правильно ли я делаю fork(); и kill(...) ?
И вообще надо ли kill делать.Первый раз пишу что-то для linux'a связвнное с процессами...
Подскажите что и как plz.Заранее спасибо за ответ. Всего доброго.
Если у тебя так и написано:
...
pid_t pid = fork();
int i = kill(pid, SIG_HUP);
...то потомок пытается хапнуть процесс с пидом 0. У меня такого нет :))
Вызов fork создает точную копия процесса со значениями данных на момент вызова и возвращает 0 потомку, -1 в случае ошибки и пид потомка родителю. Далее процессы работают независимо друг.
Надо что-то типа:
pid_t pid = fork();
if (pid == 0) {
// потомок
...
} else if (pid == -1) {
// ошибка
...
} else {
// родитель
...
};Удобнее через switch.
Что значит, "правильно ли я делаю kill(...)" ? Я бы сказал, что он тебе нафиг не нужен. Кто-то другой сказал бы, что без него никак. А вообще зависит от поставленной задачи.
>Если у тебя так и написано:
>...
>pid_t pid = fork();
>int i = kill(pid, SIG_HUP);
Я просто не помню какой именно сигнал (номер), но сигнал HANGUP (или как его там)
>...
>
>то потомок пытается хапнуть процесс с пидом 0. У меня такого нет
>:))
>Вызов fork создает точную копия процесса со значениями данных на момент вызова
>и возвращает 0 потомку, -1 в случае ошибки и пид потомка
>родителю. Далее процессы работают независимо друг.
>Надо что-то типа:
>pid_t pid = fork();
>if (pid == 0) {
> // потомок
> ...
сдесь код потомка???? Правильно ли я понял?
>} else if (pid == -1) {
> // ошибка
> ...
>} else {
> // родитель
> ...
а сдесь уже код родителя. Или нет?
>};
>
>Удобнее через switch.
>
>Что значит, "правильно ли я делаю kill(...)" ? Я бы сказал, что
>он тебе нафиг не нужен. Кто-то другой сказал бы, что без
>него никак. А вообще зависит от поставленной задачи.Но как мне завершить родителя, что-бы потомок работал?
>>Если у тебя так и написано:
>>...
>>pid_t pid = fork();
>>int i = kill(pid, SIG_HUP);
>Я просто не помню какой именно сигнал (номер), но сигнал HANGUP (или
>как его там)
>>...
>>
>>то потомок пытается хапнуть процесс с пидом 0. У меня такого нет
>>:))
>>Вызов fork создает точную копия процесса со значениями данных на момент вызова
>>и возвращает 0 потомку, -1 в случае ошибки и пид потомка
>>родителю. Далее процессы работают независимо друг.
>>Надо что-то типа:
>>pid_t pid = fork();Вот здесь (если все прошло нормально) ты уже имеешь два процесса. Мне кажется ты не понял, что порожденный процесс как и родительский будет продолжать выполнение кода именно с ЭТОГО места. Но поскольку форк выдает обоим процессам разные коды возврата, то есть возможность определить является ли процесс родительским или копией (что код приведенный ниже и делает)
>>if (pid == 0) {
>> // потомок
>> ...
> сдесь код потомка???? Правильно ли я понял?
>>} else if (pid == -1) {
>> // ошибка
>> ...
>>} else {
>> // родитель
>> ...
> а сдесь уже код родителя. Или нет?Этот код будет присутствовать и в порожденном процессе, просто он никогда не выполнится - сюда зайдет только родитель. Так что делаешь здесь exit(0) (естественно предварительно освобождение выделенной памяти итд) и родительский процесс нормально завершается (ну а порожденный понятное дело продолжает крутиться)
>>};
>>
>>Удобнее через switch.
>>
>>Что значит, "правильно ли я делаю kill(...)" ? Я бы сказал, что
>>он тебе нафиг не нужен. Кто-то другой сказал бы, что без
>>него никак. А вообще зависит от поставленной задачи.
>
>Но как мне завершить родителя, что-бы потомок работал?
Кстати, о динамической памяти. В двух словах, что происходит в коде:int main()
{
char *c=(char *)malloc(1024);
switch(fork()) {
case -1:
case 0: free(c); exit(0);
};
wait(NULL);
free(c);
return 0;
}В частности, почему без ошибок освобождается память и в потомке и в родителе - адрес-то один и тот же. Система Linux 2.4.9
>Кстати, о динамической памяти. В двух словах, что происходит в коде:
>
>int main()
>{
> char *c=(char *)malloc(1024);
> switch(fork()) {
> case -1:
> case 0: free(c); exit(0);
> };
> wait(NULL);
> free(c);
> return 0;
>}
>
>В частности, почему без ошибок освобождается память и в потомке и в
>родителе - адрес-то один и тот же. Система Linux 2.4.9А хрен его знает (не настолько я подноготную *кса еще знаю), но ради интереса попробуй в родителе не просто екзит сделать, а что нибудь в эту память записать и проверить запись в потомке.
Если она не совпадет с тем, что записал родитель, тогда уж надо думать как такое ухитрились сделать (но не сейчас - не под пиво) - в любом случае дебагер тебя спасет :).
В провивном случае - если информация совпадает - станет ясно, что порожденный процесс пользуется данными родительского (вернее имеет разделяемую с ним память - форк насколько я помню по ману гарантирует полное соответствие данных в процессах только в момент вызова, но точно утерждать сейчас не берусь). Думаю понятно, что маллок, на самом деле, выделяет память не только под данные, но и под служебную информацию о выделеннной памяти, так что форку в этй информации ничего не стоит какой-нибудь счетчик на 1 увеличить (ну что ради дочернего процесса не сделаешь :). Фрии (как и все остальное, что работает с памятью ) общается с этими блокам информации. При каждом нормальном вызове эта/это самая/самое фрии делает счетчику -1, когда счетчик=0, тогда ДЕЙСТВИТЕЛЬНО память освобождается.
ЗЫ не забудь, что это тольк сказка - а то я сам себе почти поверил, пока все это написал Ж)
Наверное потому, что это линейный адрес один и тот же, а физический очень даже и разный. (После первого free полагаю).
>>>Если у тебя так и написано:
>>>...
>>>pid_t pid = fork();
>>>int i = kill(pid, SIG_HUP);
>>Я просто не помню какой именно сигнал (номер), но сигнал HANGUP (или
>>как его там)
>>>...
>>>
>>>то потомок пытается хапнуть процесс с пидом 0. У меня такого нет
>>>:))
>>>Вызов fork создает точную копия процесса со значениями данных на момент вызова
>>>и возвращает 0 потомку, -1 в случае ошибки и пид потомка
>>>родителю. Далее процессы работают независимо друг.
>>>Надо что-то типа:
>>>pid_t pid = fork();
>
>Вот здесь (если все прошло нормально) ты уже имеешь два процесса. Мне
>кажется ты не понял, что порожденный процесс как и родительский будет
>продолжать выполнение кода именно с ЭТОГО места. Но поскольку форк выдает
>обоим процессам разные коды возврата, то есть возможность определить является ли
>процесс родительским или копией (что код приведенный ниже и делает)
>
>>>if (pid == 0) {
>>> // потомок
>>> ...
>> сдесь код потомка???? Правильно ли я понял?
>>>} else if (pid == -1) {
>>> // ошибка
>>> ...
>>>} else {
>>> // родитель
>>> ...
>> а сдесь уже код родителя. Или нет?
>
>Этот код будет присутствовать и в порожденном процессе, просто он никогда не
>выполнится - сюда зайдет только родитель. Так что делаешь здесь exit(0)
>(естественно предварительно освобождение выделенной памяти итд) и родительский процесс нормально завершается
>(ну а порожденный понятное дело продолжает крутиться)
>
>>>};
>>>
>>>Удобнее через switch.
>>>
>>>Что значит, "правильно ли я делаю kill(...)" ? Я бы сказал, что
>>>он тебе нафиг не нужен. Кто-то другой сказал бы, что без
>>>него никак. А вообще зависит от поставленной задачи.
>>
>>Но как мне завершить родителя, что-бы потомок работал?Попробую сегодня разобраться... Если что напишу :) Спасибо.
>>>>Если у тебя так и написано:
>>>>...
>>>>pid_t pid = fork();
>>>>int i = kill(pid, SIG_HUP);
>>>Я просто не помню какой именно сигнал (номер), но сигнал HANGUP (или
>>>как его там)
>>>>...
>>>>
>>>>то потомок пытается хапнуть процесс с пидом 0. У меня такого нет
>>>>:))
>>>>Вызов fork создает точную копия процесса со значениями данных на момент вызова
>>>>и возвращает 0 потомку, -1 в случае ошибки и пид потомка
>>>>родителю. Далее процессы работают независимо друг.
>>>>Надо что-то типа:
>>>>pid_t pid = fork();
>>
>>Вот здесь (если все прошло нормально) ты уже имеешь два процесса. Мне
>>кажется ты не понял, что порожденный процесс как и родительский будет
>>продолжать выполнение кода именно с ЭТОГО места. Но поскольку форк выдает
>>обоим процессам разные коды возврата, то есть возможность определить является ли
>>процесс родительским или копией (что код приведенный ниже и делает)
>>
>>>>if (pid == 0) {
>>>> // потомок
>>>> ...
>>> сдесь код потомка???? Правильно ли я понял?
>>>>} else if (pid == -1) {
>>>> // ошибка
>>>> ...
>>>>} else {
>>>> // родитель
>>>> ...
>>> а сдесь уже код родителя. Или нет?
>>
>>Этот код будет присутствовать и в порожденном процессе, просто он никогда не
>>выполнится - сюда зайдет только родитель. Так что делаешь здесь exit(0)
>>(естественно предварительно освобождение выделенной памяти итд) и родительский процесс нормально завершается
>>(ну а порожденный понятное дело продолжает крутиться)
>>
>>>>};
>>>>
>>>>Удобнее через switch.
>>>>
>>>>Что значит, "правильно ли я делаю kill(...)" ? Я бы сказал, что
>>>>он тебе нафиг не нужен. Кто-то другой сказал бы, что без
>>>>него никак. А вообще зависит от поставленной задачи.
>>>
>>>Но как мне завершить родителя, что-бы потомок работал?
>
>Попробую сегодня разобраться... Если что напишу :) Спасибо.бЛИН, проблема осталась. Не могу прибить родителя. (если делаю exit(...), потомок умирает нахрен, вместе с родителем).
Цикл работы потомка (который у меня и есть сам демон) я запихал сюда:
if (pid == 0) { DeamonAction(); }
Я правильно понял?
>Но как мне завершить родителя, что-бы потомок работал?Чегото я не понял если ты пишешь демон то зачем его убивать.
По поводу fork(), как мне думаеться он создает совершенно разные процессы, т.е. память тоже дублируеться, поэтому и корректно освобождееться память и у родителя и у потомка.
>>Но как мне завершить родителя, что-бы потомок работал?
>
>Чегото я не понял если ты пишешь демон то зачем его убивать.
>Убивается только родительский процесс - за ненадобностью, а порожденный остается крутиться. Если не сделать форк, то при выходе из шелла (из которого ты демона запускал) он убьет все дочернии процессы, в том числе и твоего демона (или ты собираешься демона запустить и после этого никогда logout не делать - консолей на таких демонов не напасешься :). Порожденный же форком процесс не имеет родителя и поэтому будет продолжать работать и после закрыти шелла.
>По поводу fork(), как мне думаеться он создает совершенно разные процессы, т.е.
>память тоже дублируеться, поэтому и корректно освобождееться память и у родителя
>и у потомка.
>Убивается только родительский процесс - за ненадобностью, а порожденный остается крутиться. Если
>не сделать форк, то при выходе из шелла (из которого ты
>демона запускал) он убьет все дочернии процессы, в том числе и
>твоего демона (или ты собираешься демона запустить и после этого никогда
>logout не делать - консолей на таких демонов не напасешься :).
>Порожденный же форком процесс не имеет родителя и поэтому будет продолжать
>работать и после закрыти шелла.
Тогда могу посоветовать после вызова fork(),в потомке делать вызов exec(),
который собственно и будет запускать твой деман.
>>Убивается только родительский процесс - за ненадобностью, а порожденный остается крутиться. Если
>>не сделать форк, то при выходе из шелла (из которого ты
>>демона запускал) он убьет все дочернии процессы, в том числе и
>>твоего демона (или ты собираешься демона запустить и после этого никогда
>>logout не делать - консолей на таких демонов не напасешься :).
>>Порожденный же форком процесс не имеет родителя и поэтому будет продолжать
>>работать и после закрыти шелла.
>Тогда могу посоветовать после вызова fork(),в потомке делать вызов exec(),
>который собственно и будет запускать твой деман.
>порожденный процесс и есть демон - ничего больше запускать не надо.
man fork.
>порожденный процесс и есть демон - ничего больше запускать не надо.Чтобы kill убиал shell? но не трогал твой деман, в теле демана(в начале) вызови ситемную функцию setpgrp(), после этого вроде shell должен умирать нормально(не трогая твоего демана)
>Чтобы kill убиал shell? но не трогал твой деман, в теле демана(в
>начале) вызови ситемную функцию setpgrp(), после этого вроде shell должен умирать
>нормально(не трогая твоего демана)Что-то я окончательно перестал понимать что ты делаешь, деман делает fork() для того,чтобы запустить то что обработает запрос, но зачем при запуске демона делать fork(),неясно,т.к. shell делат это при запуске демона.
>>Чтобы kill убиал shell? но не трогал твой деман, в теле демана(в
>>начале) вызови ситемную функцию setpgrp(), после этого вроде shell должен умирать
>>нормально(не трогая твоего демана)
>
>Что-то я окончательно перестал понимать что ты делаешь, деман делает fork() для
>того,чтобы запустить то что обработает запрос, но зачем при запуске демона
>делать fork(),неясно,т.к. shell делат это при запуске демона.
бЛИН, проблема осталась. Не могу прибить родителя. (если делаю exit(...), потомок умирает нахрен, вместе с родителем).Цикл работы потомка (который у меня и есть сам демон) я запихал сюда:
if (pid == 0) { DeamonAction(); }
Я правильно понял?
Попробуй так if (pid == 0) { setpgrp(); DeamonAction();}
>Попробуй так if (pid == 0) { setpgrp(); DeamonAction();}а потом прибить родителя простым return'ом ? Или я опять туплю... :)
>>Попробуй так if (pid == 0) { setpgrp(); DeamonAction();}
>
>а потом прибить родителя простым return'ом ? Или я опять туплю... :)
>
ДА.
>>>Попробуй так if (pid == 0) { setpgrp(); DeamonAction();}
>>
>>а потом прибить родителя простым return'ом ? Или я опять туплю... :)
>>
>ДА.Попробую... Спасиба... Если что напишу ;))))
Короче почитай man по setprgp() и setsid();
Еще есть хорошая книга Операционная Ситсема UNIX (Андрей Робачевский)
Он кажеться есть на этом сервере в электронном виде.
>Короче почитай man по setprgp() и setsid();
>Еще есть хорошая книга Операционная Ситсема UNIX (Андрей Робачевский)
>Он кажеться есть на этом сервере в электронном виде.
man'ы читал, но несовсем все понятно просто. Вродебы должно работать - а нет... Сегодня посмотрю, надеюсь все заработает как надо. :)
>>Чтобы kill убиал shell? но не трогал твой деман, в теле демана(в
>>начале) вызови ситемную функцию setpgrp(), после этого вроде shell должен умирать
>>нормально(не трогая твоего демана)
>
>Что-то я окончательно перестал понимать что ты делаешь, деман делает fork() для
>того,чтобы запустить то что обработает запрос, но зачем при запуске демона
>делать fork(),неясно,т.к. shell делат это при запуске демона.Может я окончательно запутался в процессах? Х/З. А как мне тогда отправить себя в фон. К примеру такого плана прога:
...
int main(int argc, char **agrv)
{
for (int i=0;i<=9999;i++) {
...
}return 0;
}
И как мне себя в фон отослать? Естественно не ./myprogram& .Грубо говоря демоном стать без форка? Я вообще деманом вот так становлюсь (теперь уже :) после того как более менее с вашей помощью разобрался):
...
int main(...)
{
...
pid_t pid = fork();
if (pid == 0) {
setpgrp(); // с этим еще не проверял :)
for (...) {
...;
}
if (...) {
fprintf(stdout, "Error.");
return -1;
}
...
return 0;
}
Я понял что принцип таков.И вообще насколько я понимаю демон это и есть процесс порожденный от родителя.
Могу и ошибаться. Может опять че напутал. Не ругайте сильно, очень хочется разобраться...
>И вообще насколько я понимаю демон это и есть процесс порожденный от
>родителя.Демон - это процесс, не имеющий управляющего терминала. Был тут хороший совет - читать Робачевского. Там все вполне понятно описано.
>>И вообще насколько я понимаю демон это и есть процесс порожденный от
>>родителя.
>
>Демон - это процесс, не имеющий управляющего терминала.
Это понятно. Я имею ввиду в моем случае демоном и будет потомок, т.к. родитель двинет кони. Или я совсем уже запутался?
>>>И вообще насколько я понимаю демон это и есть процесс порожденный от
>>>родителя.
>>
>>Демон - это процесс, не имеющий управляющего терминала.
>Это понятно. Я имею ввиду в моем случае демоном и будет потомок,
>т.к. родитель двинет кони. Или я совсем уже запутался?Да. Вот еще примерчик посмотри: http://www.opennet.me/openforum/vsluhforumID9/613.html
>>>>И вообще насколько я понимаю демон это и есть процесс порожденный от
>>>>родителя.
>>>
>>>Демон - это процесс, не имеющий управляющего терминала.
>>Это понятно. Я имею ввиду в моем случае демоном и будет потомок,
>>т.к. родитель двинет кони. Или я совсем уже запутался?
>
>Да. Вот еще примерчик посмотри:
^^^ - Всмысле Да? Совсем запутался? :))))>http://www.opennet.me/openforum/vsluhforumID9/613.html
Спасибо, уже видел. По нему впринципе и разбирался, но понял все довольно поверхностно, именно по этому и написал в форум :)
>>>>>И вообще насколько я понимаю демон это и есть процесс порожденный от
>>>>>родителя.
>>>>
>>>>Демон - это процесс, не имеющий управляющего терминала.
>>>Это понятно. Я имею ввиду в моем случае демоном и будет потомок,
>>>т.к. родитель двинет кони. Или я совсем уже запутался?
>>
>>Да. Вот еще примерчик посмотри:
> ^^^ - Всмысле Да? Совсем запутался? :))))
>В смысле - правильно (это не ты запутался, а я неоднозначно ответил :)
>>http://www.opennet.me/openforum/vsluhforumID9/613.html
>
>Спасибо, уже видел. По нему впринципе и разбирался, но понял все довольно
>поверхностно, именно по этому и написал в форум :)
>В смысле - правильно (это не ты запутался, а я неоднозначно ответил
>:)Ok. Сегодня дома помаслаю все как следует и скажу результаты. Хоть немного разобрался, за что и спасибо.
>Здравствуйте.
>
>Начал мутить демона. Сам в linux'e работал только в качестве SysAdmin'a. Решил
>попробывать свои силы в programming'е. В ДОС'e в свое время программил
>на C/C++ :)
>
>Вообщем САБЖ.
>
>[cut]
> ...
> pid_t pid = fork();
> int i = kill(pid, SIG_HUP);
> ...
>[cut]
> А когда пишу что делать при сигнале HUP вызываю action(); (к
>примеру)
>
>...
>
>void action(void)
>{
> while (1) { ...
> };
>}
>...
>
>Интересует правильно ли я делаю fork(); и kill(...) ?
>И вообще надо ли kill делать.
>
>Первый раз пишу что-то для linux'a связвнное с процессами...
>Подскажите что и как plz.
>
>Заранее спасибо за ответ. Всего доброго.
Я не до конца прочел тред... Вобщем я всегда делаю так и всегда работает:if (fork()) return;
Далее код.
И все.
>>Здравствуйте.
>>
>>Начал мутить демона. Сам в linux'e работал только в качестве SysAdmin'a. Решил
>>попробывать свои силы в programming'е. В ДОС'e в свое время программил
>>на C/C++ :)
>>
>>Вообщем САБЖ.
>>
>>[cut]
>> ...
>> pid_t pid = fork();
>> int i = kill(pid, SIG_HUP);
>> ...
>>[cut]
>> А когда пишу что делать при сигнале HUP вызываю action(); (к
>>примеру)
>>
>>...
>>
>>void action(void)
>>{
>> while (1) { ...
>> };
>>}
>>...
>>
>>Интересует правильно ли я делаю fork(); и kill(...) ?
>>И вообще надо ли kill делать.
>>
>>Первый раз пишу что-то для linux'a связвнное с процессами...
>>Подскажите что и как plz.
>>
>>Заранее спасибо за ответ. Всего доброго.
>
>
>Я не до конца прочел тред... Вобщем я всегда делаю
>так и всегда работает:
>
>if (fork()) return;а что он в этом случае вернет ? fork() > 0 ? Правильно?
>
>Далее код.
Код потомка?
>
>И все.Кстати попробывал вчера. Все ок. Получился такой вот код:
#include <...>
void DeamonAction(void)
{
while(1) {
...;
}
}void SetSignals()
{
...
}int main(int argc, char **argv)
{
pid_t ppid;
SetSignals();ppid = fork();
if (ppid == 0) {
DeamonAction();
exit(0);
}
if (ppid > 0) {
fprintf(stdout, "Deamon created\n\n");
return 0;
}
if (ppid < 0) {
fprintf(stderr, "Error: can't create deamon\n\n");
return -1;
}return 0;
}Вот-так. Все работает :)
Если что не правильно или некрасиво Ж) поправте.Всем спасибо за советы.
>int main(int argc, char **argv)
>{
> pid_t ppid;
> SetSignals();
>
> ppid = fork();
> if (ppid == 0) {
> DeamonAction();
> exit(0);
> }
> if (ppid > 0) {
> fprintf(stdout, "Deamon created\n\n");
> return 0;
> }
> if (ppid < 0) {
> fprintf(stderr, "Error: can't create deamon\n\n");
> return -1;
> }
>
> return 0;
>}
>
>Вот-так. Все работает :)
>Если что не правильно или некрасиво Ж) поправте.
>
Тут для демана надо еще одно доброе дело сделать, это закрыть дискрипторы унаследованные от родительского процесса(он их от shell'а унаследовал), в том числе может быть закрыть стандартные фаилы ввода вывода (STDIN,STDOUT,STDERR).
Вопрос после смерти родителя твой демон не превращаеться в зомби ???
Посмотреть можно чем-нибудь вроде ps -Af, на против демана не должно быть надписей в стиле <defunct>.
Функция setpgrp(pid,pid), где pid-pid твоего процесса делает твоего демана лидером вновь созданной группы => не восприимчевым к сигнала посылаемым shell'ом при смерти.Но лучше использовать setsid().
Вызов функции setsid() (работает для UNIX system 5)создает новую ссесию, и процесс отделяеться от родительского.
>>int main(int argc, char **argv)
>>{
>> pid_t ppid;
>> SetSignals();
>>
>> ppid = fork();
>> if (ppid == 0) {
>> DeamonAction();
>> exit(0);
>> }
>> if (ppid > 0) {
>> fprintf(stdout, "Deamon created\n\n");
>> return 0;
>> }
>> if (ppid < 0) {
>> fprintf(stderr, "Error: can't create deamon\n\n");
>> return -1;
>> }
>>
>> return 0;
>>}
>>
>>Вот-так. Все работает :)
>>Если что не правильно или некрасиво Ж) поправте.
>>
> Тут для демана надо еще одно доброе дело сделать, это закрыть
>дискрипторы унаследованные от родительского процесса(он их от shell'а унаследовал), в том
>числе может быть закрыть стандартные фаилы ввода вывода (STDIN,STDOUT,STDERR).
>Вопрос после смерти родителя твой демон не превращаеться в зомби ???
>Посмотреть можно чем-нибудь вроде ps -Af, на против демана не должно быть надписей в стиле <defunct>.
>Функция setpgrp(pid,pid), где pid-pid твоего процесса делает твоего демана лидером вновь созданной группы => не восприимчевым к сигнала посылаемым shell'ом при смерти.Но лучше использовать setsid().
>Вызов функции setsid() (работает для UNIX system 5)создает новую ссесию, и процесс
>отделяеться от родительского.Спасиба, приму к сведению.