Linux中文件I/O函数
一、lseek函数
每个打开文件都有一个与其相关联的“当前文件偏移量”。它通常是一个非负整数,用以度量从文件开始处
计算的字节数。通常,读、写操作都从当前文件偏移量处开始,并使偏移量增加所读写的字节数。当打开一个文
件时,除非指定O_APPEND选项(调用open函数时使用了O_APPEND),否则该偏移量被设置为0。调用lseek函数显
式地为一个打开文件设置偏移量。该函数原型为:
#include <unistd.h>
off_t lseek(int fd,off_t offset,int whence);
该函数若成功则返回新的文件偏移量,若出错返回-1。参数fd为打开的文件描述符,参数offset与参数whence
的值有关:
- 若whence是SEEK_SET,则将该文件的偏移量设置为距文件开始处offset个字节。
- 若whence是SEEK_CUR,则将该文件的偏移量设置为其当前值加offset,offset可为正为负。
- 若whence是SEEK_END,则将该文件的偏移量设置为文件长度加offset,offset可正可负。
若lseek成功执行,则返回新的文件偏移量。如果文件描述符指向的是一个管道、FIFO或网络套接字,则lseek
返回-1,并将errno设置为ESPIPE。
二、dup和dup2函数
dup和dup2系统调用都可以用来复制文件描述符,函数的原型为:
#include <unistd.h>
int dup(int fd);
int dup2(int fd,int fd2);
函数成功执行返回新的文件描述符,若出错返回-1。由dup返回的新文件描述符一定是当前可用文件描述符中的
最小数值。对于dup2,可以用fd2参数指定新的文件描述符的值。如果fd2已经打开,则先将其关闭。若fd等于fd2,
则dup2返回fd2,而不关闭它。否则,fd2的FD_CLOEXEC文件描述符标志就被清除,这样fd2在进程调用exec时是打
开状态。
dup(fd);等效于fcntl(fd,F_DUPFD,0); dup2(fd,fd2);等效于close(fd2);fcntl(fd,F_DUPFD,fd2);
而dup2并不完全等同于close加上fcntl。它们之间的区别有:
(1)dup2是一个原子操作,而close和fcntl包括了两个函数调用。有可能在close和fcntl之间调用了信号捕获
函数,它可能修改文件描述符。如果不同的线程改变了文件描述符的话也会出现同样的问题。
(2)dup2和fcntl有一些不同的errno。
三、fcntl函数
fcntl系统调用可以用来对已经打开的文件描述符进行各种控制操作以改变已打开文件的各种属性,该函数的
原型为:
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd,int cmd,.../*int arg*/);
fcntl函数有以下5种功能:
(1)复制一个已有的文件描述符(cmd=F_DUPFD或F_DUPFD_CLOEXEC)。
(2)获取/设置文件描述符标志(cmd=F_GETFD或F_SETFD)。
(3)获取/设置文件状态标志(cmd=F_GETFL或F_SETFL)。
(4)获取/设置异步I/O所有权(cmd=F_GETOWN或F_SETOWN)。
(5)获取/设置记录锁(cmd=F_GETLK、F_SETLK或F_SETLKW)。
F_DUPFD:复制文件描述符fd。新文件描述符作为函数值返回。它是尚未打开的各描述符中大于或等于第3个
参数值(取为整型值)中各值的最小值。新文件描述符与fd共享同一文件表项。但是新的文件描述符有它自己的
一套文件描述符标志,其FD_CLOEXEC文件描述符标志被清除(这表示该文件描述符在exec时仍保持有效)。
F_DUPFD_CLOEXEC:复制文件描述符,设置与新的文件描述符关联的FD_CLOEXEC文件描述符标志的值,返回
新的文件描述符。
F_GETFD:对应于fd的文件描述符标志作为函数值返回当前只定义了一个文件描述符标志FD_CLOEXEC。
F_SETFD:对于fd设置文件描述符标志。新标志值按第3个参数(取为整型值)设置。
F_GETFL:对应于fd的文件状态标志作为函数值返回。
F_SETFL:将文件状态标志设置为第3个参数的值(取为整型值)。可以更改的几个标志为:O_APPEND、O_NO
NBLOCK、O_SYNC、O_DSYNC、O_RSYNC、O_FSYNC和O_ASYNC。
F_GETOWN:获取当前接收SIGIO和SIGURG信号的进程ID或进程组ID。
F_SETOWN:设置接收SIGIO和SIGURG信号的进程ID或进程组ID。正的arg指定一个进程ID,负的arg表示等于
arg绝对值的一个进程组ID。
fcntl的返回值与命令有关。如果出错,所有命令都返回-1,如果成功则返回某个其它值。F_DUPFD返回新的
文件描述符,F_GETFD和F_GETFL返回相应的标志,F_GETOWN返回一个正的进程ID或负的进程组ID。
四、ioctl函数
ioctl系统调用通常用来控制设备,不能用其它函数进行的控制操作都可以用ioctl来进行,该函数原型为:
#include <unistd.h>
#include <sys/ioctl.h>
int ioctl(int fd,int request,...);
ioctl用来控制特殊设备文件的属性,第一个参数fd必须是一个已经打开的文件描述符,第三个参数一般为
char *argp,它随第二个参数request的不同而不同。参数request决定了参数argp是向ioctl传递数据还是从io
ctl获取数据。
五、readv和writev函数
readv函数将数据从文件描述符读到分散的内存块中,即分散读;writev函数则将多块分散的内存数据一并
写入文件描述符中,即集中写。函数的原型为:
#include <sys/uio.h>
ssize_t readv(int fd,const struct iovec *iov,int count);
ssize_t writev(int fd,const struct iovec *iov,int count);
函数中fd参数是被操作的目标文件描述符。iov参数的类型是iovec结构数组,该结构体描述一块内存区。参
数count是iov数组的长度,即有多少块内存数据需要从fd读出或写到fd。readv和writev函数在成功时返回读出/
写入fd的字节数,失败则返回-1并设置errno。
六、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参数指定从读
入文件流的哪个位置开始读,如果为空,则使用读入文件流默认的起始位置。count参数指定在文件描述符in_fd
和out_fd之间传输的字节数。sendfile函数成功时返回传输的字节数,失败则返回-1并设置errno。in_fd必须是一
个支持类似mmap函数的文件描述符,即它必须指向真实的文件,不能是socket和管道;而out_fd则必须是一个soc
ket。因此,sendfile函数几乎是专门为在网络上传输文件而设计的。
七、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,则系统自动
分配一个地址。length参数指定内存段的长度。prot参数用来设置内存段的访问权限,它可以取以下几个值的按位
或:(1)PROT_READ:内存段可读。(2)PROT_WRITE:内存段可写。(3)PROT_EXEC:内存段可执行。(4)PRO
T_NONE:内存段不能被访问。
flags参数控制内存段内容被修改后程序的行为,它可以被设置为某些值的按位或(其中MAP_SHARED和MAP_PRIVATE
是互斥的,不能同时指定)。flags参数的常用值有:MAP_SHARED、MAP_PRIVATE、MAP_ANONYMOUS、MAP_FIXED、MA
P_HUGETLB。fd参数是被映射文件对应的文件描述符,它一般通过open系统调用获得。offset参数设置从文件的何
处开始映射(对于不需要读入整个文件的情况)。
mmap函数成功时返回指向目标内存区域的指针,失败则返回MAP_FAILED((void*)-1)并设置errno。munmap函数
成功时返回0,失败则返回-1并设置errno。
八、splice函数
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);
函数中fd_in参数是待输入数据的文件描述符,如果fd_in是一个管道文件描述符,那么off_in参数必须被设置
为NULL,如果fd_in不是一个管道文件描述符,那么off_in表示从输入数据流的何处开始读取数据,此时若off_in
被设置为NULL,则表示从输入数据流的当前偏移位置读入;若off_in不为NULL,则它将指出具体的偏移位置。fd_o
ut/off_out参数的含义与fd_in/off_in相同,不过用于输出数据流。len参数指定移动数据的长度;flags参数则控
制数据如何移动,它可以被设置为某些值的按位或,常用值为:SPLICE_F_MOVE、SPLICE_F_NONBLOCK、SPLICE_F_
MORE、SPLICE_F_GIFT。使用splice函数时,fd_in和fd_out必须至少有一个是管道文件描述符。splice函数调用成
功时返回移动字节的数量,它可能返回0,表示没有数据需要移动,这发生在从管道中读取数据(fd_in是管道文件
描述符)而该管道没有被写入任何数据时。splice函数失败时返回-1并设置errno。
九、tee函数
tee函数在两个管道文件描述符之间复制数据,也是零拷贝操作。它不消耗数据,因此源文件描述符上的数据仍
然可以用于后续的读操作。该函数原型为:
#include <fcntl.h>
ssize_t tee(int fd_in,int fd_out,size_t len,unsigned int flags);
该函数的参数的含义与splice相同(但fd_in和fd_out必须都是管道文件描述符)。tee函数成功时返回在两个文
件描述符之间复制的数据数量(字节数)。返回0表示没有复制任何数据。tee失败时返回-1并设置errno。
Linux中文件I/O函数的更多相关文章
- linux中文件IO
一. linux常用文件IO接口 1.1. 文件描述符 1.1.1. 文件描述符的本质是一个数字,这个数字本质上是进程表中文件描述符表的一个表项,进程通过文件描述符作为index去索引查表得到文件表指 ...
- [转]Linux中文件权限目录权限的意义及权限对文件目录的意义
转自:http://www.jb51.net/article/77458.htm linux中目录与文件权限的意义 一.文件权限的意义 r:可以读这个文件的具体内容: w:可以编辑这个文件的内容,包括 ...
- php中文件操作常用函数有哪些
php中文件操作常用函数有哪些 一.总结 一句话总结:读写文件函数 判断文件或者目录是否存在函数 创建目录函数 file_exists() mkdir() file_get_content() fil ...
- LSOF查看linux中文件打开情况
如何查看linux中文件打开情况 前言 我们都知道,在linux下,“一切皆文件”,因此有时候查看文件的打开情况,就显得格外重要,而这里有一个命令能够在这件事上很好的帮助我们-它就是lsof. lin ...
- linux中文件压缩介绍
原文内容来自于LZ(楼主)的印象笔记,如出现排版异常或图片丢失等问题,可查看当前链接:https://app.yinxiang.com/shard/s17/nl/19391737/1c62bb7f-f ...
- linux中文件颜色,蓝色,白色等各自代表的含义
linux中文件颜色,蓝色,白色等各自代表的含义 绿色文件---------- 可执行文件,可执行的程序 红色文件-----------压缩文件或者包文件 蓝色文件----------目录 白色文件- ...
- Linux中文件函数(二)
一.link.linkat.unlink.unlinkat.remove函数 创建一个指向现有文件的链接的方法是使用link函数或linkat函数.函数的原型为: #include <unist ...
- 对于数据包的截取,使用linux中的netfilter钩子函数
http://blog.csdn.net/wswifth/article/details/5115358 在师哥的代码(packet.c)中使用的是Linux2.4内核中的一个子系统:netfilte ...
- linux中应用程序main函数中没有开辟进程的,它应该在那个进程中运行呢?
1.main函数是一个进程还是一个线程? 不知道你是用c创建的,还是用java创建的. 因为它们都是以main()做为入口开始运行的. 是一个线程,同时还是一个进程. 在现在的操作系统中,都是多线程的 ...
随机推荐
- CentOS 7运维管理笔记(8)----Apache基于域名的虚拟主机配置
使用基于域名的虚拟主机配置是比较流行的方式,可以在同一个IP上配置多个域名并且都通过80端口访问. (1) 在网卡 eth0的第五个接口上配置 192.168.1.215 这个地址: (2) 配置/e ...
- 制作Makefile中 ** missing separator 错误解决
非常简单就是根据提示,在这一行的前面摁Tab键 错误如上图所示:
- push本地代码到github发生错误的解决办法
有一天,我在github上编写好了README.md这个文件,接着发现本地有段代码忘记上传了,于是熟练的输入git add . git commit -m "modify",以 ...
- Linux Firefox Adobe Flash Player 安装和更新
1.下载 Firefox Adobe Flash Player 使用Linux上的火狐浏览器访问如下的下载网址: https://get.adobe.com/flashplayer/ 选择下载 &qu ...
- 如何阅读 Redis 源码?ZZ
原文链接 在这篇文章中, 我将向大家介绍一种我认为比较合理的 Redis 源码阅读顺序, 希望可以给对 Redis 有兴趣并打算阅读 Redis 源码的朋友带来一点帮助. 第 1 步:阅读数据结构实现 ...
- wcf 配置与代码创建
<behaviors> <serviceBehaviors> <behavior name="MyServiceBehavior"> <s ...
- shell链接
5个实用的shell脚本面试题和答案: http://www.cnblogs.com/xinjie10001/p/6395945.html linux shell 逻辑运算符.逻辑表达式详细介绍: h ...
- Angular开启两个项目方法
Angular开启两个项目方法: ng server --port 80
- 第一周 day1 Python学习笔记
为什么要学习Python? Python擅长的领域 1. python2.x中不支持中文编码,默认编码格式为ASCII码,而python3.x中支持Unicode编码,支持中文,变量名可以为中文,如: ...
- phoneGap的Android下编写phonegap 插件
一. javascript 端的编写 第一个参数 成功的回调函数 第二个参数 失败的回调函数 第三个参数 是插件的类名称,也就是后台java文件的类名 第四个参数 执行的 action 名称 ...