• APUE(3)---文件I/O (3)


    十二、函数sync、fsync和fdatasync

      延迟写:传统的Unix系统在内核中设有缓冲区或页高速缓冲,大多数磁盘I/O都通过缓冲区进行,当我们向文件写入数据时,内核通常先将数据复制到缓冲区,然后排入队列,晚些时候再写入磁盘。Unix系统提供了sync、fsync和fdatasync三个函数。

    #include <unistd.h>
    int fsync(inf fd);
    int fdatasync(int fd);
    //若成功,返回0;若出错,返回-1
    void sync(void);

      sync只是将所有修改过的块缓冲区排入写队列,然后就返回,它并不等待实际磁盘操作结束。通常称为update的喜欢守护进程周期性地调用sync函数,这就保证了定期冲洗(flush)内核的块缓冲区。

      fsync函数只对内核文件描述符fd指定的一个文件起作用,并且等待写磁盘操作结束后才返回,其主要应用场景是数据库内应用。

      fdatasync函数类似fsync,但他至响应文件的数据部分。而除数据外,fsync还会更新文件的属性。

    十三、函数fcntl

    #include <fcntl.h>
    int fcntl(int fd, int cmd, .../*int arg*/);
    //若成功,则依赖于cmd;若出错,则返回-1

       fcntl函数可以改变已经打开文件的属性,有以下5个功能:

    1.复制一个已有的描述符(cmd = F_DUPFD 或 F_DUPED_CLOEXEC)

    2.获取、设置文件描述符标志(cmd = F_GETFD 或 F_SETFD)

    3.获取、设置文件状态标志(cmd = F_GETFL 或 F_SETFL)

    4.获取、设置异步I/O所有权(cmd = F_GETOWN 或 F_SETOWN)

    5.获取、设置记录锁(cmd = F_GETLK、F_SETLK 或 F_SETLKM)

    F_DUPFD        : 复制文件描述符fd,新文件描述符作为函数返回值,它是尚未打开的各描述符中大于或等于第三个参数值返回。新描述符和fd共享一张文件表项,但是新文件描述符由他自己的一套文件文件描述符标志。其FD_CLOEXEC文件描述符标志被清除。

    F_DUPED_CLOEXEC: 复制文件描述符,设置与新描述符关联的FD_CLOEXEC文件描述符标志的值。

    F_GETFD       : 对应于fd的文件描述符标志作为函数值作为返回。当前只定义了一个文件描述符标志FD_CLOEXEC

    F_SETFD       : 对于fd设置文件描述符标志。新标志值按第三个参数设置。

    F_GETFL        : 对应fd的文件状态标志作为函数值返回,其返回值和open的标志位一致。

    F_SETFL                 : 将文件状态标志设置为第三个参数的值:可以更改的几个标志是:O_APPEND、O_NONBLOCK、O_SYNC、O_DSYNC、O_RSYNC、O_FSYNC和O_ASYNC

    F_FETOWN          : 获取当前接受SIGIO和SIGURG信号的进程或进程组ID

    F_SETOWN             :设置SIGIO和SIGURG信号的进程ID或进程组ID。正的arg指定一个进程ID,负的arg指定一个进程组ID。

    #include "apue.h"
    #include <fcntl.h>
    
    int main(int argc, char *argv[])
    {
        int val;
        if(argc != 2)
        {
            err_quit("usage : a.out <descripor#>");
        }
        
        if((val = fcntl(atoi(argv[1]), F_GETFL, 0)) < 0)
        {
            err_sys("fcntl error for fd %d
    ", atoi(argv[1]));
        }
        
        switch(val & O_ACCMODE)
        {
        case O_RDONLY:
        printf("read only");
        break;
        case O_WRONLY:
        printf("write only");
        break;
        case O_RDWR:
        printf("read write");
        break;
        default:
        err_dump("unknow access mode");     
        }
        
        if(val & O_APPEND)
        {
            printf(", append");
        }
        
        if(val & O_NONBLOCK)
        {
            printf(", nonblocking");
        }
        
        if(val & O_SYNC)
        {
            printf(", synchronous writes");
        }
        
    // #if !defined_ ( _POSIX_C_SOURCE) && defined_(O_FSYNC) && (O_FSYNC != O_SYNC)
        if(val & O_FSYNC)
        {
            printf(", synchronous writes");
        }
    // #endif
    
        putchar('
    ');
        exit(0);
    }

    3-5:对于指定的描述符打印文件标志

      在修改文件描述符标志或文件状态标志时必须谨慎,先要获得现在的标志值,然后按期望值修改他,然后设置新标志值。不能只是执行F_SETFD或F_SETFL命令,这样会关闭以前设置的标志位:

    void set_fl(int fd, int flags)
    {
        int val;
        if((val = fcntl(fd, F_GETFL, 0)) < 0)
        {
            err_sys("fcntl F_GETFL error");
        }
        
        val |= flags;
        
        if(fcntl(fd, F_SETFL, val) < 0)
        {
            err_sys("fcntl F_SETFL error");
        }
    }

    3-6:对一个文件描述符开启一个或多个文件状态标志

      在Unix系统中,通常write只是将数据排入队列,而实际的写磁盘操作则可能在以后的某个时刻进行。而数据库系统则需要使用O_SYNC,这样一来,他从write返回时就知道数据已确实写到了磁盘上,以免在系统异常时产生数据丢失。数据的安全性得到了保证,其代价是设置O_SYNC会显著增加系统时间和时钟时间。

    十四、函数ioctl和/def/fd

      iotl函数一直是I/O操作的杂物箱。不能用本章其他函数表示的I/O操作通常都能用ioctl标识。终端I/O是使用ioctl最多的地方。

      较新的系统都提供名为/dev/fd的目录,其目录项是名为0、1、2等的文件。打开文件/dev/fd/n等效于复制描述符n。

     

  • 相关阅读:
    组件ListWidget 继承StatefulWidget后动态传入List数据,组件并不会重新渲染。
    Spring Security 采用httpBasic模式认证
    基于Vue2.0实现OpenLayers MarkerCluster海量聚合点标记
    Spring Security 采用formLogin模式认证
    配置页面兼容360浏览器
    如何进行企业工作流选型
    IT项目管理的六种错误思维
    时间管理10项技巧
    一个项目涉及到的50个Sql语句(下)
    SQL Server2000存储过程调试
  • 原文地址:https://www.cnblogs.com/cauchy007/p/5558496.html
Copyright © 2020-2023  润新知