2013-07-21 2 views
0

Я изучаю linux fifos, и я сделал две небольшие программы на C, которые общаются через fifo. Первый работает как сервер, получает шаблон и выполняет команду с использованием этого шаблона. Второй действует как клиент, он отправляет шаблон и получает результат. Я хочу, чтобы сервер был способен обслуживать несколько запросов, не обязательно одновременно, но странно, что после того, как первый клиент обслуживается, он просто останавливается, хотя я помещаю туда бесконечный цикл.Странное поведение fifos на linux

server.c

#include <sys/types.h> 
#include <sys/stat.h> 
#include <string.h> 
#include <signal.h> 
#include <fcntl.h> 


void siginthandler(int i){ 
    remove("./fifo1"); 
    remove("./fifo2"); 
    printf("Got SIGINT signal\n"); 
    exit(EXIT_SUCCESS); 
} 


int main(int argc, char *argv[]){ 
    signal(SIGINT, siginthandler); 
    int f = mkfifo("./fifo1", 0600); 
    if (f == -1){ 
     perror("Unable to create fifo1\n"); 
     exit(EXIT_FAILURE); 
    } 
    f = mkfifo("./fifo2", 0600); 
    if (f == -1){ 
     perror("Unable to create fifo2\n"); 
     exit(EXIT_FAILURE); 
    } 
    int fd1 = open("./fifo1", O_RDONLY); 
    int fd2 = open("./fifo2", O_WRONLY); 
    if (fd1 == -1 || fd2 == -1){ 
     perror("Unable to open fifos\n"); 
     exit(EXIT_FAILURE); 
    } 
    while (1){ 
     char buf[50]; 
     char pattern[50]; 
     read(fd1, pattern, 50); 
     char command[80] = "ps -e | grep "; 
     strcat(command, pattern); 
     FILE *result = popen(command, "r"); 
     while (fgets(buf, 50, result)){ 
      write(fd2, buf, 50); 
      //printf("%s", buf); 
     } 
     memset((void *) buf, 0, 50); 
     write(fd2, buf, 50); 
     pclose(result); 
    } 
    remove("./fifo1"); 
    remove("./fifo2"); 
    return 0; 
} 

client.c

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

int main(int argc, char *argv[]){ 
    int fd1 = open("./fifo1", O_WRONLY); 
    int fd2 = open("./fifo2", O_RDONLY); 
    if ((fd1 == -1) || (fd2 == -1)){ 
     perror("Unable to find fifos"); 
     exit(EXIT_FAILURE); 
    } 
    char input[50]; 
    printf("Give pattern: "); 
    scanf("%s", input); 
    write(fd1, input, 50); 
    char buf[50]; 
    while (read(fd2, buf, 50) == 50){ 
     if (buf[0] == 0){ 
      break; 
     } 
     printf("%s", buf); 
    } 
    return 0; 
} 

ответ

3

Когда первый клиент закрывает FIFO, сервер получает EOF в FIFO и продолжает получать новые данные неограниченно. Сервер должен снова открыть FIFO для следующего клиента. Если бы одновременно было несколько клиентов с одновременным открытием FIFO, сервер не получал EOF до тех пор, пока последний из клиентов не будет отключен (пока есть один писатель, читатель - сервер - будет в порядке).

Ожидаемое поведение - или, поскольку вы не ожидали этого, это поведение, которое следует ожидать.

Конечно, поскольку ваш код полностью игнорирует возвращаемое значение от read(), вы понятия не имеете, что, если что-либо читается.

Код:

memset((void *) buf, 0, 50); 
write(fd2, buf, 50); 

Любопытно; почему вы отправляете клиенту буфер с 50 0 байтами? Вы вполне можете закрыть FIFO, не отправив это.

Также обратите внимание, что запись на FIFO, где нет считывателя, будет генерировать сигнал SIGPIPE - и вы не обрабатываете их. Действие по умолчанию для SIGPIPE - выход.

+0

Я учил, что была проблема с последним куском данных, поэтому я поставил там memset. Спасибо за помощь! – Jelly

3

Запись в трубе получает вас SIGPIPE если нет читатель; вам нужно, чтобы сервер открыл канал для чтения, поэтому есть читатель (который ничего не читает, но он существует).

 Смежные вопросы

  • Нет связанных вопросов^_^