准备
博主:大大怪先森(记得关注,下次不要迷路哦)
编程环境:xshell(点击下载)
所示代码:码源
提示:写完文章后,目录可以自动生成
前言
提示:这里可以添加本文要记录的大概内容:
本文将讲解linux当中的基础I/O的问题!!!
提示:以下是本篇文章正文内容
一、c语言文件接口(回顾)
C语言写文件:
#include<stdio.h>
int main()
{
FILE* fp = fopen("./mytxt.txt","w");
if (fp == NULL)
{
perror("fail\n");
return -1;
}
char* buffer = "hello wzd\n";
fputs(buffer, fp);
fclose(fp);
fp = NULL;
return 0;
}
C语言读文件:
#include<stdio.h>
int main()
{
FILE* fp = fopen("./mytxt.txt", "r");
if(fp == NULL)
{
perror("fail\n");
return -1;
}
int cnt = 10;
char arr[128] = { 0 };
rewind(fp);
while (fgets(arr, sizeof(arr), fp))
{
printf("%s", arr);
}
fclose(fp);
fp = NULL;
return 0;
}
C语言的三种标准流:
stdin & stdout & stderr
stdin :标准输入流,键盘
stdout :标准输出流,显示屏
stderr:标准错误流,显示屏
这三个流的类型都是FILE*, fopen返回值类型,文件指针
二、系统文件I/0
1.接口介绍
open(打开函数):
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
pathname: 要打开或创建的目标文件
flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。
参数:
O_RDONLY: 只读打开
O_WRONLY: 只写打开
O_RDWR : 读,写打开
这三个常量,必须指定一个且只能指定一个
O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
O_APPEND: 追加写
返回值:
成功:新打开的文件描述符
失败:-1
其他接口
write read close lseek ,类比C文件相关接口
2.代码案例
代码如下(示例):
#include<stdio.h>
2 #include<unistd.h>
3 #include<sys/types.h>
4 #include<sys/stat.h>
5 #include<string.h>
6 #include<fcntl.h>
7 int main()
8 {
9 //FILE* fp = fopen("./log.txt","w");
10 //close(1);
11 //int fd = open("./log.txt",O_RDONLY | O_CREAT);
12 // int fd = open("./log.txt",O_RDWR);
13 // if(fd < 0)
14 // {
15 // perror("open");
16 // return 1;
17 // }
18 // dup2(fd,0);
19 // char line[128] = {0};
20 // fgets(line,sizeof(line) - 1,stdin);
21 // //while(fgets(line,sizeof(line) - 1,stdin))
22 // ///{
23 // // printf("%s",line);
24 // //}
25 // //fllush();
26 // fprintf(stdout,"hello wold\n");
27 // fputs("study well\n",stdout);
28 // write(1,line,strlen(line));
29 // //read(1,line,strlen(line));
30 // close(fd);
31 // close(1);
32 // int fp = open("log.txt",O_CREAT | O_WRONLY,0644);
33 //
34 // printf("%d\n",fp);
35 // fprintf(stdout,"hello wzd\n");
36 // fprintf(stdout,"study well\n");
37 // fprintf(stdout,"you will have mush money\n");
38 //char buff[64];
39 //ssize_t s = read(0, buff, sizeof(buff));
40 //buff[s-1] = 0;
41 const char* msg = "hello world\n";
42 // printf("echo# %s\n", buff);
43 write(2, msg, strlen(msg));
44 write(2, msg, strlen(msg));
45 return 0;
46 }
3.缓冲区
进程退出时,会将FILE内部的元素刷新到os缓冲区
用户刷新到os的刷新策略:
立刻刷新
行刷新(比如行缓冲):显示器刷新
缓冲满了才刷新(全刷新):比如:网磁盘文件写入;
1 #include<stdio.h>
2 #include<string.h>
3 #include<unistd.h>
4 #include<sys/types.h>
5 #include<sys/stat.h>
6 #include<fcntl.h>
7 int main()
8 {
9 // int fd = open("./log.txt",O_WRONLY | O_CREAT,0644);
10 // if(fd < 0)
11 // {
12 // perror("open");
13 // return -1;
14 // }
15
16 char* msg = "hello wzd\n";
17 write(1,msg,strlen(msg));
18 fprintf(stdout,"study well\n");
19 fprintf(stdout,"you will have mush money\n");
20 fork();
21 //printf("hello world");
22 return 0;
23 }
结果:
三、理解文件系统
磁盘使我们经常使用的一个外部设备;其中磁盘的写入区域:扇区
每一个磁盘当中的扇区我们可以理解成一种线性结构;
如下图:
文件 = 文件属性 + 文件内容
3.1inode
Linux ext2文件系统,上图为磁盘文件系统图(内核内存映像肯定有所不同),磁盘是典型的块设备,硬盘分区被划分为一个个的block。一个block的大小是由格式化的时候确定的,并且不可以更改。例如mke2fs的-b选项可以设定block大小为1024、2048或4096字节。而上图中启动块(Boot Block)的大小是确定的,
- Block Group:ext2文件系统会根据分区的大小划分为数个Block Group。而每个Block
Group都有着相同的结构组成。政府管理各区的例子- 超级块(Super Block):存放文件系统本身的结构信息。记录的信息主要有:bolck 和 inode的总量,未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个文件系统结构就被破坏了
- GDT,Group Descriptor Table:块组描述符,描述块组属性信息,有兴趣的同学可以在了解一下块位图(Block Bitmap):Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用
- inode位图(inode Bitmap):每个bit表示一个inode是否空闲可用。
i节点表:存放文件属性 如 文件大小,所有者,最近修改时间等- 数据区:存放文件内容
3.2软硬链接
硬链接:
我们看到,真正找到磁盘上文件的并不是文件名,而是inode。 其实在linux中可以让多个文件名对应于同一个inode。
软连接:
硬链接是通过inode引用另外一个文件,软链接是通过名字引用另外一个文件
为什么./可以可以找到当前路径下面?
我们发现当前目录下每一个隐藏的.代表当前路径,他们的inode是相同的。
结语
希望本篇文章能给各位带来帮助,如有不足还请指正!!!
码字不易,各位大大给个收藏点赞吧!!!
宝子们,点赞,支持。
三连走一波!!!