zoukankan      html  css  js  c++  java
  • 有名管道FIFO

    管道和FIFO的特征之一是它们的数据是一个字节流。这是UNIX的原生I/O模型。进程往其中写入的是字节流,系统不对它作解释。

    FIFO不存数据,只是通过它找到内核文件。

    一.建立有名管道

    1.命令mknod   :

    mknod  name  p/s/m    //创建管道文件/信号量/共享内存

    2.命令mkfifo 创建管道

    mkfifo -m 664 k2     //创建一个访问权限为664的管道文件k2 

    3作为函数:mkfifo

    #include <sys/types.h>

    #include <sys/stat.h>

    int mkfifo(const char *pathname, mode_t mode);

    【注意】

    mkfifo已隐含指定O_CREAT|O_EXCL。即它要么创建一个新的FIFO,要么返回一个EEXIST错误。如果只是希望打开而不创建文件,那就应调用open而不是mkfifo。

    要打开一个已存在的FIFO或创建一个新的FIFO,应先调用mkfifo,检查它是否返回EEXIST错误,若返回则改为调用open。

    另:open函数

    open(const char *path, O_RDONLY);//1
    open(const char *path, O_RDONLY | O_NONBLOCK);//2
    open(const char *path, O_WRONLY);//3
    open(const char *path, O_WRONLY | O_NONBLOCK);//4

    1、就是程序不能以O_RDWR(读写)模式打开FIFO文件进行读写操作,而其行为也未明确定义,因为如一个管道以读/写方式打开,进程就会读回自己的输出,同时我们通常使用FIFO只是为了单向的数据传递。

    2、就是传递给open的是FIFO的路径名,而不是文件名。

    3.第二个参数中的选项O_NONBLOCK,选项O_NONBLOCK表示非阻塞,加上这个选项后,表示open调用是非阻塞的,如果没有这个选项,则表示open调用是阻塞的。

    以只读方式和只写方式打开文件时要注意:

    读端打开,如果写端已打开则打开操作成功返回,如果写端没打开,则读端阻塞。如果是非阻塞函数,则成功返回,(读到文件结束标志)

    写端打开,如果读端已打开则打开操作成功返回,如果读端没打开,则写端阻塞。如果是非阻塞函数,则返回ENXIO错误产生信号SIGPIPE

    FIFO中读取数据

    1. 读端的阻塞标志只对本进程第一个读操作施加作用,如果本进程内有多个读操作序列,则在第一个读操作被唤醒并完成读操作后,其它将要执行的读操作将不再阻塞,即使在执行读操作时,FIFO中没有数据也一样(此时,读操作返回0)。

    2. 对于设置了阻塞标志的读操作说,造成阻塞的原因有两种:当前FIFO内有数据,但有其它进程在读这些数据;另外就是FIFO内没有数据。解阻塞的原因则是FIFO中有新的数据写入,不论写入数据量的大小,也不论读操作请求多少数据量。就是说读操作同时只可以有一个进程进行。

    3. 如果有进程写打开FIFO,且当前FIFO内没有数据,则对于设置了阻塞标志的读操作来说,将一直阻塞。对于没有设置阻塞标志读操作来说则返回-1,当前errno值为EAGAIN,提醒以后再试。

    FIFO中写入数据:

    1.对于设置了阻塞标志的写操作:

    • 当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。如果此时管道空闲缓冲区不足以容纳要写入的字节数,则进入睡眠,直到当缓冲区中能够容纳要写入的字节数时,才开始进行一次性写操作。
    • 当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。FIFO缓冲区一有空闲区域,写进程就会试图向管道写入数据,写操作在写完所有请求写的数据后返回。(这时读端可能间歇性得到数据)

    2.对于没有设置阻塞标志的写操作:

    • 当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。如果当前FIFO空闲缓冲区能够容纳请求写入的字节数,写完后成功返回;如果当前FIFO空闲缓冲区不能够容纳请求写入的字节数,则返回EAGAIN错误,提醒以后再写;
    • 当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。在写满所有FIFO空闲缓冲区后,写操作返回。

    FIFO内核实现时可以支持双向通信。(pipe单向通信,因为父子进程共享同一个file 结构体

    先关闭只读方式打开的文件,再以只写方式打开文件。这样就可以实现双向通信了。但最好使用一对FIFO

    验证代码:

    先写后读:

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <string.h>
    #define MSG "hello"
    int main()
    {
        int fd;
        fd = open("./fio",O_WRONLY);
        printf("w:send msg:%s
    ",MSG);
        write(fd,MSG,sizeof(MSG));
        sleep(5);
        close(fd);
        fd = open("./fio",O_RDONLY);
        char buf[1024];
        memset(buf,0,sizeof(buf));
        read(fd,buf,sizeof(buf));
        printf("w,recv:%s
    ",buf);
    
    }

    先读后写:

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <string.h>
    #include <fcntl.h>
    int main()
    {
        int fd;
        fd = open("./fio",O_RDONLY);
        char buf[1024];
        memset(buf,0,sizeof(buf));
        read(fd,buf,sizeof(buf));
        printf("r:recv msg:%s
    ",buf);
    
        sleep(5);
        close(fd);
        fd = open("./fio",O_WRONLY);
        printf("r:send:%s
    ","fighting");
        write(fd,"fighting",9);
    
    }

    安全问题:

    个FIFO文件,有多个进程同时向同一个FIFO文件写数据,而只有一个读FIFO进程在同一个FIFO文件中读取数据时,会发生数据块的相互交错。

    根据上面的知识我们知道:

    如果所有的写请求都是发往一个阻塞的FIFO的,并且每个写记请求的数据长度小于等于PIPE_BUF字节,系统就可以确保数据决不会交错在一起。

    模型:

    1-1

    n-1

    n-1-n

     fgets,它读取以换行符“ ”结尾的字符串.

    小结:

    管道文件。它占用i节点块和数据块,在目录文件中记载了文件和i节点对应关系的管道是有名管道,没有记载的是无名管道。

    管道文件一旦读出,就从管道中删除,所以它具有不可再现性。

  • 相关阅读:
    Changing Icon File Of Push Button At Runtime In Oracle Forms 6i
    Set Font Properties On Mouse Hover Of Push Button And Text Items At Run time In Oracle Forms
    Change An Item Property Using Set_Item_Property In Oracle Forms
    Calling / Running a report in Oracle forms 10g / 11g
    Change Or Set Report Object Property At Run Time In Oracle Forms Using Set_Report_Object_Property Command
    Refresh / Updating a form screen in Oracle D2k Forms 6i
    Know How And When To Use System.Message_Level To Control Messages In Oracle Forms
    Perform Cut Copy Paste Operations Using Cut_Region Copy_Region Paste_Region Commands In Oracle Forms
    CHECKBOX_CHECKED built-in in Oracle D2k Forms
    Limiting To Select Only 5 Check Boxes Out Of Ten In Oracle Forms
  • 原文地址:https://www.cnblogs.com/Lune-Qiu/p/9368051.html
Copyright © 2011-2022 走看看