`

不带缓冲的文件I/O之open

阅读更多
        本节介绍不带缓冲的文件I/O中如何打开或创建一个文件,这可以用以下两个函数实现:
#include <fcntl.h>

int open(const char *path, int oflag, ... /* mode_t mode */);
int openat(int fd, const char *path, int oflag, ... /* mode_t mode */);
    /* 两个函数的返回值:若成功,返回文件描述符;否则返回 -1 */

        最后一个参数“...”表明余下的参数的数量和类型是可变的。对于 open 函数而言,仅当创建新文件时才使用。
        path 参数是要打开或创建的文件的名字。oflag 参数可用来说明此函数的多个选项。用下列一个或多个常量进行“或”运算构成(都在头文件 <fcntl.h> 中定义):
    O_RDONLY / 0:只读打开。
    O_WRONLY / 1:只写打开。
    O_RDWR / 2:读、写打开。
    O_EXEC:只执行打开。
    O_SEARCH:只搜索打开(应用于目录)。O_SEARCH 常量的目的在于在打开目录时验证它的搜索权限,对目录的文件描述符的后续操作就不需要再次检查该目录的搜索权限。不过多数系统目前并不支持该选项。
        以上这5个常量中必须且只能指定一个,下列常量则是可选的:
    O_APPEND:每次写时都追加到文件的尾端。
    O_CLOEXEC:把 FD_CLOEXEC 常量设置为文件描述符标志。
    O_CREAT:若此文件不存在则创建它。使用此选项时,open/openat 函数需同时说明第 3/4 个参数 mode,用以指定新文件的访问权限位。
    O_DIRECTORY:若 path 引用的不是目录,则出错。
    O_EXCL:若同时指定了 O_CREAT,而文件已经存在,则出错。这可以用来原子性地测试和创建文件。
    O_NOCTTY:如果 path 引用的是终端设备,则不将该设备分配作为此进程的控制终端。
    O_NOFOLLOW:若 path 引用的是一个符号链接,则出错。
    O_NONBLOCK:若 path 引用的是一个 FIFO、一个块特殊文件或一个字符特殊文件,则此选项为文件的本次打开操作和后续的 I/O 操作设置非阻塞方式。
    O_SYNC:使每次 write 等待物理 I/O 操作完成,包括由该 write 操作引起的文件属性更新所需的 I/O。
    O_TRUNC:若此文件存在,而且为只写或读-写成功打开,则将其长度截断为 0。
    O_TTY_INIT:如果打开一个还未打开的终端设备,设置非标准 termios 参数值,使其符合 Single UNIX Specification。
        下面两个标志也是可选的,它们是 Single UNIX Specification 以及 POSIX.1 中同步输入和输出选项的一部分:
    O_DSYNC:使每次 write 要等到物理 I/O 操作完成,但是如果该写操作并不影响读取刚写入的数据,则不需要等待文件属性被更新。该选项和 O_SYNC 标志有微妙的区别:仅当文件属性需要更新以反映文件数据变化(例如,更新文件大小以反映文件中包含了更多的数据)时,O_DSYNC 才影响文件属性。而设置 O_SYNC 后,数据和属性总是同步更新。当文件用 O_DSYNC 打开,在重写其现有的部分内容时,文件时间属性不会同步更新。而用 O_SYNC 时,那么对该文件的每一次 write 都将在 write 返回前更新文件时间。这与是否改写现有字节或追加写文件无关。
    O_RSYNC:使每一个以文件描述符作为参数进行的 read 操作等待,直至所有对文件同一部分挂起的写操作都完成。

        fd 参数把 open 和 openat 函数区分开,共有3种可能性:
    1、path 指定的是绝对路径名,在这种情况下,fd 参数被忽略,openat 函数就相当于 open 函数。
    2、path 指定的是相对路径名,fd 参数指出了相对路径名在文件系统中的开始地址。fd 参数是通过打开相对路径名所在的目录来获取。
    3、path 指定了相对路径名,fd 参数具有特殊值 AT_FDCWD。此时路径名在当前工作目录中获取,openat 函数在操作上与 open 函数类似。

        openat 函数是 POSIX.1 中新增的函数之一,希望解决两个问题:
    1、让线程可以使用相对路径名打开目录中的文件,而不再只能打开当前工作目录。因为同一进程中的所有线程共享相同的当前工作目录,因此很难让同一进程的多个不同线程在同一时间工作在不同的目录中。
    2、可以避免 TOCTTOU(time-of-check-to-time-of-use)错误。该错误的基本思想是:如果有两个基于文件的函数调用,其中第二个依赖于第一个的结果,那么程序是脆弱的。因为两个调用并不是原子操作,在两个调用之间文件可能改变了,这样也就造成了第一个调用的结果不再有效,使得程序最终的结果是错误的。文件系统命名空间中的 TOCTTOU 错误通常处理的就是那些颠覆文件系统权限的小把戏,这些小把戏通过骗取特权程序降低特权文件的权限控制或者让特权文件打开一个安全漏洞等方式进行。
分享到:
评论

相关推荐

    嵌入式Linux下文件I/O

    文件I/O函数如`open`、`close`、`read`、`write`等直接操作内核级的文件描述符,不带缓冲,适合资源受限的嵌入式系统。"文件IO.rar"中可能包含了这些函数的实例,展示了如何在嵌入式Linux下进行低级文件操作。 4. ...

    APUE(UNIX环境高级编程)——文件I/O篇

    这些函数构成了不带缓存的I/O(unbuffered I/O),即每次读写操作都会直接调用内核的系统调用,确保数据的实时传输。不带缓存的I/O不是ANSI C标准的一部分,但属于POSIX.1和XPG3标准,因此在UNIX和类UNIX系统中广泛...

    文件io编程

    不带缓存的I/O函数如open、read、write等,直接与文件系统交互,适用于一些特殊场景,比如需要确保数据即时写入磁盘或直接与硬件设备通信的场合。 Linux中的设备文件是一种特殊的文件,它对应于系统中的硬件设备。...

    《Linux高级系统编程》教学教案—02输入输出.pdf

    文件I/O则是直接通过系统调用,如`read`和`write`,来与文件交互,它通常不带缓冲或者具有更直接的控制。 系统调用是操作系统提供给用户程序的一个低级别接口,允许程序请求操作系统执行特定服务。在Linux系统中,...

    深究标准IO的缓存

    无缓冲I/O,如使用open和read系统调用,直接对文件进行操作,不进行缓存;带缓冲I/O,如fopen和fwrite,数据首先写入用户空间的缓存区,当缓存区满或者执行fflush时,再将数据写入内核缓冲区,最终由内核将数据写入...

    文件基础学习资料

    标准I/O操作会由C运行时库管理缓冲区,从而减少系统调用的次数,提高效率,而底层的文件I/O则是不带缓冲的,直接与内核交互。 UNIX系统中,程序是指存放在磁盘文件中的可执行文件,而进程则是程序的执行实例。通过...

    Linux 系统IO

    不带缓冲的I/O意味着每次函数调用都会直接导致一个系统调用,这种方式效率较低,但能提供更精确的控制。 在Linux中,文件被视为一组相关联元素的有序序列,这一概念被称为“一切皆文件”。这意味着无论是文本、二...

    Unix环境高级编程3

    在文件I/O中,"不带缓存的I/O"(unbuffered I/O)是指每次read和write操作都会直接调用内核的系统调用,这意味着数据的传输是实时且无缓冲的。这种方式对于需要精确控制数据流的应用来说尤其重要,但效率可能较低。...

    实验5Linux文件操作之带缓存和非缓冲文件的读写.doc

    实验内容涉及了`open()`, `read()`, `write()`, 和 `fcntl()`等关键函数的使用,这些都是Linux文件I/O的基础。 1. **文件操作基础** - `open()`: 这个函数用于打开一个已存在的文件或创建一个新文件。在实验中,`O...

    UNIX环境高级编程03

    不带缓存的I/O意味着每次read和write操作都会直接调用内核级别的系统调用,这虽然效率较低,但提供了更直接的控制。这些函数虽非ANSI C标准,但属于POSIX.1和XPG3标准,因此在跨平台的UNIX开发中至关重要。 在多...

    UNIX环境高级编程003

    它们不涉及缓冲机制,因此被称为不带缓冲的I/O。 2. **文件描述符**:文件描述符是内核用来标识打开文件的非负整数值。当进程打开或创建文件时,内核返回一个文件描述符。标准的文件描述符有0(标准输入)、1(标准...

    Linux_C_io.rar_linux omap

    3. **缓冲I/O**:C标准库提供了`fread()`和`fwrite()`函数,它们处理内存缓冲区与文件之间的数据传输,通常比`read()`和`write()`更高效。 4. **文件定位**:`lseek()`函数可以改变文件指针的位置,允许随机访问...

    Linux系统调用和文件IO.ppt

    不带缓存的I/O操作意味着每次read和write都会触发一次系统调用,直接与内核交互。这些函数属于POSIX标准,而非ANSI C标准。 文件描述符是Linux中表示已打开文件的唯一标识,是一个非负整数。当打开或创建文件时,...

    嵌入式 LINUX 应用程序开发标准教程

    ### 嵌入式LINUX应用程序开发之文件I/O编程详解 #### 一、系统调用与用户编程接口(API) 在《嵌入式LINUX应用程序开发标准教程》的第六章中,作者华清远见首先介绍了Linux系统调用与用户编程接口(API)的基本概念...

    软件设计的编程规范和技术文档

    3. **不带缓存的I/O函数**: - **open函数** 用于打开或创建文件,接受文件名、打开模式(如只读、只写、读写)和权限作为参数,返回文件描述符。 - **read函数** 从文件描述符指定的文件读取数据。 - **write...

    进程之间的调用基于arm开发

    Unbuffered I/O 函数是一组系统调用函数,提供了基本的输入/输出操作,不带缓冲区。这些函数包括 `open`、`read`、`write`、`close` 等。Unbuffered I/O 函数的优点是可以提供更好的性能和更低的系统调用延迟,但是...

Global site tag (gtag.js) - Google Analytics