2010-05-30 58 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); 
}