Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c-F_GETFL和F_SETFL的用法_C_File Io_Fcntl - Fatal编程技术网

c-F_GETFL和F_SETFL的用法

c-F_GETFL和F_SETFL的用法,c,file-io,fcntl,C,File Io,Fcntl,在尝试将fcntl()与命令F_GETFL和F_SETFL一起使用时,我遇到了一些问题: 为什么fcntl(fd,F_GETFL)返回的标志只包含打开文件时设置的位的子集?它是否只显示可修改的内容 使用fcntl(fd,F_SETFL,flag)时,我应该如何传递flag参数,我是否需要先通过fcntl(fd,F_GETFL)读取flag,然后修改并传递它?或者在内部,它只是对新参数执行一点&操作 在哪里可以找到32位(或更少)打开文件标志的完整列表 代码-[dup\u fd\u share.c

在尝试将
fcntl()
与命令
F_GETFL
F_SETFL
一起使用时,我遇到了一些问题:

  • 为什么
    fcntl(fd,F_GETFL)
    返回的标志只包含打开文件时设置的位的子集?它是否只显示可修改的内容

  • 使用
    fcntl(fd,F_SETFL,flag)
    时,我应该如何传递flag参数,我是否需要先通过
    fcntl(fd,F_GETFL)
    读取flag,然后修改并传递它?或者在内部,它只是对新参数执行一点
    &
    操作

  • 在哪里可以找到32位(或更少)打开文件标志的完整列表

  • 代码-[dup\u fd\u share.c]:

    // prove duplicated fd shared file offset and open file status,
    // TLPI exercise 5.5
    
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <unistd.h>
    #include <fcntl.h>
    
    #define BUF_SIZE 100
    
    void fd_share() {
        char *fp = "/tmp/fd_share.txt";
        char *buf = "abc\n";
        int write_size = 4;
        int fd, fd2;
        off_t cur, cur2;
        int open_flag, open_flag2;
    
        // open
        int flag = O_RDWR | O_CREAT | O_TRUNC | O_APPEND;
        printf("file flag param: %x\n", flag);
        fd = open(fp, flag, 0644);
    
        // dup
        fd2 = dup(fd);
    
        // initial offset
        cur = lseek(fd, 0, SEEK_CUR);
        printf("fd[%d] offset: %ld\n", fd, cur);
        cur2= lseek(fd2, 0, SEEK_CUR);
        printf("fd[%d] offset: %ld\n", fd2, cur2);
    
        // write, offset change,
        write(fd, buf, 4);
        printf("write %d chars\n", write_size);
    
        // new offset
        cur = lseek(fd, 0, SEEK_CUR);
        printf("fd[%d] offset: %ld\n", fd, cur);
        cur2= lseek(fd2, 0, SEEK_CUR);
        printf("fd[%d] offset: %ld\n", fd2, cur2);
    
        // get original open file flag,
        open_flag = fcntl(fd, F_GETFL);
        printf("fd[%d] open flag: %x\n", fd, open_flag);
        open_flag2 = fcntl(fd2, F_GETFL);
        printf("fd[%d] open flag: %x\n", fd2, open_flag2);
    
        // change open file flag,
        open_flag &= ~O_APPEND;
        if(fcntl(fd, F_SETFL, open_flag) == -1) {
            printf("failed to set flag\n");
            return;
        }
        printf("change open file flag, remove %s\n", "O_APPEND");
    
        open_flag = fcntl(fd, F_GETFL);
        printf("fd[%d] open flag: %x\n", fd, open_flag);
        open_flag2 = fcntl(fd2, F_GETFL);
        printf("fd[%d] open flag: %x\n", fd2, open_flag2);
    
        close(fd);
    }
    
    int main(int argc, char *argv[]) {
        fd_share();
        return 0;
    }
    
    file flag param: 642
    
    fd[3] offset: 0
    fd[4] offset: 0
    write 4 chars
    fd[3] offset: 4
    fd[4] offset: 4
    
    fd[3] open flag: 402
    fd[4] open flag: 402
    change open file flag, remove O_APPEND
    fd[3] open flag: 2
    fd[4] open flag: 2
    
    1) fcnl返回的代码描述了函数是否成功以及如何:

    返回值

       For a successful call, the return value depends on the operation:
    
       F_DUPFD  The new descriptor.
    
       F_GETFD  Value of file descriptor flags.
    
       F_GETFL  Value of file status flags.
    
       F_GETLEASE
                Type of lease held on file descriptor.
    
       F_GETOWN Value of descriptor owner.
    
       F_GETSIG Value of signal sent when read or write becomes possible, or
                zero for traditional SIGIO behavior.
    
       F_GETPIPE_SZ, F_SETPIPE_SZ
                The pipe capacity.
    
       F_GET_SEALS
                A bit mask identifying the seals that have been set for the
                inode referred to by fd.
    
       All other commands
                Zero.
    
       On error, -1 is returned, and errno is set appropriately.
    
    错误

       EACCES or EAGAIN
              Operation is prohibited by locks held by other processes.
    
       EAGAIN The operation is prohibited because the file has been memory-
              mapped by another process.
    
       EBADF  fd is not an open file descriptor
    
       EBADF  cmd is F_SETLK or F_SETLKW and the file descriptor open mode
              doesn't match with the type of lock requested.
    
       EBUSY  cmd is F_SETPIPE_SZ and the new pipe capacity specified in arg
              is smaller than the amount of buffer space currently used to
              store data in the pipe.
    
       EBUSY  cmd is F_ADD_SEALS, arg includes F_SEAL_WRITE, and there
              exists a writable, shared mapping on the file referred to by
              fd.
    
       EDEADLK
              It was detected that the specified F_SETLKW command would
              cause a deadlock.
    
       EFAULT lock is outside your accessible address space.
    
       EINTR  cmd is F_SETLKW or F_OFD_SETLKW and the operation was
              interrupted by a signal; see signal(7).
    
       EINTR  cmd is F_GETLK, F_SETLK, F_OFD_GETLK, or F_OFD_SETLK, and the
              operation was interrupted by a signal before the lock was
              checked or acquired.  Most likely when locking a remote file
              (e.g., locking over NFS), but can sometimes happen locally.
    
       EINVAL The value specified in cmd is not recognized by this kernel.
    
       EINVAL cmd is F_ADD_SEALS and arg includes an unrecognized sealing
              bit.
    
       EINVAL cmd is F_ADD_SEALS or F_GET_SEALS and the filesystem
              containing the inode referred to by fd does not support
              sealing.
    
       EINVAL cmd is F_DUPFD and arg is negative or is greater than the
              maximum allowable value (see the discussion of RLIMIT_NOFILE
              in getrlimit(2)).
    
       EINVAL cmd is F_SETSIG and arg is not an allowable signal number.
    
       EINVAL cmd is F_OFD_SETLK, F_OFD_SETLKW, or F_OFD_GETLK, and l_pid
              was not specified as zero.
    
       EMFILE cmd is F_DUPFD and the process already has the maximum number
              of file descriptors open.
    
       ENOLCK Too many segment locks open, lock table is full, or a remote
              locking protocol failed (e.g., locking over NFS).
    
       ENOTDIR
              F_NOTIFY was specified in cmd, but fd does not refer to a
              directory.
    
       EPERM  Attempted to clear the O_APPEND flag on a file that has the
              append-only attribute set.
    
       EPERM  cmd was F_ADD_SEALS, but fd was not open for writing or the
              current set of seals on the file already includes F_SEAL_SEAL.
    
    2) 要设置的标志由您选择::

    F_SETFL(int)

    3) 你有一个完整的描述。

    你问:

    为什么fcntl(fd,F_GETFL)返回的标志只包含我在打开文件时设置的位的子集?它是否只显示可修改的内容

    没有;它仅显示系统“记住”的内容,例如
    O_RDWR
    。这些真的可以称为“旗帜”。在
    oflag
    参数中存储的其他一些位更像是
    打开的系统调用的“命令指令”:例如,
    O_create
    表示“如果不存在请创建此文件”,而
    O_TRUNC
    表示“请截断它”,两者都不是“标志”。创建时被截断的文件与创建时未被截断的文件无法区分:它们都只是“文件”。因此,在
    open
    创建或截断文件后,它就不必“记住”该历史。它只“记住”重要的事情,比如文件是否打开以供读取或写入

    编辑添加:这些不同种类的旗帜有半官方名称
    O_RDWR
    是“访问模式”(记住,不可修改)
    O_APPEND
    是一种“操作模式”(记住,通常可修改)
    O_TRUNC
    是一个“打开时间标志”(属于
    open
    操作本身,不属于文件描述符;因此不被记住)。请注意,“访问模式”不可修改-不能使用
    fcntl
    将只读fd转换为只读fd

    使用
    fcntl(fd,F_SETFL,flag)
    时,我应该如何传递flag参数,我是否需要先通过
    fcntl(fd,F_GETFL)
    读取flag,然后修改并传递它?或者在内部,它只是对新参数执行一点
    &
    操作

    F_SETFL
    用您传入的内容覆盖标志(尽管它会忽略您设置非真正标志位的微小尝试,例如
    O_TRUNC
    )。如果要设置一个特定的标志并保持其他标志不变,则必须
    F_GETFL
    旧标志,
    新标志,然后
    F_SETFL
    结果。这必须作为两个独立的系统调用来完成;据我所知,没有原子或线程安全的方法来实现它

    在哪里可以找到32位(或更少)打开文件标志的完整列表

    fcntl.h
    或其文档中(
    manfcntl
    )。例如,在我的MacBook上,手册页显示:

    The flags for the F_GETFL and F_SETFL commands are as follows:
    
          O_NONBLOCK   Non-blocking I/O; if no data is available to a read call, or if a write operation would block, the read or write
                       call returns -1 with the error EAGAIN.
    
          O_APPEND     Force each write to append at the end of file; corresponds to the O_APPEND flag of open(2).
    
          O_ASYNC      Enable the SIGIO signal to be sent to the process group when I/O is possible, e.g., upon availability of data to be
                       read.
    
    换句话说,在OS X上可以设置(或取消设置)的位正好有三位。而在Linux上,手册页上说:

    顺便说一句,一些Linux文件系统在文件系统级别具有“仅附加文件”的概念;如果打开其中一个文件,然后尝试清除结果描述符的
    O_APPEND
    标志,则会出现
    EPERM
    错误。可以使用该实用程序在文件系统级别控制文件的“仅附加”属性


    这是您的测试程序的一个更系统的版本。你可能对它不感兴趣,但我通过写作学到了一些东西,所以我把它留在这里。:)


    O_create
    O_TRUNC
    是控制
    open
    调用本身行为的修饰符;它们不是应用于打开文件的模式。
    The flags for the F_GETFL and F_SETFL commands are as follows:
    
          O_NONBLOCK   Non-blocking I/O; if no data is available to a read call, or if a write operation would block, the read or write
                       call returns -1 with the error EAGAIN.
    
          O_APPEND     Force each write to append at the end of file; corresponds to the O_APPEND flag of open(2).
    
          O_ASYNC      Enable the SIGIO signal to be sent to the process group when I/O is possible, e.g., upon availability of data to be
                       read.
    
    On Linux this command can change only the O_APPEND, O_ASYNC,
    O_DIRECT, O_NOATIME, and O_NONBLOCK flags.
    
    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    
    int main() {
        int fd = open("/tmp/fd_share.txt", O_RDWR | O_CREAT | O_TRUNC | O_APPEND, 0644);
    
        // append to empty file
        write(fd, "aaaaaaaaaa", 10);
    
        off_t cur = lseek(fd, 1, SEEK_SET);
        printf("offset after being set to 1: %ld\n", (long)cur);
    
        // append
        write(fd, "bbbbbbbb", 8);
    
        cur = lseek(fd, 0, SEEK_CUR);
        printf("offset after appending bbbbbbbb: %ld\n", (long)cur);
    
        cur = lseek(fd, 2, SEEK_SET);
        printf("offset after being set to 2: %ld\n", (long)cur);
    
        // now toggle "append mode" to FALSE
        int open_flag = fcntl(fd, F_GETFL);
        if (fcntl(fd, F_SETFL, open_flag & ~O_APPEND) == -1) {
            printf("failed to set flag\n");
            return 0;
        }
    
        cur = lseek(fd, 0, SEEK_CUR);
        printf("offset after unsetting O_APPEND: %ld\n", (long)cur);
    
        cur = lseek(fd, 3, SEEK_SET);
        printf("offset after being set to 3: %ld\n", (long)cur);
    
        // write without appending
        write(fd, "cccc", 4);
    
        cur = lseek(fd, 0, SEEK_CUR);
        printf("offset after writing cccc: %ld\n", (long)cur);
    
        // now toggle "append mode" to TRUE
        open_flag = fcntl(fd, F_GETFL);
        if (fcntl(fd, F_SETFL, open_flag | O_APPEND) == -1) {
            printf("failed to set flag\n");
            return 0;
        }
    
        cur = lseek(fd, 0, SEEK_CUR);
        printf("offset after unsetting O_APPEND: %ld\n", (long)cur);
    
        // append
        write(fd, "dd", 2);
    
        cur = lseek(fd, 0, SEEK_CUR);
        printf("offset after appending dd: %ld\n", (long)cur);
    
        close(fd);
    }
    
    offset after being set to 1: 1
    offset after appending bbbbbbbb: 18
    offset after being set to 2: 2
    offset after unsetting O_APPEND: 2
    offset after being set to 3: 3
    offset after writing cccc: 7
    offset after unsetting O_APPEND: 7
    offset after appending dd: 20