• 第三章文件I/O学习笔记


     

    1.文件描述符:是一个非负整数,用来描述打开的文件

    2.函数open和函数openat

     

    1 #include <fcntl.h>
    2 int open(const char * path, int oflag,...);
    3 int openat(int fd, const char * path, int oflag,...);

    打开或者创建一个文件描述符,失败的话返回-1

    path是要打开或创建的文件名

    oflag参数可用来说明此函数的多个选项

    fd参数指出了相对路径名在文件系统的开始地址

    这两个函数返回的都是未用的最小的文件描述符

     

    3.函数create

    1 #include <fcntl.h>
    2 int create(const char * path, mode_t mode);

    创建一个新的文件,返回文件描述符,错误的话返回-1

    等效于:

    1 open(path,O_WRONLY|O_CREAT|O_TRUNC, mode);

    4.函数close

    1 #inlude <unistd.h>
    2 int close (int fd);

    成功的话返回0,失败的话返回-1

    关闭一个打开的文件,还会释放该进程加在该文件上的所有记录锁

    大多数时候进程终止时,内核会自动管理她所有的打开文件

     

    5.函数lseek

     

    1 #include <unsitd.h>
    2 off_t lseek(int fd, off_t offset, int whence);

    这个函数可以显式地为一个打开文件设置偏移量

    成功的话返回新的文件偏移量,失败的话,返回-1

    whence是解释偏移量的

    SEEK_SET 设置为距离文件开始处offset个字节

    SEEK_CUR 设置为当前的的值加offset

    SEEK_END 设置为文件长度加offset

     

    6.函数read

    1 #include <unistd.h>
    2 ssize_t read(int fd, void * buf, size_t nbytes);

    从打开的文件中读数据

    成功返回读到的字节数,到达尾部的话,返回0,出错的话返回-1

     

    7.函数write

    1  #include <unistd.h>
    2 ssize_t write(int fd, const void *buf, size_t nbytes);

    向打开的文件写数据

    成功的话,返回已写的字节,失败的话,返回-1

     

    8.文件共享

     

    内核使用三种数据结构表示打开的文件

    1) 每个进程在进程表里面有一个记录项,包含一张打开文件描述符表,每个描述符占一项,包含两个部分,文件描述符标志,指向文件表项的指针

    2) 内核为所有的打开文件维持一张文件表,每个文件表包含三部分,文件状态标志,当前文件偏移量,指向该文件v节点表项的指针

    3) 每个打开的文件都有一个v-node结构,包含文件类型和对文件进行各种操作函数的指针

     

     

    9.原子操作

     

    1) 追加到一个文件

    在打开文件时设置O_APPEND标志,这样使内核在每次写操作之前,都将进程的当前偏移量设置到该文件的末尾处,于是每次写之前就不再需要调用lseek

    2) 函数preadpwrite

    1 #include <unistd.h>
    2 ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset);

    返回读到的字节数,到达文件尾部的话返回0,出错的话,返回-1.

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

    成功返回写的字节数,失败,返回-1.

    pread相当于调用lseek后调用read

    pwrite相当于调用lseek后调用write

    区别在于连贯的函数无法中断操作

     

    3) 创建一个文件

    atomic operation是指多步组成的一个操作,如果该操作原子地执行,要么执行完所有的步骤,要么一步也不执行,不可能执行一个子集。

     

    10.函数dupdup2

     

    1 #include <unistd.h>
    2 int dup(int fd);
    3 int dup2(int fd, int fd2);

    函数用来复制一个现有的文件描述符

    成功的话返回新的文件描述符,失败的话返回-1

    dup返回的文件描述符是当前可用的最小的

    dup2可以指定fd2为新的描述符,要是fd2已经打开,则先关闭,要是fd=fd2就直接返回,不关闭。

     

    11.函数sync,fsyncfdatasync

     

    当我们向文件写入数据时,内核通常先将数据复制到缓冲区,然后排入队列,晚些时候写入磁盘。当内核需要重用缓冲区存放其他磁盘块数据时,会把所有延迟写数据块写入磁盘。为保证磁盘上实际文件系统和缓冲区中的内容一致,使用下面的三个函数。

    1 #include <unistd.h>
    2 int fsync(int fd);
    3 int fdatasync(int fd);
    4 //成功返回0失败返回-1
    5 void sync(void);

    sync只是将所有修改过的块缓冲区排入写队列,然后返回,不等待实际写磁盘的操作结束。

    守护进程updata周期性调用sync函数,保证定期冲洗内核的块缓冲区。

    fsync针对指定的文件描述符,并且等待磁盘操作结束

    fdatasync可用于数据库这样的程序,确保修改过的块立即写到磁盘上。

    12.函数fcntl

    1 #include <fcntl.h>
    2 int fcntl(int fd, int cmd,...);

    改变已经打开的文件的属性

     

    13.函数ioctl

     

    1 #include <unistd.h>
    2 #include <sys/ioctl.h>
    3 int ioctl(int fd, int request,...);

    出错返回-1成功返回其他值

    不能用其他函数表示的I/O通常可以用这个函数实现。

    14./dev/fd

     

    打开文件/dev/fd/n等效于复制描述符n(假定描述符n是打开的)

    1 fd=open(“/dev/fd/0”,mode);
    2 fd=dup(0);//描述符0和fd共享同一文件表项
    3 fd=open(“/dev/fd/0”,O_RDWR);//要是0被打开为只读,即使这个调用成功,也不能对fd进行写操作。
  • 相关阅读:
    两个数组的交集
    左叶子之和
    下载安装python
    占位
    2020 软件工程实践 助教总结
    安装使用 QEMU-KVM 虚拟化环境(Arch Linux / Manjaro / CentOS / Ubuntu )
    #69. 新年的QAQ
    1097E. Egor and an RPG game(Dilworth定理)
    #553. 【UNR #4】己酸集合
    #2099. 「CQOI2015」标识设计(插头dp)
  • 原文地址:https://www.cnblogs.com/kongchung/p/4599208.html
Copyright © 2020-2023  润新知