分类: 系统运维
2012-03-28 12:49:12
通过调用open函数可以打开或创建一个文件:
#include
int open(const char *pathname, int oflga, .../* mode_t mode */ );
如果成功返回文件描述符,错误返回-1。
第三个参数为...,是ISO C表示剩余参数的数量和类型可变的方法。对于这个函数来说,第三个参数仅当创建一个文件时使用,我们稍后讨论。我们在函数原型中把这个参数作为一个注释。
pathname是打开或创建的文件的名字,这个函数有一个选项群,由参数oflag描述。这个参数由一个或多个以下定义在
O_RDONLY:只读方式打开;
O_WRONLY:只写方式打开;
O_RDWR:读写方式打开。
为了与早期的程序兼容,多数实现把O_RDONLY定义为0、O_WRONLY定义为1、而O_RDWR定义为2。
这三个常量必须有且只能有一个被指定。以下的常量是可选的:
O_APPEND:每次写时添加到文件末尾;
O_CREAT:创建这个文件如果它不存在。这个选项需要为open函数提供第三个参数--打开模式--来指定这个新建文件的访问权限位
O_EXCL:如果O_CREAT也同时被指定而文件已存在的话会产生一个错误 。这个文件是否存在的测试以及当文件不存在时文件的创建是一个原子操作。
O_TRUNC:如果文件存在而且它以只写或读写方式被成功打开的话,把它的长度截为0;
O_NOCTTY:如果路径名指向一个终端设备,则不要为这个进程把这个设备作为控制终端分配;
O_NONBLOCK:如果文件名指向一个FIFO,一个块特殊文件或一个字符特殊文件,这个选项为打开文件及后续I/O设置非阻塞模式。
在系统V的早期版本,有个O_NDELAY(no
delay)标志。这个选项和O_NONBLOCK(nonblocking)选项类似,但是会为一个读操作的返回值产生歧义。如果没有数据可从一个管
道、FIFO或设备读入时,no-delay选项导致一个读操作返回0,这与碰到文件结束时返回0产生冲突。基于SVR4的系统仍然支持带有早期语义的
no-delay选项,但是新的程序应该使用nonblocking选项。
下面三个标志同样是可选的。它们是SUS(也是POSIX.1)的同步输入输出选项:
O_DSYNC:让每个write都等待物理I/O的完成,但如果不影响读取已写入的数据,则不等待文件属性的更新;
O_RSYNC:让每个在文件描述符上的read操作都等待,直到任何正在执行的在文件的相同部分上的写操作都结束为止;
O_SYNC:让每个write都等待物理I/O的完成,包括write引起的文件属性更新的修改。
O_DSYNC和O_SYNC标志相似,但稍微有些不同。O_DSYNC标志仅当文件属性的更新反应了文件数据的改变时才会影响文件的属性(例如,更新文
件大小来反映更多的数据。)对于O_SYNC标志,数据和属性一直都同步地更新。当使用O_DSYNC选项覆写一个文件已经存在的部分时,文件的时间不会
同步更新。相反,如果我们以O_SYNC标志打开这个文件,每个write都会在write返回前更新这个文件的时间,而不管我们在覆写存在的字节还是添
加到这个文件。
Solaris 9支持这三个标志。FreeBSD 5.2.1和Mac OS X
10.3有另一个与O_SYNC做相同事情的标志(O_FSYNC)。因为这两个标志是一样的,所以FreeBSD
5.2.1把它们定义成相同的值(但是很奇怪的是,Mac OS 10.3没有定义O_SYNC)。FreeBSD 5.2.1和Mac OS X
10.3没有支持O_DSYNC和O_RSYNC标志。Linux 2.4.22把这两个标志等同视为O_SYNC。
open返回的文件描述符被确保为可用描述符的最小值。一些应用程序利用这个事实在标准输入、标准输出或标准错误上打开一个新的文件。例如,一个程序可能
关闭标准输出--通常情况下是文件描述符1--然后打开另一个文件,并知道它将作为描述符1被打开。我们将会看到让文件在给定描述符上打开一个文件的更好
方法:dup2函数。
文件名和路径名截断(Filename and Pathname Truncation)
如果NAME_MAX是14而我们尝试在当前目录创建一个文件名包含15个字符的新文件会怎么样?System
V的早期版本,比如SVR2,允许这种事发生,同时静默地把14位后的字符截断。基于BSD的系统返回一个错误状态,把errno设为
ENAMETOOLONG。静默截断文件名会引起不只简单地影响文件创建的问题。如果NAME_MAX是14而有一个存在的名字为刚好14个字符的文件,
任何接受路径参数的函数比如open或stat都无法知道文件原始的名字,因为原始名可能已经被截断了。
POSIX.1规定,常量_POSIX_NO_TRUNC决定是裁断长文件名和长路径名还是返回一个错误。是否返回错误是一个存在很久的问题。比如,基于
SVR4的系统不会为传统的System V文件系统(S5)产生错误。然而,基于SVR4的系统却不会为BSD风格文件系统(UFS)产生错误。
另一个例子,Solaris为UFS返回错误,但不为PCFS(DOS兼容文件系统)返回错误,因为DOS静默地截断不符合8.3格式的文件名。
基于BSD的系统和Linux总是会返回错误。
如果_POSIX_NO_TRUNC起效,当整个文件名超过PATH_MAX或路径名中的任何文件名超过NAME_MAX,errno会被设为ENAMETOOLONG,而且一个错误状态会被返回。