Problem z łączami nazwanymi(fifo)

0

Jestem w trakcie pisanie programu na Systemy Operacyjne. Dodam, że muszę to robić na linuxie w C.
Więc.... Program d1 po otrzymaniu sygnału powinien zapisać w łączu nazwanym wiadomość i wysłać inny sygnał do programu d2. Gdy d2 otrzyma sygnał powinien odczytać wiadomość i jeśli odczytana wiadomość jest równa czemuś konkretnemu ma np. wyświetlić jakiś komunikat. Problem polega na tym, że coś jest nie tak w programie d1, tak jakby po otwarciu łącza nic się dalej nie dzieje.
Z góry dziękuję za jakiekolwiek wskazówki.

Program d1:

 #include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
void fun(int siq)
{
	int fh,n=2;
	char *fifo = "/tmp/fifo";
	char tab[n];
	tab[0]='1';

	mkfifo(fifo, 0666);
	if((fh = open(fifo, O_WRONLY))<0)
	{
		printf("Blad\n");
		exit(1);
	}
	write(fh, tab, n);
	close(fh);

	system("killall -SIGUSR1 d2");
}

int main()
{
	while(1)
	{
	signal(SIGINT,fun);
	}
	return 0;
}

Program d2:

 #include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>

void fun(int sig)
{
	int fh,n=2;
	char *fifo = "/tmp/fifo";
	char tab[n];
	int i;


	if((fh = open(fifo, O_RDONLY))<0)
	{
		printf("Blad\n");
		exit(1);
	}
	read(fh, tab, n);
	close(fh);

	if( tab[0]=='1') printf("jest rowne\n");
	else printf("nie jest rowne\n");

	unlink(jawny);
}


int main()
{
	while(1)
	{
	signal(SIGUSR1, fun);
	}
	return 0;
}

Oba programy są wywoływane w programie inicjującym przez execlp() w procesach utworzonych funkcją fork().

0

Jeżeli one działają równolegle to nie lepiej pipe pipe fork. i zpętlić w select? To tak na szybko bo może ma kolega wymóg użycia sygnałów ;-)

Pierwszy błąd jaki widze to że nie sprawdza kolega czy write wszystko napisało. podobnie ze sprawdzeniem czy read odcztało wszystko. odsyłam do man 2 read i man 2 write. Poza tym brak obsługi błędów. Chce kolega używac sygnałów i nawet nie sprawdza EINTR (może programów jest więcej które mogą wysłać sygnał?)

tab[1] jest niezinicjalizowane.

Pzdr.

0

man 7 fifo
(...)
The kernel maintains exactly one pipe object for each FIFO special file that is opened by at least one process. The FIFO must be opened on both ends (reading and writing) before data can be >passed. Normally, opening the FIFO blocks until the other end is opened also.

A process can open a FIFO in nonblocking mode. In this case, opening for read only will succeed even if no-one has opened on the write side yet, opening for write only will fail with ENXIO (no >such device or address) unless the other end has already been opened.
(...)

Więcej tu. https://linux.die.net/man/7/fifo

A że najlepiej użyć select lub poll czy sigaction zamiast signal to inna sprawa. W nowych kernelach masz też signalfd, to w ogóle fajna sprawa, ale czysto linuxowa, nie POSIXowa...

I headerów Ci brakuje, skompiluj -Wall to zobaczysz jakich.

0

Generalnie to ja dopiero się uczę, na zajęciach robiliśmy przy użyciu signal.
Czym są headery?

0

Wszystkie potrzebne "headery" już są, ale nadal coś jest nie tak.
W sytuacji gdy nie ma sygnałów (chodzi o to, że w ogóle w programie ich nie, program działa na zasadzie wywołania funkcji) programy działają poprawnie, lecz jak już dochodzą sygnały pojawia się błąd otwarcia łącza w d1. Zmieniłam O_WRONLY i O_RDONLY na O_RDWR i dosłownie 3 razy zadziałało, a potem znów wrócił błąd.

0

Zasadniczo to co Kolega już wyżej wspomniał praktycznie zawsze lepsze jest sigaction a nie signal i podobnie z kill sigqueue.
To raz. Dwa jak używasz bardzo wiele sygnałów to radzę dowiedzieć się co to są sygnały które mogą być tylko pojedyńcze w kolejce a które mogą się że tak ustawić w grupie. (nigdy nie pamiętam poprawnej nazwy).

To jeszcze zapytam Czy ten program co jest wyżej wklejony to wszystko ? Jak nie to wklej coś więcej plis.

0

Jest jeszcze program inicjujący. Zaczęło działać po dodaniu mkfifo(fifo, 0666) w drugim programie. Choć wcześniej tak próbowałam i nie działało, teraz działa. Linux ma humory najwyraźniej. Nie wnikam w to jak na razie. Dzięki wszystkim za pomoc :)

0

Jak masz błędy z sygnałami a bez nie, to sprawdzaj errno==EINTR. Albo w ogóle sprawdzaj errno, to jest dość pożyteczna zmienna ;)

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