Почему моя труба в C не работает? - PullRequest
3 голосов
/ 16 июня 2011

в качестве упражнения мне нужно использовать обработчик сигнала и каналы для отправки некоторых сообщений между двумя процессами при получении сигнала.Ниже мой исходный код.Когда я запускаю его, я могу заставить каналы работать, оба процесса могут общаться, пока я вызываю канал в их main-методе (в данном случае process1 () и process2 ()).Но я хочу использовать каналы внутри обработчиков сигналов.Но сейчас трубы не работают.Вот некоторые результаты, которые я получил:

3 - 4 and 5 - 6
Segv at 8825
USR1 at 8824
898 sent to 4
130 received on 3
130

'898' и '130' должны быть равны, но это не так.Я знаю, что каналы работают правильно, поэтому я думаю, что это как-то связано с сигнальными устройствами ... Но что ...?

Исходный код:

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

int fd1[2], fd2[2], status;
int cpid, cpoid;

void process1() {   
    cpid = getpid();        /*What's my process ID?*/
    cpoid = cpid + 1;       /*And what's the other process ID?*/

    close(fd1[0]);
    close(fd2[1]);

    while (1) {}
}

void process2() {   
    cpid = getpid();
    cpoid = cpid - 1;

    close(fd1[1]);
    close(fd2[0]);

    raise(SIGSEGV);         /*Start with a SegV signal*/

    while (1) {}
}

/*Method to send a message to the other process, by pipe*/
void send (int msg) {
    if (cpid < cpoid) {
        write(fd1[1], &msg, 1);
        printf("%d sent to %d\n", msg, fd1[1]);
    } else {
        write(fd2[1], &msg, 1);
        printf("%d sent to %d\n", msg, fd2[1]);
    }
}

/*Method to receive a message from the other process*/
int receive () {
    int msg = 0;
    if (cpid < cpoid) {
        read(fd2[0], &msg, 1);
        printf("%d received on %d\n", msg, fd2[0]);
    } else {
        read(fd1[0], &msg, 1);
        printf("%d received on %d\n", msg, fd1[0]);
    }
    return msg;
}

/*The SegV Signal handler*/
void segvHandler() {
    int y = -1;
    printf("Segv at %d\n", cpid);
    kill(cpoid, SIGUSR1);           /*Send an USR1 Signal to the other proces*/

    while (y != 898) {
        y = receive();
        printf("%d\n", y);
    }
}

/*The Usr1 Signal handler*/
void usr1Handler() {
    int x = 898;
    printf("USR1 at %d\n", cpid);

    send(x);
}

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

    if (pipe(fd1) < 0) {
        fprintf (stderr, "Could not make pipe\n");
        return (EXIT_FAILURE);
    }
    if (pipe(fd2) < 0) {
        fprintf (stderr, "Could not make pipe\n");
        return (EXIT_FAILURE);
    }
    printf("%d - %d and %d - %d\n", fd1[0], fd1[1], fd2[0], fd2[1]);    /*Pipe numbers*/

    signal(SIGUSR1, usr1Handler);   /*Signal handlers*/
    signal(SIGSEGV, segvHandler);

    if (fork() != 0) {
        process1();
    } else {
        process2();
    }
    waitpid(-1, &status, 0);

    return EXIT_SUCCESS;
}

Ответы [ 2 ]

3 голосов
/ 16 июня 2011

Некоторые ошибки основаны на быстром просмотре.

  • printf () не является безопасным для асинхронного сигнала; не вызывайте его в обработчике сигналов.

  • Вы читаете и пишете 1 байт, что, скорее всего, меньше, чем sizeof (int).

  • Вы не можете предполагать, что PID являются последовательными. В родителе возвращаемое значение fork () дает PID дочернего элемента. В дочернем элементе, если родительский файл хранил возвращаемое значение getpid () перед fork (), он у вас есть; в противном случае смотрите getppid ().

2 голосов
/ 16 июня 2011

Как уже упоминалось в комментариях, вы не должны вызовите printf в обработчике сигналов, но это, вероятно, не проблема. Если целые числа не являются одним байтом на вашем компьютере, проблема заключается в том, что вы не пишете или не читаете целое int, поскольку вы записываете только один байт в канал. (Измените код на: write (fd [1], & msg, sizeof msg) и внесите те же изменения в чтение.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...