美文网首页
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