大多数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的更多相关文章

  1. 在linux下,去除^M,将windows格式文件(dos文件)改为unix格式文件

    在Windows系统下编辑的文件,换行符回车的格式为'\r\n',在linux系统下,回车的格式为'\n',在Windows下编辑的文本文件在上传至linux服务器时,回车'\r\n'就显示成^M+' ...

  2. 如何用python在Windows系统下,生成UNIX格式文件

    平时测试工作中,少不了制造测试数据.最近一个项目,我就需要制造一批可在UNIX下正确读取的文件.为确保这批文件能从FTP下载成功,开发叮嘱我:“文件中凡是遇到换行,换行符必须是UNIX下的LF,而不是 ...

  3. UNIX设备文件

    UNIX和Linux中比较重要的三个设备文件是:/dev/console,/dev/tty和/dev/null. 0 /dev/console 这个设备代表的是系统控制台,错误信息和诊断信息通常会被发 ...

  4. Unix/Linux文件类型及访问权限

    在Linux系统中,有7种文件类型. 普通文件 (regular file) 目录文件 (directory) 链接文件 (symbolic link) 管道文件 (FIFO) 套接字文件 (sock ...

  5. unix中文件I/O

    在unix中可用的文件I/O函数包含打开文件,读文件,写文件等. Unix系统中的大多数文件I/O须要用到5个函数:open,read,write,lseek,close. 这里要说明的是read,w ...

  6. Unix 复制文件至指定目录

    cp /gaps/log/20160504/bxdx_20160504.log.Z   /home 将/gaps/log/20160504/bxdx_20160504.log.Z 文件复制到home路 ...

  7. unix解释器文件详解

    exec执行普通文件和解释器文件的区别 2014-11-15 23:52:45 分类: LINUX exec执行普通文件和解释器文件的区别 ——lvyilong316 1. 从一个问题开始 首先要从项 ...

  8. Linux/UNIX数据文件和信息系统

    数据文件和信息系统 密码文件 在存储/etc/passwd在.以下功能可以用来获得密码文件条目. #include <sys/types.h> #include <pwd.h> ...

  9. Linux/UNIX之文件和文件夹(2)

    文件和文件夹(2) link.ulink.remove和rename函数 #include <unistd.h> int link(const char *oldpath, const c ...

随机推荐

  1. css-a:visited

    如下代码: <a href="#">链接地址</a> 如果属性 href的设置为'#',则鼠标滑过(即使没有点击',也算成'visited'.而对于 hre ...

  2. PL/SQL 访问网页(get or post方式)

    在我们开发plsql程序的过程中,有时候难免要访问一些外部网站的数据.这个时候我们就要用到utl_http包. 使用utl_http包前需要注意的是,当前的用户下是否有访问外部网络的权限. 如下是自己 ...

  3. JavaScript上下文和闭包

    "this" 上下文 上下文通常是取决于一个函数如何被调用.当函数作为对象的方法被调用时,this 被设置为调用方法的对象: var object = { foo: functio ...

  4. linux系统 web在线日志分析

    线上环境出现问题时,不能像本地环境一样,断点查找问题,只有根据日志分析来定位问题,当然有资深的经验也是可以的,哈哈. 最基本的就是cat命令,可以通过cat filename,来查看文件全部内容, & ...

  5. apache日志文件 accesslog

    因为想要看到apache的日志记录用户请求某个页面所花的时间,需要添加额外参数才会记录,所以临时查了下哦..记下来了 在httpd.conf里可以看到一行这样的配置 LogFormat "% ...

  6. RegularExpressionValidator 常用

    RegularExpressionValidator 控件用于验证输入值是否匹配正则表达式指定的模式 属性: ControlToValidate="要验证的控件名称" Valida ...

  7. 10300 - Ecological Premium

    Problem A Ecological Premium Input: standard input Output: standard output Time Limit: 1 second Memo ...

  8. java怎么连接sql server,需要注意的几点

    一.JAVA连接SQL的语句    JAVA连接SQL2000语句为:  Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");  Drive ...

  9. nutch getOutLinks 外链的处理

    转载自: http://blog.csdn.net/witsmakemen/article/details/8067530 通过跟踪发现,Fetcher获得网页解析链接没有问题,获得了网页中所有的链接 ...

  10. navBar

    改变NavgationBar的颜色: [[UINavigationBar appearance] setBarTintColor:[UIColor blackColor]]; 改变NavgationB ...