open() - Unix,Linux系统调用
Tutorials Point


  Unix入门
  Unix Shell编程
  高级Unix
  Unix有用参考
  Unix有用资源
  精选阅读

版权所有 © 2014 tutorialspoint



  首页     参考资料     讨论论坛     关于TP  

open() - Unix,Linux系统调用


previous next AddThis Social Bookmark Button

广告

名称

open, creat - 打开并可能创建文件或设备

概要

#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 

int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); int creat(const char *pathname, mode_t mode);

描述

给定文件的路径名open() 返回一个文件描述符,一个小的非负整数,用于后续的系统调用(read(2), write(2), lseek(2), fcntl(2) 等)。成功调用返回的文件描述符将是当前进程中未打开的最低编号的文件描述符。

新的文件描述符设置为在 execve(2) 中保持打开状态(即,fcntl(2) 中描述的 FD_CLOEXEC 文件描述符标志最初被禁用)。文件偏移量设置为文件的开头(参见 lseek(2))。

调用 open() 会创建一个新的打开的文件描述,这是系统范围内打开文件表中的一个条目。此条目记录文件偏移量和文件状态标志(可通过 fcntl() F_SETFL 操作进行修改)。文件描述符是对这些条目之一的引用;如果随后删除路径名或将其修改为引用不同的文件,则此引用不受影响。新的打开的文件描述最初不与任何其他进程共享,但可以通过 fork(2) 实现共享。

参数flags必须包含以下访问模式之一:O_RDONLYO_WRONLYO_RDWR。这些分别请求以只读、只写或读写方式打开文件。

此外,零个或多个文件创建标志和文件状态标志可以按位flags中。文件创建标志O_CREATO_EXCLO_NOCTTYO_TRUNC文件状态标志是下面列出的所有其余标志。这两组标志的区别在于,可以使用 fcntl(2) 检索和(在某些情况下)修改文件状态标志。文件创建标志和文件状态标志的完整列表如下所示

标签描述
O_APPEND
 文件以追加模式打开。在每次write() 之前,文件偏移量将定位到文件的末尾,就像使用lseek() 一样。如果多个进程同时将数据追加到同一个文件中,O_APPEND 可能会导致 NFS 文件系统上的文件损坏。这是因为 NFS 不支持追加到文件,因此客户端内核必须模拟它,而这无法在没有竞争条件的情况下完成。
O_ASYNC
 启用信号驱动的 I/O:当此文件描述符上的输入或输出变为可能时,生成一个信号(默认为 SIGIO,但这可以通过 fcntl(2) 更改)。此功能仅适用于终端、伪终端、套接字和(自 Linux 2.6 起)管道和 FIFO。有关更多详细信息,请参见 fcntl(2)。
O_CREAT
 如果文件不存在,则将创建它。文件的拥有者(用户 ID)设置为进程的有效用户 ID。组所有权(组 ID)设置为进程的有效组 ID 或父目录的组 ID(取决于文件系统类型和挂载选项以及父目录的模式,例如,请参见 ext2 文件系统的挂载选项bsdgroupssysvgroups,如 mount(8) 中所述)。
O_DIRECT
 尝试最大限度地减少此文件的 I/O 对缓存的影响。通常,这会降低性能,但在特殊情况下很有用,例如当应用程序自己进行缓存时。文件 I/O 直接在用户空间缓冲区之间进行。I/O 是同步的,即在 read(2) 或 write(2) 完成时,保证数据已传输。在 Linux 2.4 下,传输大小和用户缓冲区以及文件偏移量的对齐必须都是文件系统逻辑块大小的倍数。在 Linux 2.6 下,对齐必须适合设备的块大小。

raw(8) 中描述了块设备的一种语义上相似(但已弃用)的接口。

O_DIRECTORY
 如果路径名不是目录,则导致打开失败。此标志是 Linux 特定的,是在内核版本 2.1.126 中添加的,用于避免在对 FIFO 或磁带设备调用 opendir(3) 时出现拒绝服务问题,但不应在 opendir 的实现之外使用。
O_EXCL 当与 O_CREAT 一起使用时,如果文件已存在,则这是一个错误,并且 open() 将失败。在这种情况下,符号链接存在,无论它指向哪里。O_EXCL 在 NFS 文件系统上已损坏;依赖它来执行锁定任务的程序将包含竞争条件。使用锁定文件执行原子文件锁定的解决方案是在同一文件系统上创建唯一文件(例如,包含主机名和 pid),使用 link(2) 创建指向锁定文件的链接。如果 link() 返回 0,则锁定成功。否则,对唯一文件使用 stat(2) 检查其链接计数是否已增加到 2,在这种情况下,锁定也成功。
O_LARGEFILE
 (LFS)允许打开大小无法用off_t表示(但可以用off64_t表示)的文件。
O_NOATIME
 (自 Linux 2.6.8 起)在读取文件时不更新文件上次访问时间(inode 中的 st_atime)。此标志旨在供索引或备份程序使用,在其使用中可以显著减少磁盘活动量。此标志可能并非对所有文件系统都有效。一个例子是 NFS,其中服务器维护访问时间。
O_NOCTTY
 如果路径名指的是终端设备——参见tty(4)——即使进程没有一个,它也不会成为进程的控制终端。
O_NOFOLLOW
 如果路径名是符号链接,则打开失败。这是 FreeBSD 的扩展,在版本 2.1.126 中添加到 Linux。路径名中较早的组件中的符号链接仍将被遵循。
O_NONBLOCKO_NDELAY
 如果可能,则以非阻塞模式打开文件。返回的文件描述符上的 open() 或任何后续操作都不会导致调用进程等待。对于 FIFO(命名管道)的处理,另请参见 fifo(7)。有关 O_NONBLOCK 与强制文件锁和文件租约结合使用时的影响的讨论,请参见 fcntl(2)。

O_SYNC 文件以同步 I/O 方式打开。结果文件描述符上的任何 write() 都将阻塞调用进程,直到数据已物理写入底层硬件。但请参见下面的限制
O_TRUNC
 如果文件已存在并且是常规文件,并且打开模式允许写入(即 O_RDWR 或 O_WRONLY),则它将被截断为长度 0。如果文件是 FIFO 或终端设备文件,则忽略 O_TRUNC 标志。否则,O_TRUNC 的效果未指定。
打开文件后,可以使用 fcntl() 更改其中一些可选标志。

参数mode指定如果创建新文件要使用的权限。它以通常的方式由进程的 umask 修改:创建的文件的权限为 (mode & ~umask)。请注意,此模式仅适用于新创建文件的未来访问;创建只读文件的 open() 调用很可能会返回读/写文件描述符。

mode提供了以下符号常量
S_IRWXU
 00700 用户(文件所有者)具有读、写和执行权限
S_IRUSR
 00400 用户具有读权限
S_IWUSR
 00200 用户具有写权限
S_IXUSR
 00100 用户具有执行权限
S_IRWXG
 00070 组具有读、写和执行权限
S_IRGRP
 00040 组具有读权限
S_IWGRP
 00020 组具有写权限
S_IXGRP
 00010 组具有执行权限
S_IRWXO
 00007 其他用户具有读、写和执行权限
S_IROTH
 00004 其他用户具有读权限
S_IWOTH
 00002 其他用户具有写权限
S_IXOTH
 00001 其他用户具有执行权限
如果 O_CREAT 位于flags中,则必须指定mode,否则将忽略它。

creat() 等效于 open(),其中flags等于 O_CREAT|O_WRONLY|O_TRUNC

返回值

open() 和 creat() 返回新的文件描述符,如果发生错误则返回 -1(在这种情况下,errno 将被适当地设置)。

备注

请注意,open() 可以打开设备特殊文件,但 creat() 不能创建它们;请改用 mknod(2)。

在启用了 UID 映射的 NFS 文件系统上,open() 可能会返回文件描述符,但例如 read(2) 请求会被 EACCES 拒绝。这是因为客户端通过检查权限来执行 open(),但 UID 映射是在读取和写入请求时由服务器执行的。

如果文件是新创建的,则其st_atime、st_ctime、st_mtime字段(分别为上次访问时间、上次状态更改时间和上次修改时间;参见stat(2))将设置为当前时间,其父目录的st_ctime和st_mtime字段也是如此。否则,如果由于O_TRUNC标志修改了文件,则其st_ctime和st_mtime字段将设置为当前时间。

错误

标签描述
EACCES 不允许请求的文件访问,或者拒绝搜索pathname路径前缀中某个目录的权限,或者文件尚不存在且不允许对父目录进行写访问。(另请参见path_resolution(2)。)
EEXIST pathname已存在,并且使用了O_CREATO_EXCL
EFAULT pathname指向您可访问的地址空间之外。
EISDIR pathname指向一个目录,并且请求的访问涉及写入(即,设置了O_WRONLYO_RDWR)。
ELOOP 解析pathname时遇到过多符号链接,或者指定了O_NOFOLLOWpathname是符号链接。
EMFILE 进程已打开最大数量的文件。
ENAMETOOLONG
  pathname太长。
ENFILE 已达到系统对打开文件总数的限制。
ENODEV pathname指向一个设备特殊文件,并且不存在相应的设备。(这是Linux内核错误;在这种情况下,必须返回ENXIO。)
ENOENT 未设置O_CREAT,并且指定的文件不存在。或者,pathname中的目录组件不存在或是不存在的符号链接。
ENOMEM 可用内核内存不足。
ENOSPC 要创建pathname,但是包含pathname的设备没有足够空间容纳新文件。
ENOTDIR
 pathname中用作目录的组件实际上不是目录,或者指定了O_DIRECTORYpathname不是目录。
ENXIO 设置了O_NONBLOCK | O_WRONLY,指定的文件是FIFO,并且没有进程打开该文件以进行读取。或者,该文件是设备特殊文件,并且不存在相应的设备。
EOVERFLOW
  pathname指向一个常规文件,太大而无法打开;请参见上面的O_LARGEFILE。
EPERM 指定了O_NOATIME标志,但调用者的有效用户ID与文件所有者不匹配,并且调用者没有特权(CAP_FOWNER)。
EROFS pathname指向只读文件系统上的文件,并且请求了写访问。
ETXTBSY
  pathname指向当前正在执行的可执行映像,并且请求了写访问。
EWOULDBLOCK
 指定了O_NONBLOCK标志,并且在文件上持有不兼容的租约(参见fcntl(2))。

注意

在Linux下,O_NONBLOCK标志表示希望打开但并不一定有读取或写入的意图。这通常用于打开设备以获取用于ioctl(2)的文件描述符。

符合标准

SVr4、4.3BSD、POSIX.1-2001。O_NOATIMEO_NOFOLLOWO_DIRECTORY标志是Linux特有的。可能需要定义_GNU_SOURCE宏才能获得它们的定义。

O_RDONLY | O_TRUNC的(未定义的)效果在不同的实现中有所不同。在许多系统上,文件实际上会被截断。

O_DIRECT标志是在SGI IRIX中引入的,它具有与Linux 2.4类似的对齐限制。IRIX还有一个fcntl(2)调用来查询适当的对齐方式和大小。FreeBSD 4.x引入了相同名称的标志,但没有对齐限制。Linux内核版本2.4.10中添加了对它的支持。较旧的Linux内核会忽略此标志。可能需要定义_GNU_SOURCE宏才能获得它的定义。

错误

“O_DIRECT一直困扰我的地方在于,整个接口都很愚蠢,可能是某个精神错乱的猴子在服用某种强效精神控制药物时设计的。”——Linus

当前,调用open()时无法通过指定O_ASYNC来启用信号驱动的I/O;使用fcntl(2)来启用此标志。

限制

NFS底层的协议中存在许多缺陷,影响到O_SYNCO_NDELAY等。

POSIX提供了三种不同类型的同步I/O,分别对应于标志O_SYNCO_DSYNCO_RSYNC。目前(2.1.130)在Linux下它们都是同义词。

参见



previous next Printer Friendly

广告


  

广告



广告