【Linux网络编程】高级I/O函数

本文深入探讨了Linux中的高级I/O函数,包括pipe用于进程间通信,socketpair创建双向管道,dup和dup2实现文件描述符复制,以及sendfile、mmap、munmap实现高效的数据传输。同时介绍了零拷贝技术如splice和tee,以及fcntl对文件描述符的控制。这些函数在高性能服务器编程中发挥着关键作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

总结《Linux高性能服务器编程》第六章

第六章 高级I/O函数

pipe函数

  • pipe函数可用于创建一个管道,以实现进程间通信,pipe函数的定义如下

    #include<unistd.h>
    int pipe(int fd[2]);
    
    • 参数:一个包含两个int型整数的数组指针;
    • 成功时返回0,并将一对打开的文件描述符值填入其参数指向的数组,失败则返回-1;
  • 通过pipe函数创建的这两个文件描述符fd[0]和fd[1]分别构成管道的两端,往fd[1]写入的数据可以从fd[0]读出,并且fd[0]只能从管道读出数据fd[1]则只能往管道写入数据,而不能反过来使用

  • 管道内部传输的数据是字节流,且管道本身拥有容量限制

  • socketpair函数能够方便地创建双向管道;

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

dup函数和dup2函数

  • 用于复制文件描述符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和dup类似,不过它将返回第一个不小于file_descriptor_two的整数值;
  • 通过dup和dup2创建的文件描述符并不继承原文件描述符的属性,比如close-on-exec和non-blocking等;

代码清单6-1 用dup函数实现CGI服务器原理

readv函数和writev函数

  • readv函数:将数据从文件描述符读到分散的内存块中,即分散读

  • writev函数:将多块分散的内存数据一并写入文件描述符中,即集中写

    #include<sys/uio.h>
    size_t readv(int fd, const struct iovec*vector,int count)size_t writev(int fd, const struct iovec*vector,int count);
    
    • vector参数的类型是iovec结构数组,该结构体描述一块内存区;
    • count参数是vector数组的长度;
    • 相当于简化版的recvmsg和sendmsg函数;

sendfile函数

  • sendfile函数在两个文件描述符之间直接传递数据(完全在内核中操作),从而避免了内核缓冲区和用户缓冲区之间的数据拷贝,效率很高,被称为零拷贝;

    #include<sys/sendfile.h>
    size_t sendfile(int out_fd,int in_fd,off_t*offset,size_t count);
    
    • in_fd必须指向真实文件,不能是socket和管道,而out_fd则必须是一个socket;

mmap函数和munmap函数

  • mmap函数用于申请一段内存空间。我们可以将这段内存作为进程间通信的共享内存,也可以将文件直接映射到其中,munmap函数则释放由mmap创建的这段内存空间;

    #include<sys/mman.h>
    void* mmap(void*start,size_t length,int prot,int flags,int fd,off_t offset);
    int munmap(void*start,size_t length);
    
    • start参数允许用户使用特定地址作为这段内存的起始地址,如果为NULL则由系统自动分配;
    • prot参数用来设置内存段的访问权限:PROT_READ(内存段可读)/ PROT_WRITE(内存段可写) /PROT_EXEC(内存段可执行) /PROT_NONE(内存段不能被访问);
    • flags参数控制内存段内容被修改后程序的行为;

splice函数

  • splice函数用于在两个文件描述符之间移动数据,是零拷贝操作;

    #include<fcntl.h>
    size_t splice(int fd_in, loff_t* off_in, int fd_out, loff_t* off_out, size_t len, unsigned int flags);
    
    • off_in/off_out表示从输入/输出数据流的何处开始读取/写入数据;
    • flags参数则控制数据如何移动;
  • 使用splice函数时,fd_in和fd_out必须至少有一个是管道文件描述符;

tee函数

  • tee函数两个管道文件描述符之间复制数据,是零拷贝操作;

    #include<fcntl.h>
    size_t tee(int fd_in,int fd_out,size_t len,unsigned int flags);
    
    • tee函数*不消耗数据,因此源文件描述符上的数据仍然可以用于后续的读操作;

fcntl函数

  • fcntl函数(file control)提供了对文件描述符的各种控制操作;

    #include<fcntl.h>
    int fcntl(int fd,int cmd,);
    
    • 另一个常见控制文件描述符的系统调用是ioctl,但fcntl函数是由POSIX规范指定的首选方法;
    • 在网络编程中,fcntl函数通常用来将一个文件描述符设置为非阻塞的;
image-20221026084120309
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值