重复打开同一文件读取
- 一个进程中两次打开同一个文件读取,然后分别读取,观察结果。
- 猜测结果有两种情况:
- 经过实验验证,结果是分别读。说明:fd1和fd2所对应的文件指针式不同的2个独立的指针。文件指针是包含在动态文件的文件管理表中的,所以可以看出Linux系统的进程中不同fd对应的是不同的独立的文件管理表。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc,char *argv[])
{
int fd1 = -1,fd2 = -1;
char buf[100]={0};
char w_buf[20]="l love linux\n";
int ret = -1;
//第一步:打开文件
fd1 = open("a.txt",O_RDWR);
fd2 = open("a.txt",O_RDWR);
if ((-1 == fd1)||(-1 == fd2))//有时候也写成fd < 0
{
//printf("文件打开错误\n");
perror("open");
return -1;
}
else
{
printf("文件打开成功,fd1 = %d ,fd2 = %d \n",fd1,fd2);
}
#if 1
while(1)
{
//fd1读文件
memset(buf,0,sizeof(buf));
ret = read(fd1,buf,2);
if(-1 == ret)
{
printf("读取失败\n");
}
else
{
//printf("实际读取了%d字节\n",ret);
printf("fd1:[%s]\n",buf);
}
sleep(1);
//fd2读文件
memset(buf,0,sizeof(buf));
ret = read(fd2,buf,2);
if(-1 == ret)
{
printf("读取失败\n");
}
else
{
//printf("实际读取了%d字节\n",ret);
printf("fd2:[%s]\n",buf);
}
}
#endif
//第三步:关闭文件
close(fd1);
close(fd2);
return 0;
}
重复打开统一文件写入
- 一个进程中打开同一个文件,fd1、fd2都写入,观察结果。
- 我们有时候需要分别写入,优势需要接续写,所以两种没有好坏之分。
- 实验验证,结果为分别写入。即fd2会覆盖fd1写入的值。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc,char *argv[])
{
int fd1 = -1,fd2 = -1;
char buf[100]={0};
char w_buf[20]="l love linux\n";
int ret = -1;
//第一步:打开文件
fd1 = open("a.txt",O_RDWR | O_TRUNC | O_CREAT,0666);
fd2 = open("a.txt",O_RDWR | O_TRUNC | O_CREAT,0666);
if ((-1 == fd1)||(-1 == fd2))//有时候也写成fd < 0
{
//printf("文件打开错误\n");
perror("open");
return -1;
}
else
{
printf("文件打开成功,fd1 = %d ,fd2 = %d \n",fd1,fd2);
}
//第二步:读写文件
#if 1
while(1)
{
//fd1写文件
ret = write(fd1,"ab",2);
if(ret<0)
{
perror("fd1 write error\n");
_exit(-1);
}
else
{
printf("写成功,写入了%d个字符\n",ret);
}
sleep(1);
//fd2写文件
ret = write(fd2,"cd",2);
if(ret<0)
{
perror("fd2 write error\n");
_exit(-1);
}
else
{
printf("写成功,写入了%d个字符\n",ret);
}
}
#endif
//第三步:关闭文件
close(fd1);
close(fd2);
return 0;
}
加O_APPEND解决覆盖问题
- 有时候我们希望接续写而不是分别写,在open是加O_APPEND标志即可。
- 源码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc,char *argv[])
{
int fd1 = -1,fd2 = -1;
char buf[100]={0};
char w_buf[20]="l love linux\n";
int ret = -1;
//第一步:打开文件
fd1 = open("a.txt",O_RDWR | O_TRUNC | O_CREAT | O_APPEND,0666);
fd2 = open("a.txt",O_RDWR | O_TRUNC | O_CREAT | O_APPEND,0666);
if ((-1 == fd1)||(-1 == fd2))//有时候也写成fd < 0
{
//printf("文件打开错误\n");
perror("open");
return -1;
}
else
{
printf("文件打开成功,fd1 = %d ,fd2 = %d \n",fd1,fd2);
}
//第二步:读写文件
#if 1
while(1)
{
//fd1写文件
ret = write(fd1,"ab",2);
if(ret<0)
{
perror("fd1 write error\n");
_exit(-1);
}
else
{
printf("写成功,写入了%d个字符\n",ret);
}
sleep(1);
//fd2写文件
ret = write(fd2,"cd",2);
if(ret<0)
{
perror("fd2 write error\n");
_exit(-1);
}
else
{
printf("写成功,写入了%d个字符\n",ret);
}
}
#endif
//第三步:关闭文件
close(fd1);
close(fd2);
return 0;
}
O_APPEND的实现原理和其原子操作说明
- O_APPEND能够将分别写改为接续写的关键核心是文件指针。分别写的原理就是2个fd拥有不同的文件指针并且只 考虑自己的位移。但是O_APPEND标志可以让write和read函数内部移动自己文件的同时也去把别人的文件指针同时移动。fd1和fd2还是各自用于一个独立的文件指针,但是这两个文件指针关联起来了,一个动了另一个也会动。
- O_APPEND对文件指针的影响,对文件的读写时原子的。
- 原子操作的含义是:整个操作一旦开始是不会被打断的,必须直到操作结束其他代码才能得以调度运行,这就叫原子操作。每种操作系统中都有一些机制来实现原子操作,以保证那些需要原子操作的任务可以运行。