[APUE] 标准I/O(1)

#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>




using namespace std;

FILE *f = fopen("/home/ubuntu/3.txt","w+");         //open file , read and write, everytime truncate file
FILE *f1 = fopen("/home/ubuntu/3.txt","r");         //open file , read and write, everytime truncate file'

int fd = open("/home/ubuntu/3.txt",O_RDONLY);
int fd1 = open("/home/ubuntu/3.txt",O_RDONLY);

int i = setvbuf(f,NULL,_IONBF,0);                   //no buff write , make sure data will be synced into file in time
int main()
{
    char inbuf[100] = {0};
    char outbuf[100] = {0};
    char i = '0';
    long j = 0;

    if(fd == fd1){
        cout<< " same " << endl;
    }else{
        cout<< " not same " << endl;
    }

    while(i < '9'){

        memset(inbuf,0,sizeof(inbuf));
        memset(outbuf,0,sizeof(outbuf));

        inbuf[0] = i;

        fwrite(inbuf,1,1,f);
        cout<< " write : " << inbuf[0];

        int pos = ftell(f);
        cout << " curr : " << pos;
        //fseek(f,j,SEEK_SET);        //both fwrite and fread will change offset, so reseek before do fread
        fseek(f1,j,SEEK_SET);        //if 2nd time open , fseek(f,j,SEEK_SET) will not affect f1's offset , so fseek f1

        fread(outbuf,1,1,f1);
        cout<< " read : " << outbuf[0] << endl;

        i++;
        j++;

    }

    return 0;
}

每个进程都有一个叫做进程表项的数据结构,里面包含了当前进程打开的所有文件的文件描述符,每个文件描述符都关联一个叫做文件指针的指针成员,这个指针指向一个叫做文件表项的数据结构,这个数据结构里包含文件状态标志(读/写/追加/同步/非阻塞等等),当前文件偏移量,v节点指针。v节点指针指向文件系统的v节点表项,v节点表项是文件系统级别的数据结构,所有进程所有线程都共享,里面存储着文件内部的实际数据。

当两个进程都打开同一个文件时,会产生两个互不关联但可能值相等的 fd / FILE* :

  • 每个 fd / FILE* 记录不同的 close_on_exec 标志;
  • 每个 fd / FILE* 持有不同的文件偏移量信息;
  • 每个 fd / FILE* 拥有不同的文件状态标志;
  • 每个 fd / FILE* 指向相同的v节点表项。

当一个进程两次打开同一个文件时,会产生两个互斥且值不可能相等的 fd / FILE* :

  • 每个fd或FILE* 记录不同的 close_on_exec标志;
  • 每个 fd / FILE* 持有不同的文件偏移量信息;
  • 每个 fd / FILE* 拥有不同的文件状态标志;
  • 每个 fd / FILE* 指向相同的v节点表项。

dup && dup2

前面说到每个fd / FILE* 都会由各自的数据结构(除v节点表项),但是也有一个例外,就是用dup 和 dup2来复制文件描述符,dup和dup2会新建一个文件描述符,但是这个文件描述符和原文件描述符共享文件表,即共享 文件状态标志,当前文件偏移量 ,v节点指针。但是close_on_exec标志是新的,因为这个标志存在于文件描述符表中。

dup和dup2不可以跨进程进行文件描述符复制,因为每个进程的文件描述符表项是完全独立的。

边读边写:

边读边写时需要明确当前读写的 fd / FILE* 对应的当前文件偏移量是什么:

  1. 同一个进程场景下,读写作用于相同的 fd / FILE* ,那么读写的文件偏移量是共享的。
  2. 同一个进程场景下,读写作用于不同的 fd / FILE* (多次打开同一个文件获得不同的fd / FILE* ), 那么读写的文件偏移量是独立的,这个时候要自行处理,如果还是多线程的,那么还需要对存储偏移量的变量加锁。有个例外,指定 O_APPEND / "a+" 时,操作系统会保证每次读写都使用当前文件偏移量的尾部,但是需要注意的是这个标志存储在文件状态标志中,因此当dup/dup2的时候会出现不同 fd / FILE* 共享文件状态标志的情况。
  3. 同一个进程场景下,读写由 dup / dup2 创建的 fd / FILE* ,这个时候和1)一样是共享偏移量的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值