zoukankan      html  css  js  c++  java
  • [UNIX]C语言中的文件操作函数

    文件描述符

    对于内核而言,所有打开的文件都是通过文件描述符引用.文件描述符通常是一个非负整数.

    按照惯例,UNIX系统shell把文件描述符0与进程的标准输入关联,文件描述符1与进程的标准输出关联,文件描述符2与标准错误关联.

    <unistd.h>中定义了符号常量STDIN_FIELNO,STDOUT_FILENO,STDERR_FILENO.

    文件描述符的范围是0~OPEN_MAX-1.

    文件的类型

    1. 普通文件
    2. 目录文件
    3. 块特殊文件
    4. 字节特殊文件
    5. 命名管道
    6. 套接字
    7. 符号链接

    open和openat

    
    int open(const char *path, int aflag, ...));
    
    int openat(int fd, const char *path, int aflag, ...);
    
    

    path是要打开或创建的文件的路径,aflag用来说明此函数的多个选项.

    openopenat函数返回的文件描述符是最小未用的描述符.

    creat

    
    int creat(const char *path, mode_t mode);
    
    
    

    在早期,open的第二个参数只能是0,1,2.无法打开一个不存在的文件,所以需要creat.

    他的打开方式只能是只写方式,需要打开,关闭,打开,才能.

    现在可以替换成

    
    open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); //只写
    
    open(path, O_RDWR | O_CREAT | O_TRUNC, mode); //读写
    
    

    close

    
    int close(int fd);
    
    

    fd是被操作文件的文件标识符.

    当一个进程中止,内核会关闭他的所有文件,所以有时不必显式调用close.

    lseek

    
    off_t lseek(int fd, off_t offset, int whence);
    
    

    常常有一个非负整数表示文件偏移量,代表文件和文件开头距离的字节数.

    除非使用O_APPEND参数,否则默认打开文件之后偏移量是0.

    可以用这个函数调整偏移量.

    如果调整成功,返回新的偏移值;否则返回-1,并且errno设置成ESPIPE.

    whence参数 作用
    SEEK_SET 把文件偏移量设置为距离文件开始offset个字节处
    SEEK_CUR 把文件偏移量设置为当前值加offset
    SEEK_END 把文件偏移量设置为文件长度加offset

    lseek仅仅将偏移量记录在内核中,不会引起IO操作,只是影响之后的IO操作.

    偏移量可以大于文件长度,写的时候文件会被加长.

    read

    
    ssize_t read(int fd, void *buf, size_t nbytes);
    
    

    成功返回读取到的文件数,如果已经到底尾端,返回0,出错返回-1.

    从当前的文件偏移量开始读,返回之前设置新的文件偏移量.

    ssize_t是带符号的size_t,为了返回-1.

    write

    
    ssize_t write(int fd, const void *buf, size_t nbytes);
    
    

    写入之后的偏移值为写入前的偏移值加写入量.

    打开文件的数据结构

    每个进程都在进程表中有一个记录,记录中包含一张打开文件描述符表,每个描述符占一项,每一项记录了文件描述符和指向文件表项的指针.

    内核维护一张文件表,每一项包含文件状态标识,文件偏移量,指向该文件v节点的指针.

    每个打开文件都有一个v节点结构.

    多个进程打开同一个文件时,他们各自有一个描述符表,描述符表指向各自的文件表项,但是文件表项的v节点指针指向同一个v节点.

    O_APPEND

    如果两个进程同时在一个文件的末尾添加内容,可能A进程定位到末尾之后被挂起,B进程开始写,之后A进程将B进程写的东西覆盖.

    如果打开时加上O_APPEND参数,每次写的时候都会把偏移量定位到最后面,不再需要一个lseek函数.

    pread/pwrite

    
    ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset);
    
    ssize_t pwrite(int fd, void *buf, size_t nbytes, off_t offset);
    
    

    相当于原子地移动偏移量并操作.操作之后不更新文件偏移量.

    dup/dup2

    
    int dup(int fd);
    
    int dup2(int fd, int fd2);
    
    

    返回一个新的文件描述符,指向fd所指向的文件文件表项(也就是和原本的fd偏移量也相同).

    前者返回的文件描述符一定是最小的可用的文件描述符.

    后者指定复制成fd2,如果fd2被占用则先关闭.如果fd==fd2,sma叶不干,返回fd2.

    不然返回-1.

    也可以fcntl(fd, F_DUPFD, fd2),新描述符必须大于等于fd2.

    sync,fsync和fdatasync

    
    void sync(void);
    
    int fsync(int fd);
    
    int fdatasync(int fd);
    
    

    sync是把所有修改过的块写入队列,然后就返回,不等待写入完成.

    fsync函数只对fd所指向的文件生效,并且等待写入完成.

    fdatasync只影响文件的数据部分(其他数据只在必要情况下更新).

    fcntl

    
    int fcntl(int fd, int cmd, ...);
    
    

    有以下功能

    1. 复制一个已有的描述符(F_DUPSF, F_DUPFD_CLOEXEC)
    2. 获取/设置文件描述符标志(F_GETFD, F_SETFD)
    3. 获取/设置文件状态标志(F_GETFL, F_SETFL)
    4. 获取/设置异步IO所有权(F_GETOWN, F_SETOWN)
    5. 获取/设置记录锁(F_GETLK, F_SETLK,F_SETLKW)

    stat

    
    int stat(const char *restrict pathname, struct stat *restrict buf);
    int fstat(int fd, struct stat *restrict buf);
    int lstat(const char *restrict pathname, struct stat *restrict buf);
    int fststat(int fd, const char *restrict pathname, struct stat *restrict buf, int flag);
    
    

    成功返回0,否则返回-1.

    stat是一个结构体,包含了文件的一些属性.

    文件访问权限

    st_mode值 含义
    S_IRUSR 用户读
    S_IWUSR 用户写
    S_IXUSR 用户执行
    S_IRGRP 组读
    S_IWGRP 组写
    S_IXGRP 组执行
    S_IROTH 其他读
    S_IWOTH 其他写
    S_IXOTH 其他执行

    所有者ID是文件的属性,有效者ID是进程的属性.

    进程能否操作文件需要对比这几个ID和所设置的权限.root用户除外.

    access, faccessat

    
    int access(const char *pathname, int mode);
    
    int faccessat(int fd, const char *pathname, int mode, int flag);
    
    

    测试文件权限.

    mode 说明
    F_OK 文件是否存在
    R_OK 文件读权限
    W_OK 文件写权限
    X_OK 文件运行权限
  • 相关阅读:
    shell与export命令
    mysql同步出现1062错误
    mysql命令行执行时不输出列名(字段名)
    python中中括号中的负数
    bash: ssh: command not found
    nagios的一些东西
    安装MySQLdb出现HAVE_WCSCOLL重定义问题的解决方法
    ImportError: No module named setuptools
    xp密钥
    破解MySQL和修改mysql的密码
  • 原文地址:https://www.cnblogs.com/zzidun-pavo/p/14335337.html
Copyright © 2011-2022 走看看