FIFO 和普通文件

FIFO; a named pipe
[root@localhost ch13]# cat fifo3.c 
/*************write*****/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>

#define FIFO_NAME "/tmp/my_fifo"
#define BUFFER_SIZE PIPE_BUF
//PIPE_BUF=4096
#define TEN_MEG (1024 * 1024 * 10)

int main()
{	
    int pipe_fd;
    int res;
    int open_mode = O_WRONLY;
    int bytes_sent = 0;
    char buffer[BUFFER_SIZE + 1]="agds";

    if (access(FIFO_NAME, F_OK) == -1) {
        res = mkfifo(FIFO_NAME, 0777);
        if (res != 0) {
            fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME);
            exit(EXIT_FAILURE);
        }
    }

    printf("Process %d opening FIFO O_WRONLY\n", getpid());
    pipe_fd = open(FIFO_NAME, open_mode);
    printf("Process %d result %d\n", getpid(), pipe_fd);

    if (pipe_fd != -1) {
        while(bytes_sent < TEN_MEG) {
            res = write(pipe_fd, buffer, BUFFER_SIZE);
            if (res == -1) {
                fprintf(stderr, "Write error on pipe\n");
                exit(EXIT_FAILURE);
            }
	printf("%s\n",buffer);
            bytes_sent += res;
        }
        (void)close(pipe_fd); 
    }
    else {
        exit(EXIT_FAILURE);        
    }

    printf("Process %d finished\n", getpid());
    exit(EXIT_SUCCESS);
}
[root@localhost ch13]# 
[root@localhost ch13]# 
[root@localhost ch13]# 
[root@localhost ch13]# cat fifo4.c 
/*************read*****/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>

#define FIFO_NAME "/tmp/my_fifo"
#define BUFFER_SIZE PIPE_BUF

int main()
{
    int pipe_fd;
    int res;
    int open_mode = O_RDONLY;
    char buffer[BUFFER_SIZE + 1];
    int bytes_read = 0;

    memset(buffer, '\0', sizeof(buffer));

    
    printf("Process %d opening FIFO O_RDONLY\n", getpid());
    pipe_fd = open(FIFO_NAME, open_mode);
    printf("Process %d result %d\n", getpid(), pipe_fd);

    if (pipe_fd != -1) {
        do {
            res = read(pipe_fd, buffer, BUFFER_SIZE);
		printf("%s\n",buffer);
            bytes_read += res;
        } while (res > 0);
        (void)close(pipe_fd);
    }
    else {
        exit(EXIT_FAILURE);
    }

    printf("Process %d finished, %d bytes read\n", getpid(), bytes_read);
    exit(EXIT_SUCCESS);
}

[root@localhost ch13]# 

[root@localhost ch13]# rm /tmp/my_fifo -f
[root@localhost ch13]# ./fifo3 &
[2] 17216
[root@localhost ch13]# Process 17216 opening FIFO O_WRONLY

[root@localhost ch13]# time ./fifo4 
...
agds
agds
agds
agds
agds
agds
agds
agds
agds
agds
agds
agds
agds
agds
agds
agds
agds
agds
agds
agds
Process 17220 finished, 10485760 bytes read
real    0m0.610s
user    0m0.002s
sys    0m0.284s
Process 17216 finished
[root@localhost ch13]# 
//FIFO文件是fifo3创建,所以先运行fifo3,如果先运行fifo4则找不到my_fifo而出错
fifo3 is blocked when it opens without NONBLOCK mode until fifo4 also open the same FIFO file
[root@localhost ch13]# ll /tmp/my_fifo 
prwxr-xr-x. 1 root root 0 Aug 26 03:14 /tmp/my_fifo
the FIFO file my_fifo is 0 bytes


如果他们之间读写的不是FIFO文件,而是一个普通文件会是怎么样呢

[root@localhost ch13]# rm /tmp/my_fifo -f
[root@localhost ch13]# touch /tmp/my_fifo 
[root@localhost ch13]# ll /tmp/my_fifo 
-rw-r--r--. 1 root root 0 Aug 26 03:20 /tmp/my_fifo
run fifo3 and fifo4 just as the cmd  above,then
Process 17276 finished, 10485760 bytes read

real	0m0.253s
user	0m0.006s
sys	0m0.235s
[root@localhost ch13]# ll /tmp/my_fifo 
-rw-r--r--. 1 root root 10485760 Aug 26 03:23 /tmp/my_fifo
看来,普通文件用于进程间通信也不慢哈
并且还可以从外部查看通信的内容和大小
但是不管open中是否用了O_NONBLOCK,都会O_NONBLOCK的






### FIFO 文件操作流程 在 Linux 中,FIFO(First In First Out)是一种特殊的文件类型,也称为命名管道。这种机制允许不相关的进程之间通过特定路径名进行通信[^3]。 #### 创建 FIFO 文件 要创建一个 FIFO 文件,可以使用 `mkfifo` 函数: ```c #include <sys/types.h> #include <sys/stat.h> int mkfifo(const char *pathname, mode_t mode); ``` 此函数会按照给定的名字权限模式创建一个新的 FIFO 特殊文件。如果功,则返回 0;若有错误发生则返回 -1 并设置 errno 变量来指示具体原因。 #### 打开 FIFO 文件 一旦 FIFO 被创建之后,就可以像普通文件一样对其进行打开操作。通常情况下,读端会在写端连接之前阻塞直到有一个对应的写者存在才会继续执行下去。同样地,写端也会等待至少一个读者准备好接收数据才解除阻塞状态。这可以通过 `open()` 来完: ```c #include <fcntl.h> /* For O_* constants */ #include <unistd.h>/* For open() */ int fd; fd = open(pathname_of_fifo, O_WRONLY); // 写入方 // 或者 fd = open(pathname_of_fifo, O_RDONLY); // 读取方 ``` 对于只做一次性的简单传输来说,也可以考虑采用阻塞的方式来进行尝试性打开: ```c fd = open(pathname_of_fifo, O_WRONLY | O_NONBLOCK); if (fd == -1 && errno == ENXIO){ // 没有其他进程正在监听该 FIFO } else { // 功打开了 FIFO 或者遇到了不同的错误情况 } ``` #### 数据交换过程 当两端都已就绪后便可以直接利用常规的 I/O 系统调用来发送/接受消息了。比如使用 `read()` `write()` 进行字节流形式的数据交互: ```c char buffer[BUFFER_SIZE]; ssize_t bytes_read; bytes_read = read(fd, buffer, BUFFER_SIZE); if(bytes_read > 0){ process_data(buffer, bytes_read); } // 同样可以用 write 发送数据至另一侧 write(fd, "message", strlen("message")); ``` #### 关闭与清理资源 完所有的通讯工作以后应当记得释放所占用的相关句柄并移除不再需要使用的 FIFO 设备本身: ```c close(fd); unlink(pathname_of_fifo); ``` 这样不仅能够防止潜在的安全隐患还能节省系统资源。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值