[Ansi C/Linux] Obsługa I/O w procesach potomnych

0

Witam,

Mam następująco postawione zadanie: aplikacja tworzy 3 procesy potomne i kończy swój aktualny proces, następnie pierwszy proces pobiera dane ze standardowego wejścia, przekazuje je do drugiego, który dokonuje pewnych operacji na tych danych i przekazuje je do trzeciego procesu, który wypisuje dane na standardowe wyjście (stdout, bez sztuczek z stderr). Aplikacja w C, pod system operacyjny Debian Linux.

Moim głównym problemem jest odziedziczenie uchwytów I/O. W momencie, gdy kończy się proces macierzysty, tracę te uchwyty.

Udało mi się osiągnąć stan, w którym proces macierzysty zakończył się, 3 procesy pozostają w pamięci i działają, jednak już nie potrafię ich zmusić, do pracy ze standardowymi strumieniami.

Proszę o jakąś wskazówkę

0

Na czym dokładnie polega problem ze „współpracą ze standardowymi strumieniami ”?
Jak tworzysz nowe procesy?
W jaki sposób wykonujesz operacje wejścia-wyjścia? (Spróbuj tylko przez read/write bezpośrednio do deskryptora, bez żadnych bibliotek, być może mogą one deinicjalizować swoje struktury i nawet zamykać deskryptory przy końcu głównego wątku.)

0

Dzięki za szybką odpowiedź. :)

Problem polega na niemożliwości odziedziczenia tych deskryptorów stdin i stdout w procesach potomnych.
Nowe procesy tworzę poprzez funkcję fork(). Zdaję sobie sprawę, że procesy potomne mają kopie deskryptorów, jednak co sie dzieje, gdy kończy się proces macierzysty?
Operacje wejścia-wyjścia próbowałem poprzez scanf(...), printf(...), fscanf(stdin,...), fprintf(stdout, ...).

0

Co sie dzieje? Procesy potomne dalej sa w posiadaniu kopi deskryptorow. Maly przyklad z ksiazki "UNIX programowanie uslug sieciowowych". Stworzymy prosty serwer czasu dobowego jako proces daeamon, i za kazdym polaczeniem bedziemy wyswietlac cos na stdout.

void daemon_init2(const char* pname, int facility) 
{
        int i;
        pid_t pid;
        if( (pid = Fork()) != 0 )
                exit(0);

        setsid();
        Signal(SIGHUP, SIG_IGN);
        if( (pid = Fork()) != 0)
                exit(0);
        chdir("/");
        umask(0);
}

int
main(int argc, char **argv)
{
        int                             listenfd, connfd;
        socklen_t               addrlen, len;
        struct sockaddr *cliaddr;
        char                    buff[MAXLINE];
        time_t                  ticks;

        daemon_init2(argv[0], 0);

        if (argc == 2)
                listenfd = Tcp_listen(NULL, argv[1], &addrlen);
        else if (argc == 3)
                listenfd = Tcp_listen(argv[1], argv[2], &addrlen);
        else
                err_quit("usage: daytimetcpsrv2 [ <host> ] <service or port>");

        cliaddr = Malloc(addrlen);

        for ( ; ; ) {
                len = addrlen;
                connfd = Accept(listenfd, cliaddr, &len);
                err_msg("connection from %s", Sock_ntop(cliaddr, len));

        ticks = time(NULL);
        snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
        Write(connfd, buff, strlen(buff));

                Close(connfd);
                printf("nanannananan");
        }
}

Wiem ze nie tworzysz w swoim programie daemonow ale mysle ze przyklad warty uwagi.

0

Rozgryzłem to. Musiałem się mocno w czoło uderzyć. ;)

stdin i stdout są strumieniami buforowanymi, więc żeby wypisać coś na wyjście, trzeba wywołać jeszcze fflush(stdout) (lub to co chcemy wypisać zakończyć '\n'). I to wszystko! fork() stworzył dokładne kopie procesów, z wszystkimi deskryptorami, więc problem rozwiązany. Działają zarówno wysokopoziomowe scanf'y i printf'y jak i read, write.

Dzięki za poświęcony czas! :)

0

mogłbyś mi powiedzieć jak przekazujesz jakieś dane z 1 procesu potomnego, do 2 procesu potomnego ?

0

Istnieje wiele metod. Łącza nazwane i nienazwane, pamięć dzielona i po prostu pliki. Dodatkowo należy wykorzystać jakąś metodę synchronizacji tych wątków: sygnały, komunikaty, semafory, mutexy.

1 użytkowników online, w tym zalogowanych: 0, gości: 1