[SOLVED][C] Program wykorzystujący sygnały i funkcję fork().

Bash, C, C++, Java, PHP, Ruby, GTK, Qt i wiele innych - wszystko tutaj.
Awatar użytkownika
arialis111
Piegowaty Guziec
Piegowaty Guziec
Posty: 23
Rejestracja: 17 lis 2005, 19:20
Płeć: Mężczyzna
Wersja Ubuntu: 10.10
Środowisko graficzne: GNOME
Architektura: x86_64
Kontakt:

[SOLVED][C] Program wykorzystujący sygnały i funkcję fork().

Post autor: arialis111 »

Witam, stanąłem przed zadaniem napisania prostego programu, którego celem jest utworzenie dwóch procesów potomnych, pierwszy z nich ma wysyłać do rodzica SIGUSR1 co sekundę, drugi zaś SIGUSR2 co trzy sekundy. Program ma działać przez czas określony za pomocą argumentu, gdy czas ten minie rodzic ma wysłać SIGTERM do swoich potomków i wypisać ile każdy z nich wysłał sygnałów. Poniżej dołączam kod:

Kod: Zaznacz cały

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>

int ile_1;
int ile_2;

void blokuj()
{
	sigset_t iset;
	sigemptyset(&iset);
	sigaddset(&iset, SIGINT); //dodanie ctrl+c do zestawu iset
	sigaddset(&iset, SIGTSTP); //dodanie ctrl+z do zestawu iset
	sigprocmask(SIG_BLOCK, &iset, NULL); //blokowanie zestawu sygnałów iset, dodatkowo nie przechowuje
					     //informacji o poprzednim zestawie (NULL)
}

void funkcjapotomka2(int nrsig, siginfo_t *info, void *ucontext_t)
{
	
	printf("Rodzic odebral sygnal SIGUSR2 o nr: %d od procesu: %d\n", info->si_signo, info->si_pid);
	ile_2++;
}

void funkcjapotomka(int nrsig, siginfo_t *info, void *ucontext_t)
{
	
	printf("Rodzic odebral sygnal SIGUSR1 o nr: %d od procesu: %d\n", info->si_signo, info->si_pid); 
	ile_1++;
	
}
int main (int argc, char *argv[])
{
	struct sigaction dlapierwszego;
	struct sigaction dladrugiego;

	pid_t main, pid1, pid2;

	int czas;
	
	czas = atoi(argv[1]);

	main = getpid();

	pid1=fork();
	
	if(pid1==0)
	{
			while(1)
			{
				sleep(1);
				kill(main,  SIGUSR1); //wyslanie sygnalu
			}
	}
	
	else
	{
		dlapierwszego.sa_flags = SA_SIGINFO;
		dlapierwszego.sa_sigaction = (void *) funkcjapotomka;
		sigaction(SIGUSR1, &dlapierwszego, NULL);
		
		pid2=fork();
		
		if(pid2==0)
		{
			
			while(1)
			{
				sleep(3);
				kill(main, SIGUSR2);
			}
		}
		else 
		{
			dladrugiego.sa_flags = SA_SIGINFO;
			dladrugiego.sa_sigaction = (void *) funkcjapotomka2;
			sigaction(SIGUSR2, &dladrugiego, NULL);
		}
	}
	
	while(czas)
	{
		sleep(1);
		czas--;
		if (czas == 0)
		{
			kill(SIGTERM, pid1);
			kill(SIGTERM, pid2);
			sleep(2);
			printf("Jestem procesem o id: %d | wyslalem %d sygnalow\n", (int)pid1, ile_1);
			printf("Jestem procesem o id: %d | wyslalem %d sygnalow\n", (int)pid2, ile_2);
		}
	}

	return 0;
}
I teraz pytanie, co jest nie tak, że dostaję wynik 8 oraz 2, gdzie wynikiem spodziewanym byłoby przynajmniej 9 oraz 3?

------------------------------------

Zauważyłem że zamiast czekać sekundę - sleep(1) - w pętli while należy użyć funkcji pause(), która usypia proces na czas dostarczenia sygnału. Jednak wynik nadal nie jest satysfakcjonujący (8:3).


-----------------------------------
Poprawiona wersja:

Kod: Zaznacz cały

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

int pid1, pid2;
int ilosc = 0;
int flag1 =1;
int flag2 =1;

struct sigaction dlapierwszego, dladrugiego, dlatrzeciego;

void blokuj()
{
	sigset_t iset;
	sigemptyset(&iset);
	sigaddset(&iset, SIGTSTP);
	sigaddset(&iset, SIGINT);
	sigprocmask(SIG_SETMASK, &iset, NULL);
}

void odbierz(int signum, siginfo_t *info)
{
	if(signum == SIGUSR1) printf("Rodzic odebrał sygnal SIGUSR1 od procesu: %d\n",info->si_pid);
	else if(signum == SIGUSR2) printf("Rodzic odebrał sygnal SIGUSR2 od procesu: %d\n",info->si_pid);
}

void obslugaterm(int signum, siginfo_t *info)
{
	if(signum == SIGTERM) 
	{
		printf("\nPotomek o id: %d, wyslal: %d sygnalow\n",getpid(),ilosc);
		flag1=0;
		flag2=0;
	}	
}

int main(int argc, char **argv)
{
	dlapierwszego.sa_flags = SA_SIGINFO;
	dlapierwszego.sa_sigaction = (void (*)(int, siginfo_t*, void*)) odbierz;
	sigaction(SIGUSR1, &dlapierwszego, NULL );
	sigaction(SIGUSR2, &dlapierwszego, NULL );
	blokuj();
	
	pid1 = fork();
	if(!pid1)
	{
		blokuj();
		dladrugiego.sa_flags = SA_SIGINFO;
		dladrugiego.sa_sigaction = (void (*)(int, siginfo_t*, void*)) obslugaterm;
		sigaction(SIGTERM, &dladrugiego, NULL );
		
		while(flag1)
		{
			kill(getppid(), SIGUSR1);
			ilosc++;
			sleep(1);
		}
		exit(0);	
	}
	
	pid2 = fork();
	if(!pid2)
	{
		blokuj();
		dlatrzeciego.sa_flags = SA_SIGINFO;
		dlatrzeciego.sa_sigaction = (void (*)(int, siginfo_t*, void*)) obslugaterm;
		sigaction(SIGTERM, &dlatrzeciego, NULL );
		
		while(flag2)
		{
			kill(getppid(), SIGUSR2);
			ilosc++;
			sleep(3);
		}
		exit(0);
	}
	
	int czas = atoi(argv[1]);
	
	while(czas)
	{
		sleep(1);
		czas--;
	}
	
	kill(pid1, SIGTERM);
	kill(pid2, SIGTERM);
	
	int i;

	for(i = 0; i < 2; i ++)
		wait(NULL);
}
ODPOWIEDZ

Wróć do „Programowanie”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 1 gość