Linux 高级I/O函数

Linux提供了很多高级I/O函数,并不像基础I/O(read,open)那么常用,但是在特定情况下可以表现出更好的性能

  •  用于创建文件描述符:pipe,dup/dup2等
  • 用于读写数据的函数:readv/writev,sendfile,mmap/munmap,splice,tee
  • 用于I/O行为和属性 :fcntl  
  1. pipe 函数:

 

             pipe函数可以创建一个管道,实现进程间通信

#include<unistd.h>
int pipe(int fd[2])

pipe函数的参数是含有两个int 整形的数组指针,成功时返回0 ,并将文件描述符值填写到数组中,fd[0]表示读端,fd[1]表示写,两端不可颠倒,默认情况这两个文件描述符都是阻塞的,如果当管道为空时,调用系统调用read()时,将被阻塞,当管道为满时,调用write()也会被阻塞,如果将fd[0]  fd[1]设置为非阻塞,则read()和write()就会有不同的行为,当fd[1]的引用计数减为0则表示,没有任何一个进行往管道中写入数据,则对于fd[0] 的read()操作返回值为0,表示读到末尾(EOF),当fd[0]的引用计数减为0,表示没有任何一个进程读这个管道,则fd[1]写端的write()将失败,引发SIGPEIPE信号,管道内部传输的也是字节流,这点也和TCP传输有些区别,TCP连接写入的数据,取决于滑动窗口的大小,而管道有默认大小:65536字节,可通过fcntl函数修改管道大小。

可通过socketpair创建双向管道

#include<sys/types.h>
#include<sys/socket.h>
int socketpair(int domain,int type, int protocol,int fd[2]);

前三个参数有socket相同,domain  使用AF_UNIX,

2.    dup/dup2函数

有时候我们希望把标准输入重定向到一个文件,或者标准输出重定向到一个网络连接

#include<unistd.h>
int dup(int file_descriptor);
int dup2(int file_descriptor_one,file_descriptor_two);

 

dup 创建的新文件描述符,和原来的文件描述符指向相同的文件,管道或者网络连接,当不继承原来文件描述符的属性。

 

3     readv /writev 函数

 

 readv将文件描述符读到分散的文件内存中,writev 将分散的内存中的数据写到一个文件描述符中,

#include<sys/uio.h>
ssize_t readv(int fd,const struct iovec*  vector,int count);
ssize_t writev(int fd,const struct iovec*  vector,int count);

 fd 是目标文件描述符,vector 是类型为iovec类型的结构体,该结构描述了一款内存,count 表示vector数组的长度

4     sendfile函数

 

sendfile函数表示两个文件描述符的数据传递,完全在内核完成,避免了内核缓冲区到用户缓冲区的拷贝,效率很高,被称为零拷贝

#include<sys/sendfile.h>
ssize_t sendfile(int out_fd,int in_fd,off_t* offset,size_t count);

 

in_fd,表示待读出的文件描述符,out_fd ,表示待写入的文件描述符,offset表示读人的位置,NULL表示默认起始位置,count表示在两个文件描述符传递的字节数,in_fd 必须是一个真实的文件,out_fd必须是一个socket,所以sendfile专门为网络传输文件设计的。 

5    mmap/munmap   函数

 

mmap 函数是申请了一块内存,我们将这块内存作为进程间通信的共享内存,也可以将文件映射到其中,munmap 释放申请的这块内存

#include<sys/mman.h>
void* mmap(void *start,siez_t length,int port,int flags, int fd,off_t offset);
int munmap(void *start,size_t length);

 

start 表示内存的起始地址,length表示内存段的长度,prot表示内存访问权限,flags 表示内存修改后控制程序的行为,fd 表示映射文件的描述符,offset表示文件映射的位置。

6   splice函数

 

 用于两个文件描述符之间的数据交流,也是一个零拷贝

#include<fcntl.h>
ssize_t splice(int fd_in,loff_t* off_in,int fd_out,loff_t* off_out,size_t len,unsigned int flags);

 

splice 函数fd_in  或者 fd_out 必须有一个是管道文件描述符

7   tee  函数

 

 tee 函数用于两个管道之间的数据交流,也是零拷贝操作

#include<fcntl.h>
ssize_t tee(int fd_in,int fd_out,size_t len,unsigned int flags);

 

fd_in  和fd_out 必须都是管道文件描述符。

8    fcntl函数

 

fcntl函数是对各种文件描述符进行操作,修改属性

#include<fcntl.h>
int fcntl(int fd,int cmd,...);
void setnonblock(int fd)//设置非阻塞
{
    int old_fcntl = fcntl(fd,F_GETFL);
    int new_fcntl = old_fcntl | O_NONBLOCK;

    if ( fcntl(fd,F_SETFL,new_fcntl) == -1 )
    {
        perror("fcntl error");
    }
}

 

posted @ 2020-03-03 15:37  睡觉lc  阅读(345)  评论(0)    收藏  举报