美文网首页
File I/O open()函数

File I/O open()函数

作者: 无无吴 | 来源:发表于2019-08-01 08:33 被阅读0次

Opening Files

The Open() System Call

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open (const char *name, int flags);
int open (const char *name, int flags, mode_t mode);

Flags for open()

  • O_RDONLY
  • O_WRONLY
  • O_RDWR
  • O_APPEND
  • O_ASYNC(当指定的文件变为可读或可写时,将生成信号(默认情况下为SIGIO)。此标志仅适用于FIFO、管道、套接字和终端,而不适用于常规文件。)
  • O_CLOEXEC(在打开的文件上设置关闭的EXEC标志。执行新进程后,文件将自动关闭。这样就无需调用fcntl()来设置fand,从而消除了争用条件。此标志仅在Linux内核2.6及更高版本中可用。)
  • O_CREAT(如果以名称表示的文件不存在,内核将创建它。如果文件已经存在,则除非给出O_EXCL,否则此标志无效。)
  • O_DIRECT(该文件将被打开用于Direct I/O)
  • O_DIRECTORY(如果name不是目录,则对open()的调用将失败。opendir()库调用在内部使用此标志。)
  • O_EXCL(当使用O_CREAT时,如果名称给定的文件已经存在,则此标志将导致对open()的调用失败。这用于防止在创建文件时出现争用条件。如果O_CREAT没有提供, 这这个标志位没有任何意义。)
  • O_LARGEFILE(给定的文件将使用64位偏移打开,允许对大于2G的文件进行操作。这是隐含在64位架构上的。)
  • O_NOATIME+ (文件不会因为读而更新access time,防止一些重要的写行为被读而覆盖)
  • O_NOCTTY(如果给定的名称引用终端设备(例如,/dev/TTY),它将不会成为进程的控制终端,即使该进程目前没有控制终端。这个标志位不常使用。)
  • O_NOFOLLOW(如果文件名字是一个symbolic link, 那么调用open()会失败。通常,链接被解析,目标文件被打开。如果给定路径中的其他组件是链接,则调用仍将成功。例如,如果名称为/etc/ship/plank.txt,如果plank.txt是一个symbolic link,则失败。然而,如果etc或ship是symbolic links,只要plank.txt不是,它就会成功。)
  • O_NONBLOCK(如果可能,文件将以非阻塞模式打开。OPEN()调用和任何其他操作都不会导致进程阻塞I/O上的(睡眠)。这种行为只能为FIFO定义。)
  • O_SYNC(该文件将为同步I/O打开,在数据被物理写入磁盘之前不会完成写入操作;正常的读取操作已经是同步的,因此标对对读没有影响。)
  • O_TRUNC(如果文件存在,它是一个常规文件,并且给定的标志允许写入,该文件将被截断为零长度。在FIFO或终端设备上使用O_TRUNC是被忽略的。用于其他文件类型是未定义的。使用O_RDONLY指定O_TRUNC也是未定义的,因为您需要对文件进行写访问才能截断它。)
int testO_TRUNC()
{
    int fd = open("../FileIO/testfile.txt", O_WRONLY);
    if(fd == -1){
        perror("open");
        return -1;
    }
    close(fd);
    return 0;
}
没有O_TRUNC
int testO_TRUNC()
{
    int fd = open("../FileIO/testfile.txt", O_WRONLY | O_TRUNC);
    if(fd == -1){
        perror("open");
        return -1;
    }
    close(fd);
    return 0;
}
有O_TRUNC

很明显,带有O_TRUNC写文件时的效果就是先把文件先清空,再写入
验证如下

int testO_TRUNC()
{
    int fd = open("../FileIO/testfile.txt", O_WRONLY | O_TRUNC);
    if(fd == -1){
        perror("open");
        return -1;
    }
    char buf[5] = "aaaa";
    write(fd, buf, 5);
    close(fd);
    return 0;
}
先写一个
int testO_TRUNC()
{
    int fd = open("../FileIO/testfile.txt", O_WRONLY | O_TRUNC);
    if(fd == -1){
        perror("open");
        return -1;
    }
    char buf[5] = "bbbb";
    write(fd, buf, 5);
    close(fd);
    return 0;
}
再写一个
通过如上的实验,结论得以验证

新文件的所有者

文件所有者的uid是创建文件的进程的uid
默认行为是将文件的gid设置为创建文件的进程的gid。

新文件的权限

之前给的两个关于open函数的调用形式都是有效的。参数mode可以被忽略除非文件是被创建的,也是就说要给出O_CREAT。当你使用O_CREAT时但忘记提供mode参数的时候,那么结果是不明确的,而且非常丑陋──所以不要忘记!

  • S_IRWXU 所有者具有读取、写入和执行权限。
  • S_IRUSR 所有这具有读取的权限
  • S_IWUSR 所有者具有写入的权限
  • S_IXUSR 所有者具有执行的权限
  • S_IRWXG 组具有读取、写入和执行权限
  • S_IRGRP 组具有读取的权限
  • S_IWGRP 组具有写入的权限
  • S_IXGRP 组具有执行的权限
  • S_IRWXO 每个人都可以写入、读取和执行
  • S_IROTH 每个人都可以读取
  • S_IWOTH 每个人都可以写入
  • S_IXOTH 每个人都可以执行
    例如,下面的代码打开文件提供的用于写入。如果文件不存在,使用权限0644创建该文件。如果确实存在,则将其截断为零长度:
int testMode()
{
    int fd = open("test1.txt", O_WRONLY | O_CREAT | O_TRUNC,
            S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP | S_IROTH);
//    int fd = open("test1.txt", O_CREAT | O_EXCL,
//                  S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP | S_IROTH);
    if(fd == -1){
        perror("testMode - open");
        return -1;
    }
    char buf[5] = "aaaa";
    write(fd, buf, 5);
    close(fd);
    return 0;
}

如果此时再用以下代码,则会发现报以下错误:

int testMode()
{
//    int fd = open("test1.txt", O_WRONLY | O_CREAT | O_TRUNC,
//            S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP | S_IROTH);
    int fd = open("test1.txt", O_CREAT | O_EXCL,
                  S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP | S_IROTH);
    if(fd == -1){
        perror("testMode - open");
        return -1;
    }
    char buf[5] = "aaaa";
    write(fd, buf, 5);
    close(fd);
    return 0;
}
创建文件但文件已存在

如果此时把文件删除,再次调用以上代码,则会发现:


试验1

也就是说明,在文件创建时没有提供写的权限,文件可以创建,但是不会被写入,并且可以看到权限的设置是按照预期的。
最后让我们先删除文件,再加入写的权限并创建文件看一下:

int testMode()
{
//    int fd = open("test1.txt", O_WRONLY | O_CREAT | O_TRUNC,
//            S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP | S_IROTH);
    int fd = open("test1.txt", O_CREAT | O_EXCL | O_WRONLY,
                  S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP | S_IROTH);
    if(fd == -1){
        perror("testMode - open");
        return -1;
    }
    char buf[5] = "aaaa";
    write(fd, buf, 5);
    close(fd);
    return 0;
}
试验2

我们发现文件按照预期权限创建,并且因为我们在创建文件时加入了写的权限,因此成功写入了想要的内容。

相关文章

网友评论

      本文标题:File I/O open()函数

      本文链接:https://www.haomeiwen.com/subject/oypfdctx.html