進程間通信之管道和FIFO

管道

管道是進程通信的手段之一,管道實際上只存在內存的文件,對這個文件的操作是通過兩個打開的文件描述符,
它們分別代表管道的兩端,管道是一種特殊的文件,它不屬於某種文件系統,它是獨立文件系統,有自己的數據結構,
按照適用範圍:分爲無名管道和有名管道。

無名管道
特點:1)半雙工,數據只能在一個方向上流動。
      2)只能在具有血緣關係的進程間使用。

#include<unistd.h>
int pipe(int fd[2]);
成功-- 0,出錯-- -1

fd  參數:返回的是文件描述符,fd[0] 讀端,fd[1]寫端。

1.如果所有指向管道寫端的文件描述符都關閉了(管道寫端的引用計數等於0),而仍
然有進程從管道的讀端讀數據,那麼管道中剩餘的數據都被讀取後,再次read會返回0,就
像讀到文件末尾一樣。
2.如果有指向管道寫端的文件描述符沒關閉(管道寫端的引用計數大於0),而持有管
道寫端的進程也沒有向管道中寫數據,這時有進程從管道讀端讀數據,那麼管道中剩餘的數
據都被讀取後,再次read會阻塞,直到管道中有數據可讀了纔讀取數據並返回。
3.如果所有指向管道讀端的文件描述符都關閉了(管道讀端的引用計數等於0),這時
有進程向管道的寫端write,那麼該進程會收到信號SIGPIPE,通常會導致進程異常終止。講
信號時會講到怎樣使SIGPIPE信號不終止進程。
4.如果有指向管道讀端的文件描述符沒關閉(管道讀端的引用計數大於0),而持有管
道讀端的進程也沒有從管道中讀數據,這時有進程向管道寫端寫數據,那麼在管道被寫滿時
再次write會阻塞,直到管道中有空位置了才寫入數據並返回

#include<stdio.h>
#include<fcntl.h>
#include<stdlib.h>
#include<unistd.h>

int main(int argc,char **argv)
{
    int     fd[2];
    char    buf[1024];
    pid_t   pid;
    int     n;

    if(pipe(fd) < 0){
        fprintf(stderr,"error: pipe ");
        exit(1);
    }

    if( (pid = fork()) < 0){
        fprintf(stderr,"error: fork");
        exit(1);
    }

    else if(pid == 0){
        close(fd[0]);//close read
        while(1){
            n = read(STDOUT_FILENO,buf,sizeof(buf));
            write(fd[1],buf,n);
        }
    }

    else{
        close(fd[1]);
        while(1){
           n = read(fd[0],buf,sizeof(buf));
           write(STDOUT_FILENO,buf,n);
        }
    
        wait(pid,NULL);
    }

    exit(0);
}


FIFO(有名管道)

特點:1)兩個無相關的進程之間可以通信
      2)FIFO 是一種文件類型,通過stat結構的st_mode成員的編碼可以知道文件是否是FIFO 類型。

#include<sys/stat.h>
int mkfifo(const char *path,mode_t mode);
成功-- 0,出錯-- -1

FIFO 需要用open來打開,對他的I/O 處理和常規文件相似。
FIFO沒有指定O_NONBLOCK,只讀open要阻塞到某個其他進程爲寫而打開這個FIFO爲止;類似的,只寫open也是這樣。

FIFO制定 O_NONBLOCK,只讀open立即返回,若沒有進程爲讀打開FIFO ,返回 -1,並將errno設置爲ENXIO。

client.c

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

#define MAXLINE 512


int main(int argc,char **argv)
{
    int     fd_rd,fd_wr;
    char    read_buf[MAXLINE],write_buf[MAXLINE];
    int     flags,n;

    fd_wr = open("public_fifo",O_WRONLY);
    fd_rd = open("usr1",O_RDONLY);
    

    while(1){
        fgets(write_buf,sizeof(write_buf),stdin);
        write(fd_wr,write_buf,strlen(write_buf));
        n = read(fd_rd,read_buf,sizeof(read_buf));
        write(STDOUT_FILENO,read_buf,n);
    }
   
    exit(1);

}

server.c

#include<stdio.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<error.h>
#include<string.h>
#include<fcntl.h>

#define MAXLINE 512


int main(int argc,char **argv)
{
    int     fd_rd,fd_wr;
    char    read_buf[MAXLINE],write_buf[MAXLINE];
    int     i = 0,n;
    fd_rd = open("public_fifo",O_RDONLY);
    if(fd_rd < 0){
        fprintf(stderr,"error: open");
        exit(1);
    }

    fd_wr = open("usr1",O_WRONLY);
    if(fd_wr < 0){
        fprintf(stderr,"error: open");
        exit(1);
    }

    while(1){
        n = read(fd_rd,read_buf,sizeof(read_buf));
        write(fd_wr,read_buf,n);
    }

   exit(0); 
}






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