高级IO函数

高级I/O函数

pipe函数

//创建一个管道,实现进程间通信
#include<unistd.h>
int pipe(int fd[2]);

//成功时返回0并将一对打开的文件描述符值填入其参数指向的数组。失败返回-1并设置errno

//fd[0]只能用于从管道读取数据
//fd[1]只能用于往管道写入数据
//实现双向通信需要使用两个管道

//默认情况下这一对文件描述符时阻塞的。如果用read系统调用读取一个空的管道,read将被阻塞,直到管道中有数据可读
//如果用write系统调用往一个满的管道中写入数据,write将被阻塞,直到管道有足够的空间可用

//如果管道的写端文件描述符fd[1]的引用计数减小到0,即没有任何进程需要往管道中写入数据,则针对该规定的读端文件描述符fd[0]的read操作将返回0,即读取到了文件结束标记
//如果管道的读端文件描述符fd[0]的引用计数减小到0,即没有任何进程需要从管道中读取数据,则针对该管道的写端文件描述符fd[1]的write操作将失败,并引发SIGPIPE信号

//管道内部传输的数据是字节流,管道容量大小默认为65536字节,可使用fcntl函数修改管道容量
//创建双向管道
#include<sys/types.h>
#include<sys/socket.h>

int socketpair(int domain,int type,int protocol,int fd[2]);

//domain只能为AF_UNIX,因为只能在本地使用这个双向管道
//fd[0]和fd[1]都是可读可写

//成功时返回0,失败时返回-1并设置errno

dup函数和dup2函数

//复制文件描述符
#include<unistd.h>

int dup(int file_descriptor);

int dup2(int file_descriptor_one,int file_descriptor_two);

//dup函数创建一个新的文件描述符,该新文件描述符与原有文件描述符file_descriptor指向相同文件、管道或网络连接
//dup返回的文件描述符总是取系统当前可用的最小整数值
//dup2与dip相似,将返回第一个不小于fille_descriptor_two的整数值
//失败时返回-1并设置errno

//dup和dup2创建的文件描述符不继承原文件描述符的属性,比如close-on-exec和non-blocking

CGI服务器工作原理

image-20211121194320564

先关闭标准输出文件描述符STDOUT_FILENO(其值为1),然后复制socket文件描述符connfd,因为dup总是返回系统中最小的可用文件描述符,所以其返回值实际上是1,即之前关闭的标准输出文件描述符的值。这样一来,服务器输出到标准输出的内容abcd就会直接发送到客户连接对于的socket上,因为printf调用的输出将被客户端获得而不是显示在服务器程序的终端上

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的字节数,失败返回-1并设置errno

sendfile函数

//在两个文件描述符之间直接传递数据(完全在内核中操作),从而避免了内核缓冲区和用户缓冲区之间的数据拷贝
//零拷贝

#include<sys/sendfile.h>

ssize_t sendfile(int out_fd,int in_fd,off_t* offset,size_t count);

//in_fd是待读出内容的文件描述符,必须时一个支持类似mmap函数的文件描述符,即必须指向真实的文件,不能是socket和管道
//out_fd是待写入内容的文件描述符,必须是socket
//offset指定从读入文件流的哪个位置开始读,如果为空,则使用读入文件流默认的起始位置
//count参数指定在文件描述符之间传输的字节数

//成功时返回传输的字节数,失败时返回-1并设置errno

mmap函数和munmap函数

#include<sys/mman.h>

void* mmap(void* start,size_t length.int prot,int flags,int fd,off_t offset);
//用于申请一段内存空间
//start允许用户使用某个特定的地址作为这段内存的起始地址,若为NULL则系统自动分配
//length指定内存段的长度
//prot设置内存段的访问权限
//flags控制内存段内容被修改后程序的行为
//成功是返回指向目标内存区域的指针,失败返回MAP_FAILED((void*)-1)并设置errno

int munmap(void* start,size_t length);
//释放用mmap创建的内存空间
//munmap成功返回0,失败返回-1并设置errno

内存段的访问权限

image-20211121200935181

image-20211121201034431

MAP_SHARED和MAP_PRIVAE是互斥的,不能同时指定

splice函数

//在两个文件描述符之间移动数据,也是零拷贝操作
#include<fctnl.h>
ssize_t splice(int fd_in,loff_t* off_in,int fd_out,loff_t* off_out,size_t len,unsigned int flags);

//fd_in是待输入数据的文件描述符
//如果fd_in是一个管道文件描述符则off_in必须为NULL
//如果fd_in不是一个管道文件描述符,off_in表示从输入数据流的何处开始读取数据
//fd_in和fd_out至少有一个必须是管道文件描述符
//len指定移动数据的长度
//flags控制数据如何移动

//成功时返回移动字节的数量,失败返回-1并设置errno

image-20211121203627953

image-20211121203739550

tee函数

//在两个管道文件描述符之间复制数据,也是零拷贝
//不消耗数据,因此文件描述符上的操作仍然可以用于后续的读操作
#include<fctnl.h>
ssize_t tee(int fd_in,int fd_out,size_t len,unsigned int flags);

//成功时返回在两个文件描述符之间复制的数据数量,失败返回-1并设置errno

fcntl函数

//提供对文件描述符的各种控制操作
#include<fctnl.h>
int fctnl(int fd,int cmd,...);

//fd被操作的文件描述符
//cmd指定执行何种类型的操作

//失败时返回-1并设置errno

image-20211121204659371

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值