有名管道FIFO的使用

對於有名管道FIFO,它是半雙工的。類似於管道但是又不同於管道。它是一個單向數據流。更爲重要的是,每個FIFO有一個路徑名與之關聯,從而允許無親緣關係的進程訪問同一個FIFO。
管道只能用於有一個共同祖先進程的各個進程之間。
FIFO由mkfifo函數創建。
#include<sys/types.h>
#include<sys/stat.h>
int mkfifo(const char *pathname,mode_t mode);
使用兩個FIFO代替管道來編寫客戶—服務器的例子
#include<sys/stat.h>
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<fcntl.h>
#define FIFO1 "/tmp/fifo.1"
#define FIFO2 "/tmp/fifo.2"
#define FILE_MODE S_IFIFO|0666
#define MAXLINE 2000
void client(int ,int ),server(int,int);
 int main(int arg,char **argvc)
{
    int readfd,writefd;
    pid_t childpid;
    unlink(FIFO1);
    unlink(FIFO2);
    /*create two FIFO2;OK if they already exist*/
    if(mkfifo(FIFO1,FILE_MODE)<0)
    {
        printf("can't create %s\n",FIFO1);
        exit(1);
    }
    if(mkfifo(FIFO2,FILE_MODE)<0)
    {
        unlink(FIFO1);
        printf("cant't create %s\n",FIFO2);
        exit(1);
    }
    /*child*/
    if((childpid = fork())==0)
    {
        readfd = open(FIFO1,O_RDONLY,0);
        writefd = open(FIFO2,O_WRONLY,0);
        server(readfd,writefd);
        exit(0);
    }
    /*parent*/
    writefd = open(FIFO1,O_WRONLY,0);
    readfd= open(FIFO2,O_RDONLY,0);
    client(readfd,writefd);
    waitpid(childpid,NULL,0);
    close(readfd);
    close(writefd);
    unlink(FIFO1);
    unlink(FIFO2);
    exit(0);

}
void server(int readfd,int writefd)
{
    int fd;
    ssize_t n;
    char buff[MAXLINE+1];
    /*read pathname from IPC channel*/
    if((n = read(readfd,buff,MAXLINE))==0)
    {
        printf("It's an error,please exit");
        exit(1);
        }
    buff[n]='\0';               /*null terminate pathname*/
    if((fd = open(buff,O_RDONLY))<0)
    {
        /*error must tell client*/
        snprintf(buff + n,sizeof(buff) - n, ":can't open,%s\n",strerror(errno));
        n = strlen(buff);
        write(writefd,buff,n);
    }
    else
    {
        /*open succeed:copy file to IPC channel*/
        while((n = read(fd,buff,MAXLINE))>0)
        {
            write(writefd,buff,n);
            close(fd);
        }
    }
   
}

void client(int readfd,int writefd)
{
    size_t len;
    ssize_t n;
    char buff[MAXLINE];
    /*read pathname*/
    fgets(buff,MAXLINE,stdin);
    len = strlen(buff);/*fgets() guarantees null byte at end*/
    if(buff[len-1]=='\n')
        len--;   /*delete newline from fgets()*/
    /*write pathname to IPC channel*/
    write(writefd,buff,len);
    /*read from IPC,write to standard output*/
    while((n = read(readfd,buff,MAXLINE))>0)
        write(STDOUT_FILENO,buff,n);
   

}
(1)在這個函數中要注意前面兩個宏定義#define FIFO1 “/tmp/fifo.1”
                                                    #define FIFO2 "/tmp/fifo.2"

如果tmp前面少了/ 的話在程序運行過程中就不會找到tmp,運行完can't create fifo.1就會結束。
(2)還有在程序中使用的一些 宏定義的標識符
如:O_RDONLY、O_WRONLY都包含在頭文件 #include<fcntl.h>中
STDOUT_FILENO等文件描述符包含在#include<unistd.h>中;在unix系統調用中,標準輸入描述字用stdin,標準輸出用stdout,標準出錯用stderr表示,但在一些調用函數,引用了STDIN_FILENO表示標準輸入才,同樣,標準出入用STDOUT_FILENO,標準出錯用STDERR_FILENO.
他們的區別:
stdin等是FILE *類型,屬於標準I/O,在<stdio.h>。
STDIN_FILENO等是文件描述符,是非負整數,一般定義爲0, 1, 2,屬於沒有buffer的I/O,直接調用系統調用,在<unistd.h>。
size_t 包含在頭文件 #include<stdlib.h>
mkfifo()包含在頭文件#include<sys/stat.h>
#define FILE_MODE   S_IFIFO|0666  指名創建一個有名管道且權限爲0666.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章