Linux_基础IO

.回顾标准库的io接口:fopen fclose fseek fwrite fread

FILE* fopen(const char* path,const char* mode);
//path:文件路径
//mode:打开方式
//打开方式:r:只读方式打开文件	r+以读写方式打开文件,从文件开始位置进行覆盖式写入
//		  w:只写打开,文件不存在则创建、存在则清空原有内容
//		  w+:读写打开,不存在则创建、每次写入都从文件尾部开始
//		  a:写追加方式打开文件,文件不存在则创建,没写写数据都在文件尾部
//		  a+:可读,写追加方式打开,文件不存在则创建,读则从文件起始位开始读,写数据则在文件尾

size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
//ptr:一块内存,用来存储读取的数据
//size:读取元素的大小
//nmemb:读取元素的个数
//stream:文件流指针,即输入

size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream);
//ptr:一块内存,用来存储写入的数据
//size:写入元素的大小
//nmemb:写入元素的个数
//stream:文件流指针,即输出

int fclose(FILE* fp)
//fp:要关闭的文件流
//关闭成功则返回0,失败返回EOF

int fseek(FILE* stream, long offset, int whence);
//用于移动文件流的读写位置
//返回0正常,出现错误-1
//stream:文件流指针
//offset:偏移量,从起始位要移动的距离,可正可负
//whence:决定偏移量的起始位置
//			SEEK_SET 文件开始处
//			SEEK_CUT 文件当前位置
//			SEEK_ENO 文件末尾


fprintf sprintf snprintf printf 的区别?

printf我们很熟悉,
sprintf:用于将输出存到字符缓冲区中
snprinf:由于sprintf不能检查目标字符串的长度,可能造成安全问题,所以一般推荐使用snprintf

int fnprintf(char* dest_str, size_t size, const char* format,...);
//最多从原串中拷贝size-1个字符到目标字符串,然后在最后面加上一个‘\0'

fprintf:其功能与printf类似,只不过fprintf的读写对象不是终端,而是磁盘文件

系统调用接口:open close lseek write read

//头文件:fcntl.h
int open(const char* pathname,int flags, mode_t mode);
//打开文件
//返回值:文件描述符(正整数),出错返回-1
//pathname:文件路径名
//falg:O_RDONLY(只读),O_WRONLY(只写)、O_RDWR(读写) (这三种必选其一)
//		O_CREAT(文件不存在则创建),O_EXCL(与O_CREAT同用,文件存在则报错)
//		O_TRUNC(打开同时截断文件内容,长度为0),O_APPEND(写追加)
//		因为flag为int, 想使用多个时 用 | 连接,例如: O_WRONLY|O_CREAT
//mode:创建文件给定的文件(八进制) 实际权限 = mode & (~mask)

//头文件:unistd.h
ssize_t write(int fd, const void* buf, size_t count);
//写操作
//返回值:实际写入的字节数,出错返回-1
//fd:打开文件所返回的文件描述符
//buf:要向文件写入的数据,输入
//count:要写入的数据长度
ssize_t read(int fd, const void* buf, size_t count);
//读操作
//返回值:实际读取的字节数
//fd:文件描述符
//buf:读取的数据储存的位置
//count:要读取的数据长度
off_t lseek(int fd, off_t offset, int whence);
//移动文件的读写位置
//fd:文件描述符
//offset:偏移量
//whence:决定偏移量的起始位置
//			SEEK_SET 文件开始处
//			SEEK_CUT 文件当前位置
//			SEEK_ENO 文件末尾
int close(int fd);
//关闭文件
//fd:文件描述符

在系统io中会发现频繁出现的文件描述符这个东西,所以我们来解释一下
文件描述符:
文件描述符简单来说就是一个正整数,这个正整数实际代表的是一个数组的下标。
具体来讲,就要从进程对文件的管理开始,先描述在组织,每一个打开的文件都是由一个结构体来描述的:struct_file
进程pcb中有一个struct_file结构体对文件进行描述,而这个结构体中有一个数组file[],当进程打开一个文件的时候,会使用struct_file结构体来描述文件,并且将描述信息添加到file[]数组中,并将返回其下标给用户,而这个下标就是文件描述符。在底层实际上就是通过文件描述符找到文件描述信息,进而操控文件
在这里插入图片描述
文件描述符分配规则:最小末的分配规则
由上图所示,给个进程创建后都会默认生成三个默认文件,标准输入,标准输出,标准错误,而这三个文件分别占据了数组下标的0,1,2,所以当我们新打开一个文件时,返回的文件描述符为3。但是当我们手动将标准输入关闭之后,返回的文件描述符为0,所以这就是最小末分配规则,找到数组中下标最小的空位置,作为新打开文件的文件描述符

重定向:

int dup2(int oldfd, int newfd)//功能:改变文件描述符所对应的描述信息
//参数很好理解,就是表面意思

举个例子:

printf是C库当中的IO函数,一般往stdout(标准输出)中输出,但是stdout底层访问文件的时候,找的但是fd:1.但此时fd下标所表示的内容,已经变成myfile的地址i,所以输出的任何信息都会往文件中写入而不是在显示器在显示,进而完成完成输出重定向。常见的重定向由> >> <

FILE:

因为IO相关函数与系统调用接口对应,并且库函数封装了系统调用,所以本质上,访问文件都是通过fd访问的,所以C库当中的FILE结构体内部一定是封装了fd的

文件系统:

首先我们先用ls -l 查看文件信息

它们分别是,权限信息、硬链接数,文件拥有者、组、大小、最后修改时间、文件名

想要了解文件系统,首先得理解一下inode节点
在这里插入图片描述
超级块:存放文件系统本身的结构信息
inode bitmap:存放文件属性
data bitmap:存放文件数据
创建一个新文件:
1.内核先找的一个空闲的i节点,内核把文件信息记录其中
2.该文件存储在二个磁盘块,内核找到了二个空闲块,将内核缓冲区的数据复制到这俩块区域
3.文件内容按顺序存放,内核在inode节点指向的磁盘分区记录了上述块的列表
4.新的文件名为a,linux如何在当前的目录中记录这个文件呢,内核将入口(inode,a)添加到目录,文件名和inode之间的对应关系将文件名和文件的内容及属性连接起来节点

现在有一个问题,linux系统下一切皆文件,那么目录和文件的区别?
目录其实也是文件只不过存储的数据是目录下的文件名+inode ,所以每个目录都是4096个字节

命令cat file:通过文件名在目录项中获取文件inode节点-》通过inode节点找数据存储位置-》读取文件数据

硬链接与软链接:

硬链接文件具有相同的inode节点号,所有的硬链接文件通过inode操作数据(每 加一个硬链接,inode不变,链接数+1)

软连接文件和源文件不是同一个文件,拥有不同的inode结点号,访问软链接文件,就是通过软链接文件中保存的源文件路径来访问源文件

删除目录只是删除目录名,彻底删除必须是其链接数为0时才彻底删除

软链接与硬链接区别:
软链接存放原文件的位置(类似与快捷方式)/硬链接是一个文件的别名

删除源文件,软链接失效;但是硬链接不影响,只是链接数-1(当一个文件链接数 为0时才是真正删除一个文件,否则只是删除目录项)

软链接可以针对目录创建,但是硬链接不可以(root用户可以,所以只是系统的硬性要求,并不是逻辑技术上不可行,因为引入对目录的硬链接可能会在目录中引入循环,那么在循环遍历时系统就会形成无限循环)

软链接可以跨分区创建,硬链接不可以

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值