在linux下进行read和write时,发现当返回一个文件描述符,对它进行write操作,之后马上read,读出来的数据都是0,当时很奇怪,因为文件描述符只是一个int型的整数,不同于C下的fwrite,是直接返回一个文件指针,每次读写这个指针也会随之而变化,于是查找了关于文件描述符的资料。
文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。内核对所有打开的文件的文件维护有一个系统级的描述符表格(open file description table)。有时,也称之为打开文件表(openfile table),并将表格中各条目称为打开文件句柄(open file handle)。一个打开文件句柄存储了与一个打开文件相关的全部信息,如下所示:
1. 当前文件偏移量(调用read()和write()时更新,或使用lseek()直接修改)
2. 打开文件时所使用的状态标识(即,open()的flags参数)
3. 文件访问模式(如调用open()时所设置的只读模式、只写模式或读写模式)
4. 与信号驱动相关的设置
5. 对该文件i-node对象的引用
6. 文件类型(例如:常规文件、套接字或FIFO)和访问权限
7. 一个指针,指向该文件所持有的锁列表
8. 文件的各种属性,包括文件大小以及与不同类型操作相关的时间戳
可以看到虽然文件描述符是一个固定的int变量,但实际它还对应这一个表,里面记录着打开的文件的偏移量就当做文件指针吧、,当你write或read是,这个量会变化,write之后,文件描述符所对应的打开文件 偏移量会发生变化,所以在write之后用lseek函数将偏移量再往上指向文件开头 再read就可以了。
<span style="font-family:Microsoft YaHei;font-size:18px;">#include<stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include<unistd.h>
int main(){
int i;
int fd=open("./emp.dat",O_RDWR|O_CREAT|O_TRUNC);
if(fd==-1){
printf("打开文件失败");
return -1;
}
char buf[10]={0};
for(i=0;i<10;i++){
buf[i]=i;
}
int res=write(fd,buf,sizeof(buf));
if(res==-1){
printf("写入失败");
return -1;
}
else{
printf("写入的数据有%d个\n",res);
}
res=lseek(fd,-sizeof(buf),SEEK_CUR);
if(res==-1){
printf("转移失败");
return -1;
}
else{
printf("距离文件头偏移量为%d\n",res);
}
char buf2[10]={0};
res=read(fd,buf2,sizeof(buf2));
if(res==-1)
{
printf("读取失败");
return -1;
}
else{
printf("读取的数据有%d个\n",res);
}
for(i=0;i<10;i++){
printf("buf2[i]=%d\n",buf2[i]);
}
return 0;
}
</span>