Mam taki problem. Potrzebuje wykorzystać funkcję fork w programie ale jest mały problem.
Program ma działać tak:
Podajemy z wiersza poleceń argumenty do programu (chodzi o pliki) - dużo ich będzie
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.
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
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).
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
– 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.
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++
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 :
/* 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 */
{
}