[Unix.C]文件I/O
大多数unix文件I/O操作只需要用到5个函数:open、read、write、lseek和close。此处所说明的函数均为不带缓存的I/O操作(下同)。不带缓存指的是每个read和write都调用内核的一个系统调用。这些不带缓存的函数并不是ANSI C的组成部分,但是是POSIX.1和XPG3的组成部分。
文件描述符(File Descriptors)
对内科而言,所有打开的文件都由fd引用。fd是一个非负整数。当打开一个已存在的文件或创建一个新文件时,内核向进程返回一个fd。当读/写一个文件时,我们将open/creat返回的fd作为一个参数传递给read/write。
按照惯例,unix将描述符0与进程的标准输入关联,fd 1与进程的标准输出惯例,fd 2与标准出错输出关联。
在POSIX应用程序中,幻数0、1、2被符号常量STDINFILENO、STDOUTFILENO、STDERR_FILENO替代。这些常量定义在unistd.h中。
open函数
#include <fcntl.h> int open(const char *pathname, int flags,.../*, mode_t mode*/); |
仅当创建一个新文件时才使用到第三个参数。pathname打开/创建的文件名。flags用来说明这个函数的多个选项,用下列一个或多个常量进行或运算构成flags参数:
- O_RDONLY 只读打开
- O_WRONLY 只写打开
- O_RDWR 读写打开
- O_APPEND 每次写时都追加到文件尾
- O_CREAT 若文件不存在则创建它,使用此选项时需要指定mode参数,用于说明该文件的访问权限
- O_EXCL 如果O_CREAT同时被指定并且文件已存在,则返回一个错误。该选项用来测试文件是否已存在,若文件不存在则文件的创建是一个原子操作
- O_TRUNC 若文件以存在且使用只写/读写打开时,将文件长度截断为0
- O_NOCTTY 如果pathname指向的是一个终端设备,不将此设备分配为该进程的控制终端
- O_NONBLOCK 如果p at hname指的是一个FI FO、一个块特殊文件或一个字符特殊文件,则此选择项为此文件的本次打开操作和后续的 I/O操作设置非阻塞方式
- O_SYNC 每次write都要等待物理I/O操作完成
The file descriptor returned by open is guaranteed to be the lowest-numbered unused descriptor.
creat函数
A new file can also be created by calling the creat function.
#include <fcntl.h> int creat(const char *pathname, mode_t mode); |
Returns: file descriptor opened for write-only if OK, 1 on error |
Note that this function is equivalent to open (pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);
close函数
关闭一个打开的文件
#include <unistd.h> int close(int filedes); |
关闭一个文件时也释放该进程加在该文件上的所有记录锁。
当一个进程终止时,它所有的打开文件都由内核自动关闭。很多程序都使用这一功能而不显式地用close关闭打开的文件。
lseek函数
每个打开文件都有一个与其相关联的“当前文件位移量”。它是一个非负整数,用以度量从文件开始处计算的字节数。通常,读、写操作都从当前文件位移量处开始,并使位移量增加所读或写的字节数。按系统默认,当打开一个文件时,除非指定O_APPEND选择项,否则该位移量被设置为0。
可以调用lseek显式地定位一个打开文件。
#include <unistd.h>
off_t lseek(int filedes, off_t offset, int whence);
返回:若成功为新的文件位移,若出错为-1
对参数offset的解释与参数whence的值有关。
- 若whence是SEEK_SET,则将该文件的位移量设置为距文件开始处offset个字节。
- 若whence是SEEK_CUR,则将该文件的位移量设置为其当前值加offset,offset可为正或负。
- 若whence是SEEK_END,则将该文件的位移量设置为文件长度加offset,offset可为正或负。
若lseek成功执行,则返回新的文件位移量,为此可以用下列方式确定一个打开文件的当前位移量:
off_t currpos;
currpos = lseek(fd, 0, SEEK_CUR);
这种方法也可用来确定所涉及的文件是否可以设置位移量。如果文件描述符引用的是一个管道或FIFO,则lseek返回-1,并将er rno设置为EPIPE。
lseek仅将当前的文件位移量记录在内核内,它并不引起任何I/O操作。然后,该位移量用于下一个读或写操作。
文件位移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将延长该文件,并在文件中构成一个空洞,这一点是允许的。文件中任何没有被写过的字节都被读为0。
read函数
用read函数从打开文件中读数据。
#include <unistd.h>
ssize_t read(int filedes, void *buf, size_t nbytes);
返回:读到的字节数,若已到文件尾为 0,若出错为- 1
如read成功,则返回读到的字节数。如已到达文件的尾端,则返回0。
有多种情况可使实际读到的字节数少于要求读字节数:
- 读普通文件时,在读到要求字节数之前已到达了文件尾端。例如,若在到达文件尾端之前还有30个字节,而要求读100个字节,则read返回30,下一次再调用read时,它将返回0(文件尾端)。
- 当从终端设备读时,通常一次最多读一行。
- 当从网络读时,网络中的缓冲机构可能造成返回值小于所要求读的字节数。
- 某些面向记录的设备,例如磁带,一次最多返回一个记录。
读操作从文件的当前位移量处开始,在成功返回之前,该位移量增加实际读得的字节数。
write函数
用write函数向打开文件写数据。
#include <unistd.h>
ssize_t write(int filedes, const void *buf, size_t nbytes);
返回:若成功为已写的字节数,若出错为- 1
其返回值通常与参数nbytes的值相同,否则表示出错。 write出错的一个常见原因是:磁盘已写满,或者超过了对一个给定进程的文件长度限制。
对于普通文件,写操作从文件的当前位移量处开始。如果在打开该文件时,指定了O_APPEND选择项,则在每次写操作之前,将文件位移量设置在文件的当前结尾处。在一次成功写之后,该文件位移量增加实际写的字节数。
dup和dup2函数
一个已存在的文件描述符可以通过下面的两个函数进行复制。
#include <unistd.h>
int dup(int filedes);
int dup2(int filedes, int filedes2);
都返回: 若成功为新的文件描述符,若失败-1
dup返回的是当前可用fd中的一个最小值。dup2允许我们通过参数filedes2指定返回的fd。如果filedes2是一个以打开的fd,则先关闭它;如果filedes和filedes2相等,则直接返回filedes2。
这些函数返回的新文件描述符与参数 filede s共享同一个文件表项。
另外一个复制fd的方法是通过fcntl函数,
dup(filedes);等价于fcntl(filedes, F_DUPFD, 0);
类似地,dup2(filedes, filedes2);等价于close(filedes2);fcntl(filedes, F_DUPFD, filedes2);
对后一种情况来讲,dup2并不完全等价于close后面跟上fcntl。dup2是一个原子操作。
sync, fsync, and fdatasync Functions
Traditional implementations of the UNIX System have a buffer cache or page cache in the kernel through which most disk I/O passes. When we write data to a file, the data is normally copied by the kernel into one of its buffers and queued for writing to disk at some later time. This is called delayed write.
The kernel eventually writes all the delayed-write blocks to disk, normally when it needs to reuse the buffer for some other disk block. To ensure consistency of the file system on disk with the contents of the buffer cache, the sync, fsync, and fdatasync functions are provided.
#include <unistd.h>
int fsync(int filedes);
int fdatasync(int filedes);
Returns: 0 if OK, 1 on error
void sync(void);
The sync function simply queues all the modified block buffers for writing and returns; it does not wait for the disk writes to take place.
The function sync is normally called periodically (usually every 30 seconds) from a system daemon, often called update. This guarantees regular flushing of the kernel's block buffers. The command sync(1) also calls the sync function.
The function fsync refers only to a single file, specified by the file descriptor filedes, and waits for the disk writes to complete before returning. The intended use of fsync is for an application, such as a database, that needs to be sure that the modified blocks have been written to the disk.
The fdatasync function is similar to fsync, but it affects only the data portions of a file. With fsync, the file's attributes are also updated synchronously.
fcntl Function
The fcntl function can change the properties of a file that is already open.
#include <fcntl.h>
int fcntl(int filedes, int cmd, ... /* int arg */ );
Returns: depends on cmd if OK (see following), 1 on error
The fcntl function is used for five different purposes.
- Duplicate an existing descriptor (cmd = F_DUPFD)
- Get/set file descriptor flags (cmd = F_GETFD or F_SETFD)
- Get/set file status flags (cmd = F_GETFL or F_SETFL)
- Get/set asynchronous I/O ownership (cmd = F_GETOWN or F_SETOWN)
- Get/set record locks (cmd = F_GETLK, F_SETLK, or F_SETLKW)
/dev/fd
比较新的系统都提供名为/dev/fd的目录,其目录项是名为 0、1、2等的文件。打开文件/dev/fd/n等效于复制描述符 n (假定描述符n是打开的)。
[Unix.C]文件I/O的更多相关文章
- 在linux下,去除^M,将windows格式文件(dos文件)改为unix格式文件
在Windows系统下编辑的文件,换行符回车的格式为'\r\n',在linux系统下,回车的格式为'\n',在Windows下编辑的文本文件在上传至linux服务器时,回车'\r\n'就显示成^M+' ...
- 如何用python在Windows系统下,生成UNIX格式文件
平时测试工作中,少不了制造测试数据.最近一个项目,我就需要制造一批可在UNIX下正确读取的文件.为确保这批文件能从FTP下载成功,开发叮嘱我:“文件中凡是遇到换行,换行符必须是UNIX下的LF,而不是 ...
- UNIX设备文件
UNIX和Linux中比较重要的三个设备文件是:/dev/console,/dev/tty和/dev/null. 0 /dev/console 这个设备代表的是系统控制台,错误信息和诊断信息通常会被发 ...
- Unix/Linux文件类型及访问权限
在Linux系统中,有7种文件类型. 普通文件 (regular file) 目录文件 (directory) 链接文件 (symbolic link) 管道文件 (FIFO) 套接字文件 (sock ...
- unix中文件I/O
在unix中可用的文件I/O函数包含打开文件,读文件,写文件等. Unix系统中的大多数文件I/O须要用到5个函数:open,read,write,lseek,close. 这里要说明的是read,w ...
- Unix 复制文件至指定目录
cp /gaps/log/20160504/bxdx_20160504.log.Z /home 将/gaps/log/20160504/bxdx_20160504.log.Z 文件复制到home路 ...
- unix解释器文件详解
exec执行普通文件和解释器文件的区别 2014-11-15 23:52:45 分类: LINUX exec执行普通文件和解释器文件的区别 ——lvyilong316 1. 从一个问题开始 首先要从项 ...
- Linux/UNIX数据文件和信息系统
数据文件和信息系统 密码文件 在存储/etc/passwd在.以下功能可以用来获得密码文件条目. #include <sys/types.h> #include <pwd.h> ...
- Linux/UNIX之文件和文件夹(2)
文件和文件夹(2) link.ulink.remove和rename函数 #include <unistd.h> int link(const char *oldpath, const c ...
随机推荐
- wpf viewmodel之间的通信
使用Prism第三方框架实现ViewModel之间的通信 创建类继承自UnityBootstrapper public class Bootstrapper : UnityBootstrapper { ...
- c语言学习之基础知识点介绍(十):内存空间模型、地址解释及指针变量
一.内存 /* 内存: 存在内存里的. 内存分了N多个小空间,每个小空间1个字节 每个小空间有它自己的地址.每个地址之间差1 int类型占用4个字节,等于占了4个空间(有4个地址),不需要记住4个地址 ...
- AUTOTRACE Statistics常用列解释
AUTOTRACE Statistics常用列解释 序号 列名 解释 1 db block gets 从buffer cache中读取的block的数量 2 consistent gets 从buff ...
- 读书笔记之 - javascript 设计模式 - 接口、封装和链式调用
javascript 采用设计模式主要有下面的三方面原因: 可维护性:设计模式有助于降低模块之间的耦合程度.这使代码进行重构和换用不同的模块变得容易,也使程序员在大型项目中合作变得容易. 沟通:设计模 ...
- [学习笔记]设计模式之Composite
为方便读者,本文已添加至索引: 设计模式 学习笔记索引 写在前面 在Composite(组合)模式中,用户可以使用多个简单的组件以形成较大的组件,而这些组件还可能进一步组合成更大的.它重要的特性是能够 ...
- Android Binder机制简单了解
Binder -- 一种进程间通信(IPC)机制, 基于OpenBinder来实现 毫无疑问, 老罗的文章是不得不看的 Android进程间通信(IPC)机制Binder简要介绍和学习计划 浅谈Ser ...
- Python 手册——开胃菜
如果你写过大规模的Shell脚本,应该会有过这样的体会:你还非常想再加一些别的功能进去,但它已经太大. 太慢.太复杂了:或者这个功能需要调用一个系统函数,或者它只适合通过C来调用……通常这些问题还不足 ...
- u-boot烧写Linux及系统整个启动过程
一.烧写文件 u-boot: u-boot.bin linux kernel: uImage Filesystem: root.bin(yaffs) 二.烧写步骤 1.烧写u-boot tftp 0 ...
- 目前最流行的网页自动运行EXE文件
大家对木马都不陌生了,它可能要算是计算机病毒史上最厉害的了,相信会使木马的人千千万万,但是有很多人苦于怎么把木马发给对方,现在随着计算机的普及,在网络上我相信很少有人会再轻易的接收对方的文件了,所以网 ...
- ARC - MRC
1. 选择工程 ---> build phases --> .m中添加 -fno-objc-arc