Задача по программированию в *nix'ах

Задача по программированию в *nix'ах

20.02.2012 11:39:27 Просмотров 26 Источник

Коллеги! Еще одна забавная задача по программированию в Unix.

Вот такой код

#include <iostream>
#include <unistd.h>

int main() {
    std::cout << "HELLO  ";
    fork();
}

Что эта программа будет выводить и почему?

У вопроса есть решение - Посмотреть?

https://ru.stackoverflow.com/questions/82070/%d0%97%d0%b0%d0%b4%d0%b0%d1%87%d0%b0-%d0%bf%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8e-%d0%b2-nix%d0%b0%d1%85#comment82071_82070
хмм.. а что такое fork? :)
https://ru.stackoverflow.com/questions/82070/%d0%97%d0%b0%d0%b4%d0%b0%d1%87%d0%b0-%d0%bf%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8e-%d0%b2-nix%d0%b0%d1%85#comment82072_82070
@Crasher, если незнакомы с программированием в юникс, то гугль в помощь)))
https://ru.stackoverflow.com/questions/82070/%d0%97%d0%b0%d0%b4%d0%b0%d1%87%d0%b0-%d0%bf%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8e-%d0%b2-nix%d0%b0%d1%85#comment82098_82070
На самом деле, это задача не столько на запуск новых процессов (хотя и на это тоже), сколько на понимание механизма ввода-вывода в С++.

Ответы - Задача по программированию в *nix&#39;ах / Задача по программированию в *nix'ах

Руслан

20.02.2012 11:56:05

HELLO
processreturned 0 (0x0) execution time : 0.008 s
Press ENTER to continue.
HELLO
https://ru.stackoverflow.com/questions/82070/%d0%97%d0%b0%d0%b4%d0%b0%d1%87%d0%b0-%d0%bf%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8e-%d0%b2-nix%d0%b0%d1%85/82076#comment82078_82076
Дивненько. Программку Вы скомпилировали и даже запустили. А почему так?
https://ru.stackoverflow.com/questions/82070/%d0%97%d0%b0%d0%b4%d0%b0%d1%87%d0%b0-%d0%bf%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8e-%d0%b2-nix%d0%b0%d1%85/82076#comment82080_82076
Игорь,А вы хотели просто HELLO HELLO? Можно и так :)
https://ru.stackoverflow.com/questions/82070/%d0%97%d0%b0%d0%b4%d0%b0%d1%87%d0%b0-%d0%bf%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8e-%d0%b2-nix%d0%b0%d1%85/82076#comment82084_82076
Главное - объяснить, почему выводится 2 раза.
https://ru.stackoverflow.com/questions/82070/%d0%97%d0%b0%d0%b4%d0%b0%d1%87%d0%b0-%d0%bf%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8e-%d0%b2-nix%d0%b0%d1%85/82076#comment82100_82076
Вот, хотел написать, что 2 раза HELLO, но на Познера отвлекся и уже ответили. Реально вывод будет по write() из fflush() из exit() (неявного, по оконанию программы) в обоих процессах. Поэтому 2 раза.
https://ru.stackoverflow.com/questions/82070/%d0%97%d0%b0%d0%b4%d0%b0%d1%87%d0%b0-%d0%bf%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8e-%d0%b2-nix%d0%b0%d1%85/82076#comment82102_82076
@avp, чую, истина уже близко. Тут главное, конечно, объяснить почему. Напиши ответ и немного пояснее.
RomanoO

21.02.2012 12:06:16

Насколько я помню из QNX, fork() создает дочерний процесс. И еще, на сколько я помню, этой функции в качестве параметра передается адрес функции для нового процесса. В данном случае логично предположить, что он создает дочерний процесс с адресом вызывающей функции, этим дело и заканчивается, так как главный процесс закончился.

https://ru.stackoverflow.com/questions/82070/%d0%97%d0%b0%d0%b4%d0%b0%d1%87%d0%b0-%d0%bf%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8e-%d0%b2-nix%d0%b0%d1%85/82082#comment82083_82082
Тут следует учесть время запуска дочернего процесса. Если это время меньше выхода из главной программы, то в выводе мы увидим больше одного HELLO.
https://ru.stackoverflow.com/questions/82070/%d0%97%d0%b0%d0%b4%d0%b0%d1%87%d0%b0-%d0%bf%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8e-%d0%b2-nix%d0%b0%d1%85/82082#comment82087_82082
Ну, собсно, это я не стал писать :) По-моему, мало-мальски соображающий человек это додумает...
https://ru.stackoverflow.com/questions/82070/%d0%97%d0%b0%d0%b4%d0%b0%d1%87%d0%b0-%d0%bf%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8e-%d0%b2-nix%d0%b0%d1%85/82082#comment82089_82082
@RomanoO, не знаю, как в QNX, но согласно POSIX системный вызов fork() не получает никакого аргумента.
https://ru.stackoverflow.com/questions/82070/%d0%97%d0%b0%d0%b4%d0%b0%d1%87%d0%b0-%d0%bf%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8e-%d0%b2-nix%d0%b0%d1%85/82082#comment82091_82082
Ну я же написал, "на сколько помню". Давно это было. Нынче я на java и Android. Во всяком случае, даже если не в fork(), то в какую-то из связанных с этой темой функцию или структуру передается адрес функции для нового процесса.
https://ru.stackoverflow.com/questions/82070/%d0%97%d0%b0%d0%b4%d0%b0%d1%87%d0%b0-%d0%bf%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8e-%d0%b2-nix%d0%b0%d1%85/82082#comment82092_82082
Это Вы наверно с pthread_create спутали.
https://ru.stackoverflow.com/questions/82070/%d0%97%d0%b0%d0%b4%d0%b0%d1%87%d0%b0-%d0%bf%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8e-%d0%b2-nix%d0%b0%d1%85/82082#comment82093_82082
На самом деле, это задача не столько на запуск новых процессов (хотя и на них тоже), сколько на понимание механизма ввода-вывода в С++.
https://ru.stackoverflow.com/questions/82070/%d0%97%d0%b0%d0%b4%d0%b0%d1%87%d0%b0-%d0%bf%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8e-%d0%b2-nix%d0%b0%d1%85/82082#comment82097_82082
Скорее с clone(2)
https://ru.stackoverflow.com/questions/82070/%d0%97%d0%b0%d0%b4%d0%b0%d1%87%d0%b0-%d0%bf%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8e-%d0%b2-nix%d0%b0%d1%85/82082#comment82101_82082
Очень может быть...
Является ответом!
avp

21.02.2012 12:59:14

В c++ cout << , в C printf () выводят в stdout. Реально данные пишутся в буфер. Буфер выталкивается (системный вызов write()) на устройство для stdout и tty (консоль) по '\n', если конечно ранее принудительно не задавали другой тип буферизации (например unbuffered). IMHO функции setbuf(), setlinebuf() и т.п. см. man -k ...

А вот '\n'-то и нет !

В твоем примере сразу за записью в буфер идет fork(). Порождается новый процесс, все данные дублируются (ну, я не буду о pid, ppid и подобном), а вызов fork() возвращает свой результат в одну и ту же точку в обоих процессах. Далее процессы исполняют независимо друг от друга одну и ту же программу.

Естественно оба в конце концов (по окончании main) делают write(1,"HELLO ",7); т.е. выталкивают буфер на устройство. Точно не знаю, но думаю, что был вызов atexit(), в котором запланирован вызов функции fflush(), выталкивающей буфера по окончании main().

Насколько помню, чтобы избежать этого (похоронить данные в буферах) надо явно вызвать _exit().

IMHO понятно (в некоторых деталях мог ошибиться, пишу по памяти, да и *nix-ы м.б. разными).

Закрыть X