IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Linux的高级I/O函数 -> 正文阅读

[系统运维]Linux的高级I/O函数

1、Linux的基本I/O函数有read,write以及open等:

#include<unistd.h>
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

2、与网络编程的高级I/O函数可以大致分为以下三类:

????????(1)用于创建文件描述符的函数,包括:pipe、dup/dup2函数?

????????(2)用于读写数据的函数,包括 readv/writev、sendfile、mmap/munmap、splice和tee函数

????????(3)用于控制I/O属性和行为的函数,包括fcntl函数

3、下面对各函数进行简单描述,包括其函数原型,参数,用法等

????????(1)pipe函数

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

????????pipe函数用于创建一个管道,以实现进程间的通信。fd[0]和fd[1]分别构成管道的两端,其中fd[0]为输出端,fd[1]为写入端。这一对文件描述符都是阻塞的,如果往一个空管道中读取数据,read会一直阻塞,直到管道中有数据可读才会解除阻塞,进而读取数据;而往一个满的管道中写数据,write也会一直阻塞,直到管道有足够多的空间可用时,解除阻塞。

? ? ? ? 另外,如果写端文件描述符fd[1]引用计数为0,即无进程往此管道写数据,那么读端的文件描述符fd[0]的read操作会返回0,即读到文件结束标志EOF;如果读端文件描述符fd[0]引用计数为0,即无进程从此管道读数据,那么写端的文件描述符fd[1]的write操作将失败,并引发SIGPIPE信号。

? ? ? ? (2)dup/dup2函数

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

? ? ? ? dup/dup2的作用是可以把标准输入重定向到一个文件,或者把标准输出重定向到一个网络连接。dup函数创建一个新的文件描述符,该文件描述符和原有的文件描述符指向同样的文件、管道或者网络连接。并且dup返回的文件描述符总是取系统当前可用的最小整数值。dup2和dup类似,不过它将返回第一个不小于file_descriptor_two的整数值。dup和dup2系统调用失败时返回-1并设置errno。

? ? ? ? 另外,通过dup或者dup2创建的文件描述符并不继承原文件描述符的的属性,比如close-on-exec和non-blocking等。

? ? ? ? (3)readv函数和writev函数

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

struct iovec{
    void* iov_base;  // 内存起始地址
    size_t iov_len;  // 这块内存的长度
}

? ? ? ? fd参数是将要被操作的文件描述符,vector参数的类型是iovec结构数组,count参数的之vector数组的长度。readv和writev调用成功返回读出/写入fd的字节数,失败返回-1并设置errno。这样的好处是不用拼接分块数据,即可一次读取或写入。

? ? ? ? (4)sendfile函数

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

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

? ? ? ? in_fd参数是待读出内容的文件描述符,out_fd参数的待写入内容的文件描述符。offset参数指定从读入文件流的哪个位置开始读,若为空,则使用读入文件流的默认起始位置。count参数是指in_fd和out_fd之间传输的字节数。sendfile成功返回传输的字节数,失败返回-1并设置errno。

? ? ? ? 需要注意的是:in_fd必须是指向真实的文件,不能是socket和管道;而out_fd则必须是一个socket。

? ? ? ? (5)mmap函数和munmap函数

#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 );

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

? ? ? ? start参数是用户指定地址作为这段内存的起始地址,如果设置为NULL,则系统自动分配,length参数是该内存段的长度,prot参数用来设置内存段的访问权限,可以设置一个,也可以多个按位或,常用的有:PROT_READ,PROT_WRITE,PROT_EXEC,PROT_NONE;flags参数是控制内存段内容被修改后程序的行为,常用的有:MAP_SHARED,MAP_PRIVATE等;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_in是一个管道文件描述符,那么off_in参数要设置为NULL,否则off_in表示从输入数据流的当前偏移位置读入。fd_out/off_out参数的含义与fd_in/off_in相同,只不过该参数用于输出数据流。len参数指定移动数据的长度,flags参数则用于控制数据如何移动,常用的值有:SPLICE_F_MOVE,SPLICE_F_NONBLOCK,SPLICE_F_MORE,SPLICE_F_GIFT,可以按位或来设置多个组合。

? ? ? ? 需要注意的是,使用该函数时,fd_in和fd_out必须至少有一个是管道文件描述符。调用成功返回移动字节数,调用失败返回-1并设置errno。

? ? ? ? (7)tee函数

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

? ? ? ? tee函数在两个管道文件描述符之间复制数据,也是零拷贝操作。它不消耗数据,因此源文件描述符上的数据仍然可以用于后续的读操作。

? ? ? ? fd_in和fd_out参数都必须为管道的文件描述符;len参数指定复制数据的长度,flags参数则用于控制数据如何复制,跟splice函数一样。调用成功返回复制的字节数,失败返回-1,并设置errno。

? ? ? ? (8)fcntl函数

#include<fcntl.h>
int fcntl( int fd, int cmd, ...);

? ? ? ? fcntl(file control)函数,提供了对文件描述符的各种控制操作。fd参数是被操作的文件描述符,cmd参数指定执行何种类型的操作。根据操作类型的不同,该函数可能还需要第三个可选参数arg。在网络编程中,fcntl常用来将一个文件描述符设置为非阻塞。如下面的例子:

int setnonblocking( int fd ){
    int old_option = fcntl( fd, F_GETFL );     // 获取文件描述符旧的状态标志
    int new_option = old_option | O_NONBLOCK;  // 设置非阻塞标志
    fcntl( fd, F_SETFL, new_option );    // 把非阻塞标志作为第三参数输入
    return old_option;    // 返回文件描述符旧的状态,以便日后恢复该状态标志
}

? ? ? ? 以上是各种Linux的高级I/O函数,在网络编程中用得较多。本文参考的是游双的《Linux高性能服务器编程》。

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-02-01 20:59:17  更:2022-02-01 21:00:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 7:55:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码