Основываясь на опубликованных функциях, я думаю, что в вашем коде есть две основные проблемы.
1. Вы закрываете дескрипторы файлов при каждом вызове обработчика сигналов.
Неплохая идея - закрыть дескрипторы файлов каждый раз после чтения или записи. Однонаправленные трубы не работают таким образом. После создания дескрипторов пары вы должны закрыть первый дескриптор в один процесс и второй в другом процессе. Это создаст трубу от первого процесса до второго (man pipe). В примере с man-страницы они закрывают дескриптор справа после записи, потому что они больше не нужны.
2. Похоже, у вас есть только 3 пары дескрипторов файлов.
Для подключения 3 процессов, с помощью однонаправленных труб (как показано на рисунке ниже), требует 6 пар дескрипторов:
fd 5,6
+------------+ +------------+
| |<----------| |
| process #0 | | process #1 |
| |---------->| |
+------------+ +------------+
| ^ fd 7,8 | ^
| | | |
fd 1,2 | | fd 3,4 fd 9,10 | | fd 11,12
| | | |
v | | |
+------------+ | |
| |<--------------+ |
| process #2 | |
| |-------------------+
+------------+
Пример.
Здесь приведен пример кода, который делает то же самое. Это далеко от хорошего примера (обработка плохих сигналов, printf
в обработчике сигналов), но я надеюсь, что это поможет немного.
int g_pfd[3][2][2]; // pairs of file desriptors.
volatile sig_atomic_t g_ignore_sighup = 0; // flag for ignoring SIGHUP
void (* g_handlers[3]) (int); // array of signal handlers
void sig_handler (int signo, int id)
{
if (signo == SIGHUP)
{
if (g_ignore_sighup)
{
g_ignore_sighup = 0;
return;
}
printf ("SIGHUP recvd, pid = %d\n", getpid());
int rd1 = (id);
int rd2 = (id == 0 ? 2 : id - 1);
// choose, which process sent SIGHUP.
fd_set rfds;
FD_ZERO (&rfds);
FD_SET (g_pfd[rd1][1][0], &rfds);
FD_SET (g_pfd[rd2][0][0], &rfds);
int rv = select (FD_SETSIZE, &rfds, NULL, NULL, NULL);
if (rv == -1)
{
perror ("select");
return;
}
else if (rv == 0)
{
return;
}
int fd = -1;
if (FD_ISSET (g_pfd[rd1][1][0], &rfds)) fd = g_pfd[rd1][1][0];
if (FD_ISSET (g_pfd[rd2][0][0], &rfds)) fd = g_pfd[rd2][0][0];
int i;
if (read (fd, &i, sizeof (int)) == -1)
{
perror ("read");
}
printf ("recvd data through pipe = %d\n", i);
return;
}
if (signo == SIGINT)
{
int wr1 = (id);
int wr2 = (id == 0 ? 2 : id - 1);
printf ("SIGINT recvd, pid = %d\n", getpid());
printf ("write: %d to %d\n", getpid(), g_pfd[wr1][0][1]);
printf ("write: %d to %d\n", getpid(), g_pfd[wr2][1][1]);
int pid = getpid();
if (write (g_pfd[wr1][0][1], &pid, sizeof (int)) == -1 ||
write (g_pfd[wr2][1][1], &pid, sizeof (int)) == -1)
{
perror ("write");
}
g_ignore_sighup = 1; // flag for ignorig own signal
// send SIGHUP to parent and all its children.
if (kill (0, SIGHUP) == -1)
{
perror ("kill");
}
return;
}
}
void sig_handler_0 (int signo) { sig_handler (signo, 0); }
void sig_handler_1 (int signo) { sig_handler (signo, 1); }
void sig_handler_2 (int signo) { sig_handler (signo, 2); }
int create_process (int *pid, int id)
{
*pid = fork();
if (*pid == -1)
{
perror ("fork");
return 1;
}
if (*pid != 0) // parent
{
return 0;
}
// close appropriate descriptors
int i1 = (id);
int i2 = (id == 0 ? 2 : id - 1);
close (g_pfd[i1][0][0]);
close (g_pfd[i2][0][1]);
close (g_pfd[i1][1][1]);
close (g_pfd[i2][1][0]);
if (signal (SIGINT, g_handlers[id]) == SIG_ERR ||
signal (SIGHUP, g_handlers[id]) == SIG_ERR)
{
perror ("signal");
return 1;
}
while (1) sleep (1);
exit (0);
}
int main (int argc, char *argv [])
{
// fill array of signal handlers.
g_handlers[0] = sig_handler_0;
g_handlers[1] = sig_handler_1;
g_handlers[2] = sig_handler_2;
if (signal (SIGHUP, SIG_IGN) == SIG_ERR)
{
perror ("signal");
return 1;
}
int pid [3];
int i, j;
// create pairs of descriptors
for (i = 0; i < 3; i++)
{
for (j = 0; j < 2; j++)
{
if (pipe (g_pfd[i][j]) == -1)
{
perror ("pipe");
return 1;
}
}
}
if (create_process (&pid[0], 0) != 0 ||
create_process (&pid[1], 1) != 0 ||
create_process (&pid[2], 2) != 0)
{
return 1;
}
sleep (1);
kill (pid[0], SIGINT); sleep (3);
kill (pid[1], SIGINT); sleep (3);
kill (pid[2], SIGINT);
wait (NULL);
for (i = 0; i < 3; i++)
{
for (j = 0; j < 2; j++)
{
close (g_pfd[i][j][0]);
close (g_pfd[i][j][1]);
}
}
return 0;
}
Спасибо за это, я надеюсь, что это сработает для меня. – manveruPL