[C++] Procesy potomne

Witam

Mam taki problem. Potrzebuje wykorzystać funkcję fork w programie ale jest mały problem.

Program ma działać tak:

  1. Podajemy z wiersza poleceń argumenty do programu (chodzi o pliki) - dużo ich będzie

  2. Następnie proces macierzysty wywołuje proces potomny ale tak żeby proces ten przetworzył tylko JEDEN z plików podanych jako argument. Później kolejny raz wywołuję i kolejny plik.

  3. Proces potomny ma zwracać wartość do programu macierzystego.

Jak wywołać proces potomny i rozróżnić do od macierzystego to wiem. Ale nie wiem jak powiedzieć programowi

“Ty, przetwórz pierwszy plik”

“A Ty teraz przetwórz drugi plik”

itd.

Ma ktoś jakiś pomysł?

Może coś takiego pomoże:

for (int i = 1; i < argc; ++i)

   {

      if (fork() == 0)

         {

            przetwarzaj(argv[i]);

            break; // (lub return) żeby potomek nie kręcił się w tej samej pętli co rodzic

         }

   }

EDIT: Ajj… nie doczytałem do punktu 3. Musisz nawiązać jakąś komunikację międzyprocesową, np. przez łącza nienazwane (man pipe).

http://www.yolinux.com/TUTORIALS/LinuxT … tml#BASICS

A jeżeli działasz pod windowsem, to to samo co wyżej i http://sourceware.org/pthreads-win32/

Niestety, na studiach mam wytyczne, ma być fork.

Już złapałem, fork wykonuje kopię programu ale od momentu utworzenia tego procesu

for(int i=0;i
{

    if (x == 0)

    {

        printf("[%u]: Proces potomny %d\n",getpid(),i);

        break;

    }

    x = fork();

}

Wynik programu

[marcinob@stud ~]$ ./a.out 8 8 8 8 8 8 8

[5824]: Proces potomny 1

[5825]: Proces potomny 2

[5826]: Proces potomny 3

[5827]: Proces potomny 4

[5828]: Proces potomny 5

[5829]: Proces potomny 6

[5830]: Proces potomny 7

czyli w pierwszym przebiegu pętli kiedy i=0 tworzony jest proces potomny i dopiero od 1 przetwarzam . Jak widać pętla nie idzie od nowa (bo myślałem że tak jest) więc jestem w domu :wink:

Dodane 23.06.2010 (Śr) 17:30

A teraz mam pytanie co do wartości zwracanej przez proces potomny, jak ?

Jeśli rezultatem procesu potomnego ma być liczba całkowita, to wystarczy funkcja wait/waitpid (przez status). W przeciwnym wypadku potrzeba będzie nawiązać komunikację (najprościej na pipe’ach).

W procesie potomnym przetwarzam paragony z pliku, proces potomny przetworzył przykładowo 125 paragonów i teraz mam zwrócić ilość paragonów które przetworzył do procesu macierzystego. Proces macierzysty ma wyświetlić to ile paragonów przetworzył proces potomny.

Próbowałem z waitpid(proces, stat, 0) i w zmiennej stat nie mam ilości paragonów. Próbowałem return ilosc, exit(ilosc) ale zawsze jakieś śmieci tam mam.

jeśli stat zadeklarowałeś przez

int stat;

, to powinno wyglądać tak:

waitpid(pid, &stat, 0);

, gdyż waitpid/wait potrzebuje wskaźnika do inta.

BTW: Możesz użyć funkcji wait zamiast waitpid - w końcu i tak ją wywołasz tyle samo razy, a nie musisz zapamiętywać pidów procesów potomnych.

I tak mam. Zauważyłem że zwraca mi wartość

tyle_co_ja_chce*256

http://linux.die.net/man/2/waitpid stoi, że powinieneś użyć flagi WEXITED w przypadku waitpid. wait natomiast zawsze informuje tylko o zakończonym procesie.

Aaa… musisz użyć makra WEXITSTATUS(stat), żeby dobrać się do kodu powrotu.

Mam dla ciebie coś takiego i myśle, że po drobnych przeróbkach to rozwikła twój problem:

#include 

#include 

#include 

#include 

#include 

#include 

#include 


using namespace std;


int main(int argc, char *argv[])

{


for(int i = 1; i < argc; i++)

{

        pid_t potomek = fork();


        if(potomek == 0)

        {

               cout << "Tworze proces potomny dla parametru: " << argv[i] << endl;

               //w tym miejscu kod wykonany bedzie tylko przez jeden nowo stworzony wątek wiec uruchamiasz funkcję która odpala kolejny plik z parametru


               exit(0); //Wczesniej pobierz w procesie maciezystym przez getpid() jego pid i tutaj zwracaj. 

        }

}


for(int i = 1; i < argc; i++)

{

        wait(0);

}


}

Pisałem to na szybko więc mógł gdzieś wkraść się błąd ale myślę że będzie dobrze. Oczywiście tam trzeba dopisać pobieranie pid z procesu macierzystego i wykonywanie kolejnych plików podanych w parametrze w miejscu które oznaczyłem komentarzem. Polecam program skompilować i przetestować np z 3 parametrami (ala ma kota). Do kompilacji używałem g++

Zadanie już dawno wykonane.

Największy problem był ze zwracaniem wartości, wykorzystywałem waitpid ale dostawałem jakieś kosmiczne liczby, po przeanalizowaniu okazało się że wartość zwracana jest o 256 razy większa. Wystarczyło podzielić i wyszło.

:lol: … Ten kod chyba nie jest zbyt przenośny, co? Próbowałeś tego na BSD / Mac OS X / Solarisie? Przecież napisałem, żebyś użył WEXITSTATUS(stat). Oto kwałek :

# define WEXITSTATUS(status)	__WEXITSTATUS (__WAIT_INT (status))

__WEXITSTATUS znajduje się w

/* If WIFEXITED(STATUS), the low-order 8 bits of the status. */

#define	__WEXITSTATUS(status)	(((status) & 0xff00) >> 8)

Tak akurat się złożyło i możesz polegać jedynie na tym, że ten szczegół implementacyjny nie ulegnie w najbliższym czasie zmianie. Poza tym, waitpid powróci nawet w przypadku, kiedy proces potomny został wstrzymany lub wznowiony przez system, dlatego trzeba zrobić coś takiego:

if WIFEXITED(stat) /* proces się zakończył */

{

   kod_powrotu = WEXITSTATUS(status);

}

else /* fałszywy alarm */

{

}