2013-07-21 34 views
0

我正在學習linux fifo,並且製作了兩個通過fifo進行通信的小型C程序。第一個就像一個服務器,它接收一個模式並使用該模式執行一個命令。第二個就像一個客戶端,它發送模式並接收結果。我希望服務器能夠處理多個請求,但不一定是同時發生的,但奇怪的是,在服務第一個客戶端之後,它只是停止,儘管我在那裏放置了一個無限循環。在Linux上fifos的奇怪行爲

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時,服務器在FIFO上獲取EOF,並且永久不會獲得新數據。服務器必須重新打開下一個客戶端的FIFO。如果有多個客戶端同時打開FIFO,則在最後一個客戶端斷開連接之前(只要有一個寫入程序,讀取程序 - 服務程序 - 將會正常),服務器將不會收到EOF。

這是預期的行爲 - 或者,因爲您沒有預料到它是應該預期的行爲。

當然,由於您的代碼完全忽略來自read()的返回值,因此您不知道正在讀取什麼內容(如果有的話)。

的代碼:

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

是好奇;你爲什麼要發送一個50 0字節的緩衝區給客戶端?您可以在不發送該信息的情況下完全關閉FIFO。

另請注意,如果在沒有閱讀器的情況下在FIFO上書寫,將會生成一個SIGPIPE信號 - 而且您沒有處理這些信號。 SIGPIPE的默認操作是退出。

+0

我教過最後一塊數據有問題,這就是爲什麼我把那個memset放在那裏的原因。謝謝您的幫助! – Jelly

3

寫入到一個管道讓你一個SIGPIPE如果沒有讀者;你需要讓服務器打開閱讀管道,所以有一個閱讀器(它不讀取任何內容,但它存在)。