分类: LINUX
2011-12-27 10:02:04
++++++APUE读书笔记-03文件输入输出(1)++++++
简介
================================================
我们以文件输入输出操作函数为开始,对UNIX系统进行讲解。文件输入输出函数包括:打开文件、读取文件、写文件等等。大多数UNIX系统上面的文件输入输出操作,都可以使用5个函数来完成:open,read,write,lseek,以及close。我们之后也会看到,对读写文件时候,设置不同的缓存大小会有什么效果。
本章所述的函数一般都被称作无I/O缓冲的函数,和我们第5章所讲述的标准I/O函数相对。非缓冲的意思就是说,每次read或者write会产生内核中的一次系统调用。这些非缓冲的I/O函数并不是ISO C的一个部分,但是却是 POSIX.1 和 the Single UNIX Specification的一个部分。
当我们讲到多进程之间的资源共享的时候,原子操作会变得非常重要。我们在讨论文件I/O以及open函数的参数的时候会对此进行讲述。这会就引出了多个进程之间如何共享文件,以及内核包含什么样的数据结构,这样的话题。讲述这些之后,我们会继续讲述dup,fcntl,sync,fsync和ioctl函数。
参考:
1、文件描述符号
================================================
内核用文件描述符来引用所有打开文件。文件描述符是一个非负整数。当打开已有文件或创建新文件时,内核就向进程返回一个文件描述符。当读、写一个文件时,用open或creat返回的文件描述符标识该文件,将其作为参数传送给read或write。
按照惯例,UNIX shell使用文件描述符0表示进程的标准输入,文件描述符1表示标准输出,文件描述符2表示标准错误输出。按照这个惯例,在POSIX.1应用程序中,幻数0、1、2应被代换成符号常数STDIN_FILENO,STDOUT_FILENO和STDERR_FILENO,这样能够提高程序的可移植特性。这些常数都定义在头文件
后面将对基本文件操作函数做简单介绍,具体可以运行"man 2
参考:
2、open函数
================================================
调用open函数可以打开或创建一个文件。其具体声明如下:
#include
int open(const char *pathname, int oflag, ... /* mode_t mode */ );
返回:如果成功返回文件描述符号,如果错误返回1。
(注意,这里出错的时候返回值为1,经过网上搜索发现,一般错误的时候,返回-1,也就是说,前面说的“如果错误返回1”中的“1”其实是布尔值,其实际值一般为-1,并且产生错误的时候,还会将错误编码记录到errno全局变量中。本书好多地方都这样说返回值,虽然简洁,但是可能会带来一些困扰所以读者应当注意,具体需要细究的时候,还需亲自查找手册上对错误情况返回值的说明)
这里,第三个参数写为 “...”,这是ANSI C表示余下参数的数目和类型可以变化的方法。pathname是要打开或创建的文件的名字。oflag参数可用来说明此函数的多个选择项。
oflag必须指定如下三个值之一:
a)O_RDONLY 只读打开。
b)O_WRONLY 只写打开。
c)O_RDWR 读、写打开。
下列常数则是可选择的:
a)O_APPEND 每次写时都加到文件的尾端。
b)O_CREAT 若此文件不存在则创建它。使用此选择项时,需同时指明第三个参数 mode,以说明该新文件的存取许可权位。
c)O_EXCL 如果同时指定了O_CREAT,而文件已经存在,那么就出错。这样可以测试文件是否存在,不存在则创建,并且这个操作是原子的。
d)O_TRUNC 如果此文件存在,而且为只读或只写方式打开,则将其长度截短为0。
e)O_NOCTTY 如果pathname指的是终端设备,则不将此设备分配作为此进程的控制终端。
f)O_NONBLOCK 如果pathname指的是一个FIFO、一个块特殊文件或一个字符特殊文件,则本次打开操作和后续的 I / O操作设置非阻塞方式。
g)O_SYNC 使每次write都等到物理I/O操作完成。
由open返回的文件描述符一定是最小的没有使用的描述符数字。如果一个应用程序先关闭标准输出(通常是文件描述符1 ),然后打开另一个文件,那么就能知道该文件一定会在文件描述符1上打开,这个方法也是一个很常用的方法。后面讲到dup2函数时,会了解到有更好的方法来保证在一个给定的描述符上打开一个文件。
当用append标记打开文件的时候,还是可以用lseek定位到任何地方来读取文件内容的,但是如果写的话,文件的offset会自动地定位到文件的结尾并且写。也就是说,用append的话,写操作不会写到除了结尾之外的地方(即使是用lseek定位也不会,这里的内容最好也参考原书3章13节,以及练习3.6)。
参考:
3、create函数
================================================
也可用creat函数创建一个新文件。声明如下:
#include
int creat(const char *pathname, mode_t mode);
返回:如果成功返回一个只写的文件描述符浩,如果错误返回1。
此函数等效于:
open(pathname,O_WRONLY|O_CREAT|O_TRUNC, mode)。
参考: