进程间通信之管道和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); 
}






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