2010-05-30 71 views
2

我寫了兩個程序:第一個是「writer」,它創建一個FIFO並將數據寫入其中。第二個,「讀者」在後臺運行並在FIFO中查找數據。一旦有數據,讀者就會讀出來。UNIX FIFO:如何僅允許一個寫入器/讀取器對使用FIFO?

如果我開始例如兩個編寫者和兩個讀者,他們都可以寫入/讀入/來自同一個FIFO。如何限制第三和第四個讀寫器使用FIFO,並且只允許一個寫入器和一個讀取器使用FIFO?

回答

1

使用pipe(2)創建FIFO,並且僅當FIFO從父進程派生出來時,纔將FIFO的每一端的文件描述符提供給適當的進程。 (或者,讓讀者呼叫pipe(2)並分配作者,反之亦然。)由於FIFO永遠不會存在於文件系統中,所以其他任何進程都無法訪問它。

如果您必須使用已命名的FIFO,請在讀取器和寫入器打開後刪除FIFO。只要閱讀器和書寫器將其打開,底層的FIFO仍然存在,但沒有新的進程能夠打開它。但是,在刪除它之前,會有另一個讀寫器可能會打開FIFO的競爭狀況。

+0

非常感謝你們,保羅!它看起來像它的作品。 我必須使用命名管道(FIFO),所以我只是添加一個刪除(「namedpipe」);在讀者程序中的write()語句後面。 現在,如果我啓動2個作者和2個閱讀器,只有1個作者可以編寫,只有1個閱讀器可以閱讀。 – 2010-05-30 15:45:21

+0

大聲笑,有時它的作品,有時不,不知道爲什麼... – 2010-05-30 16:25:03

+0

@ Max Krug:定義「不工作」。 – 2010-05-30 16:53:11

0

FIFO編劇:

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

#define BUFFERSIZE 50 
#define CHMOD 0777 



int main(int argc, char **argv)  
{ 
    char outbuf[BUFFERSIZE]; // outbuffer 
    int fifo, j, anzahl; 
    // fifo - pipe file deskriptor, j - counter, anzahl - Parameter. 

    if(argc!=2)    // Check if parameter is ok 
    {        
     printf("Ungültiger Parameter! Bsp.: ./fifow 10\n"); 
     return 1; 
    } 

    anzahl=atoi(argv[1]);  // convert paramter to integer 


    mkfifo("namedpipe4", CHMOD);   // make FIFO "namedpipe4" 
    fifo = open("namedpipe4",O_WRONLY);  // open FIFO 
    // 
    for(j=0;j<anzahl;j++) 
    { 

     printf("Writer PID: %d writes record nr. %6d\n", getpid(), j+1); 
     sprintf(outbuf, "Writer PID: %d writes record nr. %6d\n", getpid(), j+1); 
     write(fifo, outbuf, BUFFERSIZE);  
     remove("namedpipe4"); // removing the fifo 
     sleep(1);    // Wait 1 sec 
    } 

    close(fifo); // 

    exit(0); 

} 

FIFO讀者:

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

#define BUFFERSIZE 50 

int main(void)  
{ 

    char inbuf[BUFFERSIZE]; // inbuffer 
    int fifo, var; 

    printf("\n Waiting for a Pipe....\n"); 

    while((fifo = open("namedpipe4",O_RDONLY)) == -1) // while "there is no such pipe" 
    { 
    remove("namedpipe4"); 
    sleep(1); 
    }  


    while((var = read(fifo, inbuf, BUFFERSIZE)) > 0) // while "i can read" 
    {  
    printf("Reader PID: %d reads record: %s\n", getpid(), inbuf); 
    sleep(1); 
    } 



    close(fifo);  // 

    printf("\n EOF..\n"); 

    exit(0); 


} 
+0

爲了將來的參考,您可以隨時在發佈後編輯您的問題(而不是發佈更新作爲您的問題的答案,這是各種語義差的問題) – jasonmp85 2010-05-31 10:40:24

4

鑑於the code you posted in a separate answer,這裏是一個修改版本,修復您遇到的問題。詳情請參閱評論:

  • 編寫程序檢查返回值mkfifo以檢查是否有另一個寫入程序已經創建了管道。
  • 打開讀卡器後,讀卡器會通過flock獲取專用諮詢鎖,以避免第二個讀卡器在第一個讀卡器刪除之前打開管道的競爭狀況。

編劇:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/stat.h> /* needed for mkfifo */ 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <fcntl.h> 

#define BUFFERSIZE 50 
#define CHMOD 0777 

int 
main (int argc, char **argv)  
{ 
    char outbuf[BUFFERSIZE]; 
    int fifo, j, anzahl; 

    if (argc != 2) 
    {        
     printf("Ungültiger Parameter! Bsp.: ./fifow 10\n"); 
     return 1; 
    } 

    anzahl=atoi(argv[1]); 

    /* mkfifo fails if the file already exists, which means there's a 
    * writer waiting for a reader. This assures that only one writer 
    * will write to the pipe, since it only opens the pipe if it was 
    * the one who created it. 
    */ 
    if (mkfifo("namedpipe4", CHMOD) == -1) 
    { 
     printf("namedpipe4 already exists\n"); 
     return 1; 
    } 

    fifo = open("namedpipe4", O_WRONLY); 

    for (j = 0; j < anzahl; j++) 
    { 
     printf("Writer PID: %d writes record nr. %6d\n", getpid(), j + 1); 
     sprintf(outbuf, "Writer PID: %d writes record nr. %6d\n", getpid(), j + 1); 
     write(fifo, outbuf, BUFFERSIZE);  
     remove("namedpipe4"); 
     sleep(1); 
    } 

    close(fifo); 

    exit(0); 
} 

讀者:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/file.h> /* for flock */ 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <fcntl.h> 

#define BUFFERSIZE 50 

int 
main (int argc, char **argv)  
{ 
    char inbuf[BUFFERSIZE]; 
    int fifo, var; 

    printf("\n Waiting for a Pipe....\n"); 

    /* There are *two* ways the open can fail: the pipe doesn't exist 
    * yet, *or* it succeeded, but a different writer already opened 
    * it but didn't yet remove it. 
    */ 
    while (1) 
    { 
     while ((fifo = open("namedpipe4", O_RDONLY)) == -1) 
     { 
      /* Since you didn't specify O_CREAT in the call to open, there 
      * is no way that namedpipe4 would have been created by the 
      * reader. If there *is* now a namedpipe4, a remove here 
      * would delete the one the writer created! 
      */ 
      sleep(1); 
     }  

     /* Get an exclusive lock on the file, failing if we can't get 
     * it immediately. Only one reader will succeed. 
     */ 
     if (flock (fifo, LOCK_EX | LOCK_NB) == 0) 
      break; 

     /* We lost the race to another reader. Give up and wait for 
     * the next writer. 
     */ 
     close (fifo); 
    } 

    /* We are definitely the only reader. 
    */ 

    /* *Here* we delete the pipe, now that we've locked it and thus 
    * know that we "own" the pipe. If we delete before locking, 
    * there's a race where after we opened the pipe, a different 
    * reader also opened, deleted, and locked the file, and a new 
    * writer created a new pipe; in that case, we'd be deleting the 
    * wrong pipe. 
    */ 
    remove("namedpipe4"); 

    while ((var = read(fifo, inbuf, BUFFERSIZE)) > 0) 
    {  
     printf("Reader PID: %d reads record: %s\n", getpid(), inbuf); 
     /* No need to sleep; we'll consume input as it becomes 
     * available. 
     */ 
    } 

    close(fifo); 
    printf("\n EOF..\n"); 
    exit(0); 
}