问题:同一个进程中,先后对同一个文件描述符进行写入 / 读取 操作,读写指针的位置导致读取内容失败

文件‘读写指针’ / lseek 系统调用
  1. 在进行文件操作(读 / 写)时,可以使用 lseek 系统调用来设置文件的下一个读写位置。
  2. 多进程 / 多线程 环境中,对同一资源进行读 / 写操作时,很可能会 因为 ‘读写指针’ 的变化导致各种隐蔽的问题,这一点必须要仔细。
  3. lseek 系统调用(对文件描述符的读写指针进行设置,即可以用它来 设置文件的下一个读写位置
  4. open 函数的 O_APPEND 选项,会影响文件的 ‘读写指针’ 是否会在多个进程间共享(是:导致写操作 追加到文件末尾,否:导致写操作 相互覆盖)(尝试解决一个问题的最好方式是:立刻开始动手操作)
#include 
#include 
off_t lseek(int fildes, off_t offset, int whence);

实验代码如下:

#include 
#include 
#include 
#include 
#include 
#include 

void main(){
	// 以读写方式打开文件,如果文件不存在则新建,新建文件时文件权限为 ‘rw-r--r--’
    int fd = open("1111111111111.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    if(fd < 0){
        printf("error: open failed.\n");
        exit(EXIT_FAILURE);
    }
    // 先执行写入操作
    int res = write(fd, "abc", 3);
    if(res != 3){
        printf("error: write failed.\n");
        exit(EXIT_FAILURE);
    }

    char buf[10];
    // 尝试读取之前写入的内容
    res = read(fd, buf, 3);
    if(res > 0){
        buf[res] = '\0';
        printf("readed:%s\n", buf);
    }else if(res == 0){
        printf("EOF\n");
    }else{
        printf("error: read failed.\n");
        exit(EXIT_FAILURE);
    }
}

运行结果为:

  • 程序创建新文件后,立即执行写入操作,随后从中读取之前写入的数据
  • 问题是: read 调用返回 0,表示已经到达文件末尾。但实际上文件中是有数据的
ubuntu@cuname:~/dev/beginning-linux-programming/test$ gcc -o test4 test4.c
ubuntu@cuname:~/dev/beginning-linux-programming/test$ ./test4
EOF 	// 读取失败(到达文件末尾)
ubuntu@cuname:~/dev/beginning-linux-programming/test$ ls -l | grep 1111
-rw-r--r-- 1 ubuntu ubuntu    3 Apr  8 17:23 1111111111111.txt
ubuntu@cuname:~/dev/beginning-linux-programming/test$ cat 1111111111111.txt
abc

!!!突然想到可能是 ‘读写指针’ 的问题!!!
(***因为执行写入操作后,‘读写指针’ 始终指向文件的末尾!***)
修改程序代码如下(在写入成功后,设置 ‘读写指针’ 的位置):

#include 
#include 
#include 
#include 
#include 
#include 

void main(){
    int fd = open("1111111111111.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    if(fd < 0){
        printf("error: open failed.\n");
        exit(EXIT_FAILURE);
    }
    int res = write(fd, "abc", 3);
    if(res != 3){
        printf("error: write failed.\n");
        exit(EXIT_FAILURE);
    }
	// 设置文件的 ‘读写指针’ 的位置,
	// 将 ‘读写指针’ 相对于当前位置(即:文件末尾)向左偏移 res 个字节(即:回到指执行写入操作时的位置)。
    off_t off = lseek(fd, 0 - res, SEEK_CUR);
    if(off == -1){
        printf("error: lseek failed.\n");
        exit(EXIT_FAILURE);
    }

    char buf[10];
    res = read(fd, buf, 3);
    if(res > 0){
        buf[res] = '\0';
        printf("readed:%s\n", buf);
    }else if(res == 0){
        printf("EOF\n");
    }else{
        printf("error: read failed.\n");
        exit(EXIT_FAILURE);
    }
}

运行程序,结果如下(确实是文件 ’读写指针‘ 的问题!):

ubuntu@cuname:~/dev/beginning-linux-programming/test$ gcc -o test4 test4.c
ubuntu@cuname:~/dev/beginning-linux-programming/test$ ./test4
readed:abc 	// 输出正确

你可能感兴趣的:(C,Linux,-,程序设计,Unix/Linux)