大佬教程收集整理的这篇文章主要介绍了Linux_系统文件IOopen、write、read、close、文件描述符(磁盘文件和内存文件)、files_struct结构体、文件描述符分配规则、重定向、FILE*与文件描述符的关系、缓冲区),大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
在C语言文件操作时调用fopen函数以写的方式打开文件,会自动在当前路径下创建文件
#include<stdio.h>
int main()
{
FILE*fp=fopen("Test","w");
fclose(fp);
return 0;
}
注意:当前路径并不是指可执行程序的位置,而是当前的工作目录 eg:
stdin:标准输入- - >键盘 stdout:标准输出- - >显示器 stderr:标准错误- - >显示器
每个进程在打开时都会默认打开这三个输入输出流
flags:打开文件选项
mode:打开文件默认权限 注意:这个权限收到系统umask值的影响,umask在Linux-文件权限中介绍不在赘述
返回值: 成功返回文件描述符(file descriptor),失败返回-1
一个整数有32位,每一个比特位代表一种标志,每一个标志通过 | 运算联系起来可以一起传入函数中
eg: #define X 0x1; 00000000…1 #define Y 0x2; 0000000…10 X|Y就把 0000000…11传入,相当于把X和Y的信息一起传入函数中 在函数内部判断某一个比特位是否为1就代表是否传入这个信息
eg:
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
int main()
{
umask(0);//将umask值设为0
int fd=open("Test.txt",O_WRONLY|O_CREAT,0666);
printf("%dn",fd);
close(fd);
return 0;
}
返回值:实际上写了几个字节。
eg:
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
int main()
{
umask(0);//将umask值设为0
int fd=open("Test.txt",O_RDWR|O_CREAT,0666);
if(fd<0)
{
return -1;
}
char ch=0;
while(1)
{
ssize_t size=read(fd,&ch,1);//每次读取一格字符
if(size<=0){
break;
}
write(1,&ch,1);//1文件描述符是标准输出(显示器)的文件描述符
}
close(fd);
return 0;
}
在Linux中系统,默认一个进程会打开3个文件描述符 0,1,2、分别代表标准输入,标准输出,标准错误,对应C语言的(stdin,stdout,stderr) 这个数字本质是一个数组下标
Linux系统为了管理保存进程打开的文件,用struct file来描述每一个打开的文件,多个文件之间选择双链表的形式组织起来。这张双链表保存在内存中。 这种文件称为内存文件
一个文件不仅仅由文件的内容,还包括修改时间,文件大小等信息。这些信息统称为文件属性
所以:文件=文件内容+文件属性
这个文件称为磁盘文件
文件被打开时有两份,一份是加载到内存的内存文件,一份是磁盘文件。 内存文件:将磁盘文件中的属性信息加载到内存中,形成struct file数据结构。延后式加载数据(当进行文件操作时才加载数据)。 每一个struct file结构体代表一个打开的文件。
每一个进程的task_struct这个结构体。 结构体中有结构struct file* fd_array[32]
数组每个元素都是一个指向内存文件的指针
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
int main()
{
umask(0);
int fd=open("a.txt",O_RDWR,0666);
printf("fd=%dn",fd);
close(fd);
close(0);//关闭标准输出
fd=open("a.txt",O_RDWR,0666);
printf("New fd=%dn",fd);
close(fd);
return 0;
}
在进行文件描述符分配时:从上到下扫描,最小的但是没有被使用的位置开始分配
将要输出到显示器上的信息重定向到文件中
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
int main()
{
umask(0);
close(1);//关闭标准输出,fd的值为1
int fd=open("a.txt",O_RDWR|O_CREAT,0666);
write(1,"1n",2);
write(1,"2n",2);
close(fd);
return 0;
}
只要是往显示器上打印的数据都会写到文件中
重定向的本质: 修改文件描述符fd下标对应的struct file*所指向的内容
C语言中FILE是个结构体,内部封装了文件描述符
C语言中的stdout: stdout在C语言中可以看作FILE*指针,指向的FILE结构体中的包含的文件描述符为1stdin与stderr也类似
所以:
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
int main()
{
umask(0);
close(1);//关闭标准输出,此时fd的值为1
int fd=open("a.txt",O_RDWR|O_CREAT,0666);
fprintf(stdout,"Hello Linuxn");//因为关闭了1号文件描述符,所以改向文件中写入
fflush(stdout);//刷新缓冲区
close(fd);
return 0;
}
此时stdout中fd=1指向的是新文件,达到了重定向
根据上述可知: 调用C语言的fopen函数时类似的输入重定向原理与输出重定向类似。
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
int main()
{
umask(0);
int fd=open("a.txt",O_RDWR|O_CREAT,0666);
if(fd<0){
return -1;
}
dup2(fd,1);
printf("Hello Linuxn");
fflush(stdout);
close(fd);
return 0;
}
缓冲的分类
无缓冲
行缓冲:常见对显示器进行刷新数据。如C语言中的printf函数中的n刷新
全缓冲:常见对文件读写时采用全缓冲。当把缓冲区内容写满才刷新缓冲区
eg:
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
int main()
{
//C语言
printf("Hello printfn");
fprintf(stdout,"Hello fprintfn");
//系统
const char* mes="Hello writen";
write(1,mes,strlen(mes));
fork();
return 0;
}
上述现象总结:
原因:
C库函数是对系统调用的封装。所以缓冲区是语言提供的。 这个缓冲区在内存中,C语言中FILE结构体中不仅有文件描述符,还包括缓冲区(用户缓冲区)
FILE中的缓冲区在用户区,刷新时先把用户区的缓冲区数据拷贝到内核缓冲区上,在刷新到显示器或磁盘上
再次来分析代码:
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
int main()
{
umask(0);
close(1);//关闭标准输出,此时fd的值为1
int fd=open("a.txt",O_RDWR|O_CREAT,0666);
fprintf(stdout,"Hello Linuxn");
fflush(stdout);//刷新缓冲区
close(fd);
return 0;
}
之所以要fflush(stdout)的原因: 重定向文件后,语言缓冲模式变为全缓冲。如果最后不强制刷新的话,close函数将文件关闭,程序结束后,缓冲区里面的数据将没有办法刷新到文件中了。所以一定要强制刷新缓冲区
但如果用C语言的接口fclose时会自动刷新缓冲区,就不需要手动强制刷新缓冲区
以上是大佬教程为你收集整理的Linux_系统文件IOopen、write、read、close、文件描述符(磁盘文件和内存文件)、files_struct结构体、文件描述符分配规则、重定向、FILE*与文件描述符的关系、缓冲区)全部内容,希望文章能够帮你解决Linux_系统文件IOopen、write、read、close、文件描述符(磁盘文件和内存文件)、files_struct结构体、文件描述符分配规则、重定向、FILE*与文件描述符的关系、缓冲区)所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。