虚拟地址空间
我们是从内存的角度看文件的输入输出;
输入:从文件中将内容输入到内存;
输出:从内存中写内容到文件中;
标准C库的IO和Linux 中IO差别:
1.标准C库跨平台(跨操作系统);QT也是跨平台;跨平台的实现:例如JAVA为每个操作系统开发一个虚拟机,跑的时候在虚拟机中跑,不同的平台虚拟机不同;标准C库为第三方库:在不同平台上调用不同的系统API;对不同平台使用不同API去实现;
2.linux 平台的IO和C库的IO是调用和被调用的关系;标准C库的IO函数效率更高;
3.使用Linux中使用场景例如网络通信;
4.Linux 中IO没有缓存区;
如果没有虚拟地址空间;那么,运行程序可能会碰到空间不够,以及有程序释放了空间但空闲空间不连续得情况;等等。为了解决--虚拟地址空间;
程序:磁盘中的代码;进程:运行中的程序;
一个应用程序运行起来就对应一个进程,这个进程就会有一块虚拟地址空间;空间大小由电脑得CPU决定得;32位得2^32---4G(0-3G用户区,3-4G内核区);64位 2^48;
虚拟地址空间会通过MMU(内存管理单元)映射到真实物理内存中;
MMU:真实地址和虚拟地址进行转换;
用户区:用户可以自己操作;例如堆空间(大),栈空间(小),受保护的地址(例如NULL nullptr),代码段,以初始化的全局变量,未初始化。。共享库,命令行参数,环境变量;等;
内核区:用户没有权限操作,通过系统调用,系统API某些函数才能操作;
文件描述符
程序:不占用内存的资源,只占用磁盘,当运行的时候就会为其生成一个进程;
进程占用内存资源,进程启动之后会占用一旦虚拟地址空间;虚拟地址空间通过MMU映射到物理内存中;
PCB里面有一个数组--文件描述符表(定位磁盘上的文件),每个文件描述符定位一个文件;一个进程可以同时打开多个文件;
文件描述符的大小默认1024;最大同时能打开的文件个数1024;前三个默认是被使用的(标准输入0,标准输出1,标准错误2);这三个文件描述符默认打开;对应得文件---标准终端(设备文件);
Linux:一切皆文件;
一个文件可以被同时打开多次(fopen),打开多次对应得文件描述符是不一样的;当关闭时释放文件描述符;
open函数
可以打开一个已经存在的文件;创建一个没有的文件;具体根据所选函数
标准C库得fopen函数底层会调用Linux的;
标准C库的函数说明书 在man 第二章 Linux的第三章:查看
open函数源代码:
三个头文件;
两个open
调用成功-返回一个新的文件描述符,调用失败返回-1;
标准C库终端的函数perror ----打印errno对应的错误描述;
输出错误描述:
open创建新文件:
umask有默认的值也可以修改;
flags 标记用按位或 | 的原因:
read,write函数:
read: 将文件中的数据读到内存中去;
write:将内存中的数据写到文件中;
就可以实现拷贝:读一个文件写到另一个文件中;
参数:
fd :文件描述符 ,open得到,通过这个文件描述符去操作某个文件;
buf:指针类型。需要读取数据存放的地方,数组的地址;(传出参数);
count:指定的数组大小;
将文件中的数据得到之后指定存放的数组地方以及存放的数组空间大小;如果读到的比指定的大,读满就行了;
返回值:
-成功 :
>0:返回实际读到的字符数
=0:文件已经读取完了;
-失败:
-1:并设置errno ,可以通过perror获取错误信息;
write:
lseek函数:
lseek对文件指针进行偏移
参数:
fd:文件描述符,通过open得到,可以通过fd操作某个文件;
offset:偏移量
whence:需要指定的标记
SEEK_SET设置文件指针的偏移量;偏移量为多少由offset决定;
SEEK_CUR:设置偏移量:当前位置+第二个参数offset的值;
SEEK_END:设置偏移量:文件大小+第二个参数offset的值;
返回文件指针的位置
作用:
1. 移动文件指针到头文件;
lseek(fd,0,SEEK_SET);
2.可以获取当前文件指针的位置
lseek(fd,0,SEEK_CUR);
3.可以获取文件的长度;
lseek(fd,0,SEEK_END);
4.扩展文件的长度;当前文件10b,110b,扩展100b;
lseek(fd,100,SEEK_END);
扩展文件长度后面写入一个空数据:(扩展文件需要写入一次数据)
1.没加入空数据,没有扩展
2.加入空数据,扩展100,大小为:加入1=10+1+100
如果下载的文件有5G,磁盘还有5G空间,下载过程中,如果使用了空间,那导致下载不成功,因为磁盘不够。所以我们先创建出一个那么5G的文件,后续可以通过lseek移动指针到起始位置开始下载写入。
stat,lstat函数:
作用:获取一个文件的信息,传入statbuff 将信息放到这个statbuf中
返回值:成功:0;失败:-1,设置errno;
lstat 和stat的区别:
当文件有软链接时-获取软连接文件信息:
lstat获取的是软链接指向的文件的信息;
stat获取的是软连接文件的信息
模拟实现 ls -l 命令
文件类型:七种;
获取文件所有者:
我们只能得到Uid (int)--要通过一个函数 getpwUid(返回一个结构体指针)
包含头文件pwd.h
获取文件所在组:prd.h
通过函数getgrgid
获取修改的时间:st_mtime :(long int) 类型 秒从1980.。。到时间的秒数;
用函数ctime 在time.h头文件中;
但是:time函数最后带一个回车;
修改 -将最后一个字符去掉;头文件tring.h
传入buf;
文件属性操作函数![](https://i-blog.csdnimg.cn/blog_migrate/670fca682b0fc5ae6ac608bf986f8c75.png)
查看用户Uid
查看组id
目录操作函数
注意:指定的权限是777,但是底层会和掩码umask进行与操作,所以得到的最终权限是775;
权限的抹除,为保证数据的安全;
文件夹要有可执行权限才能进入该文件夹;
rmdir :只能删除空目录
改了工作目录之后,当前的工作目录就变成了lesson13;所以创建的文件在13目录下
目录遍历函数
打开一个目录使用完后要关闭目录
读取到了末尾或者失败了返回null;
参数:可执行程序 文件路径
dup函数:
返回新的文件描述符,错误返回-1;
dup函数会返回一个新的最小的文件描述符;
fd关闭了,仍可以通过复制的 fd1修改文件;
open文件状态要可读写;