欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

对文件I/O的一些探讨

程序员文章站 2022-05-24 20:15:10
...

参考书目:Unix/Linux 系统编程手册 chapter 5

一、原子操作以及竞争条件

原子操作(atomicity):将某一系统调用所要完成的各个动作作为不可中断的操作,一次性加以执行,内核使该系统调用不会为其他进程或线程中断。原子操作规避了竞争状态(race conditions)。操作共享资源的两个进程(或线程),其结果取决于一个无法预期的顺序。

以独占方式创建一个文件

由于需要先判断文件是否存在,再创建文件,所以可能会出现如图问题:
对文件I/O的一些探讨
结合O_CREAT和O_EXCL标志来一次性调用open()可以防止出现两个进程均声明自己是文件的创建者的情况。

向文件尾部追加数据

推荐使用O_APPEND标志来防止lseek()和write()时非原子操作可能造成的问题。

对于O_APPEND,练习题5.2

/*************************************************************************
    > File Name: test.c
    > Author: 0nism
    > Mail: aaa@qq.com 
    > Created Time: Thu 06 Sep 2018 07:24:50 PM CST
 ************************************************************************/

#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>


int main(int argc, char * argv[])
{
    int fd; 
    ssize_t numWrite;
    off_t offset;

    //      检测文件是否存在
    fd = open(argv[1], O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
    if (fd == -1 && errno == EEXIST)
    {   
        printf("File exist! OK.\n");
    }   
    else
    {   
        printf("File didn't exist.\n"); 
        exit(EXIT_FAILURE);
    }   

    fd = open(argv[1], O_WRONLY | O_APPEND);
    if (fd == -1) 
    {   
        perror("open"); 
        exit(EXIT_FAILURE);
    }   

    offset = lseek(fd, 0, SEEK_SET);
    if (offset == -1) 
    {   
        perror("lseek");    
        exit(EXIT_FAILURE);
       }

    numWrite = write(fd, "asd", 3);
    if (numWrite != 3)
    {
        perror("write");
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}

运行此程序发现设定的offset无效,write的数据仍然在末尾加上。原因是,此时文件偏移量的移动和数据写已经被纳入同一原子文件。

二、文件控制操作:fcntl()

   #include <unistd.h>
   #include <fcntl.h>

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

三、打开文件的标志状态

fcntl()的用途之一是针对一个打开的文件,获取或修改其访问模式以及状态标志。

获取标志F_GETFL。使用方法如下。

int flags, accessMode;
flags = fcntl(fd, F_GETFL);
if (flags == -1)
    errExit("fcntl");

改变标志F_SETFL。

四、文件描述符和打开文件之间的关系

对文件I/O的一些探讨

相关标签: Linux Apue io