linux文件I/O之 open() 函数用法

#include
#include
#include

typedef unsigned int mode_t ;

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

函数功能

打开或创建一个文件

返回值

成功返回一个新的文件描述符(指代这个打开的文件),失败则返回 -1,并设置 errno 为相对应的错误标志

参数

pathname:路径名,标识要打开的文件(或目录)(例如:"./test.txt"、"/etc/passwd")

flags:位掩码,用于指定文件的打开模式。通过 O_RDONLY(只读)、O_WRONLY(只写) 或         O_RDWR(可读可写)中的其中一个打开文件的方式 与 下面的 0 个或多个可选模式按 位或(|) 操作得到。

flags 说明
O_CREAT 若文件不存在将创建它。
O_EXCL 这个标志需要和 O_CREAT 结合在一起使用,表明如果参数 pathname 标识的文件已经存在,则打开失败,此时 errno 会被设置为 EEXIST。 换言之,这个标志确保 open() 函数就是创建新文件的。
O_NOCTTY 如果参数 pathname 引用的是终端设备,O_NOCTTY 标志表明不将该设备分配作为此进程的控制终端设备。如果 pathname 引用的不是终端设备,则此标志无效。
O_TRUNC 如果文件已经存在且为普通文件,而且打开模块又是写(即是以 O_WRONLY 或 O_RDWR 模式打开的),那么将清空文件的原有的所有内容,并将其长度设置为 0。若文件是 FIFO 或终端设备文件,此标志会被忽略。
O_APPEND 每次写文件都追加到文件的尾端。(不会覆盖原有的内容)
O_NONBLOCK 以非阻塞模式打开文件。
O_NDELAY 以非阻塞模式打开文件,跟 O_NONBLOCK 是一样的,指向同一个标志位,推荐使用 O_NONBLOCK 标志,因为 O_NDELAY  是系统早期版本引入的,在读操作时,如果读不到数据,O_NDELAY会使 I/O 函数马上返回 0,但这又衍生出一个问题,因为读取到文件末尾(EOF)时返回的也是 0,这样无法区分是哪种情况。因此,O_NONBLOCK 就产生出来,它在读取不到数据时会回传 -1,并且设置 errno 为 EAGAIN。
O_SYNC 以同步 I/O 方式打开文件,即每次 write 等待物理 I/O 操作完成,包括由该 write 操作引起的文件属性更新所需的 I/O 都操作完成。
O_LARGEFILE 支持大文件模式打开文件,在 32 位操作系统中使用此标志,允许打开那些用 31 位都不能表示其长度的大文件。
O_DIRECTORY 如果参数 pathname 不是目录,则打开失败,此时 errno 被设置为 ENOTDIR。
O_NOFOLLOW 如果参数 pathname 引用的是一个符号链接,则 open() 函数打开失败,此时 errno 被设置为 ELOOP。
O_CLOEXEC 将新打开的文件描述符设置 FD_CLOEXEC 标志,可以免去程序执行 fcntl() 函数时的 F_GETFD 和 F_SETFD 操作来设置 close-on-exec 标志的额外工作。

linux 内核中 头文件对 O_NDELAY 的定义如下所示:

#ifndef O_NDELAY
#define O_NDELAY	O_NONBLOCK
#endif

在 linux 内核中 头文件对参数 flags 所有有效取值如下所示:

/* list of all valid flags for the open/openat flags argument: */
#define VALID_OPEN_FLAGS \
	(O_RDONLY | O_WRONLY | O_RDWR | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | \
	 O_APPEND | O_NDELAY | O_NONBLOCK | O_NDELAY | __O_SYNC | O_DSYNC | \
	 FASYNC	| O_DIRECT | O_LARGEFILE | O_DIRECTORY | O_NOFOLLOW | \
	 O_NOATIME | O_CLOEXEC | O_PATH | __O_TMPFILE)

mode:位掩码,用于当调用 open() 函数创建新文件时,指定文件的访问权限。如果参数 flags 中没有指定 O_CREAT 标志,则可以省略 mode 参数。

mode 参数所有有效取值如下:

mode 说明
S_ISUID 执行时设置用户 ID
S_ISGID 执行时设置组 ID
S_ISVTX 粘着位,对目录使用
S_IRWXU 用户可读,可写,可执行
S_IRUSR 用户可读
S_IWUSR 用户可写
S_IXUSR 用户可执行
S_IRWXG 组可读,可写,可执行
S_IRGRP 组可读
S_IWGRP 组可写
S_IXGRP 组可执行
S_IRWXO 其他用户可读,可写,可执行
S_IROTH 其他用户可读
S_IWOTH 其他用户可写
S_IXOTH

其他用户可执行

S_IRWXUGO

用户、同组用户以及其他用户都可读、可写、可执行

S_IRUGO

用户、同组用户以及其他用户都可读

S_IWUGO

用户、同组用户以及其他用户都可写

S_IXUGO

用户、同组用户以及其他用户都可执行

S_IALLUGO

以上列举的所有权限都有

在 linux 内核中 头文件对 mode 参数的有效取值定义如下所示:

#define S_ISUID  0004000
#define S_ISGID  0002000
#define S_ISVTX  0001000

#define S_IRWXU 00700
#define S_IRUSR 00400
#define S_IWUSR 00200
#define S_IXUSR 00100

#define S_IRWXG 00070
#define S_IRGRP 00040
#define S_IWGRP 00020
#define S_IXGRP 00010

#define S_IRWXO 00007
#define S_IROTH 00004
#define S_IWOTH 00002
#define S_IXOTH 00001

#define S_IRWXUGO	(S_IRWXU|S_IRWXG|S_IRWXO)
#define S_IALLUGO	(S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO)
#define S_IRUGO		(S_IRUSR|S_IRGRP|S_IROTH)
#define S_IWUGO		(S_IWUSR|S_IWGRP|S_IWOTH)
#define S_IXUGO		(S_IXUSR|S_IXGRP|S_IXOTH)

例子

以下程序功能:打开 "./log.txt" 文件,并往该文件内容的末尾写一行 "hello world\n"

#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main(int argc, char *argv[])
{
    int flags = O_WRONLY | O_CREAT | O_APPEND; /* 只写,没有该文件则创建,写时从文件内容的末尾附加新内容 */
    mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; /* rw-rw-rw- */
    int fd = open("./log.txt", flags, mode); 
    if (fd < 0) {
        perror("open error");
        exit(EXIT_FAILURE);
    }
    
    char buf[] = "hello world\n";
    ssize_t nwrite = write(fd, buf, strlen(buf));
    if (nwrite < 0) {
        perror("write error");
        exit(EXIT_FAILURE);
    }
    printf("write success\n");

    close(fd);

    return 0;
}

linux文件I/O之 open() 函数用法_第1张图片

参考:

《UNIX环境高级编程》(第3版)

《Linux-UNIX系统编程手册》

你可能感兴趣的:(linux环境编程学习笔记,c++,服务器,linux,c语言)