文件,基础IO

系统文件IO

open

pathname:要打开或创建的目标文件

flags:打开文件时,可以传入多个参数,进行或运算

参数:

  • O_RDONLY:只读打开
  • O_WRONLY:只写打开
  • O_RDWR:读写打开 ;这三个常量必须指定一个并且只能指定一个
  • O_CREAT:若文件不存在,就创建。需要使用mode选项,来指明文件的访问权限
  • O_APPEND:追加写

返回值:成功就返回新打开的文件描述符,失败返回-1

mode:创建文件时指定的权限

read

 返回值是实际读到的字节数,失败返回-1。buf是存储接受到数据的缓冲区

write

被进程在内存中打开的是内存文件,没有被打开的是磁盘文件

close

关闭指定的文件,头文件和write一样。关闭成功返回0,失败返回-1。如果程序终止时没有关闭打开的文件,内核对自动将打开的文件关闭。

文件描述符fd

0&1&2

Linux进程默认情况下有3个缺省打开的文件描述符,分别是标准输入0、标准输出1、标准错误2,对应外设键盘、显示器、显示器

 文件描述符从0开始的小整数。当我们打开文件时,操作系统在内存中要创建相应的数据结构开描述目标文件,于是就有了file结构体,表示一个已经打开的文件对象。而open指令,必须让进程和文件关联起来,每个进程都有一个指针指向一张表,该表最重要的部分就是包涵一个指针数组,么个元素都是一个指向被打开文件的指针。所以,fd 的本质就是数组下标。

文件描述符的分配规则

找到没有被占用的最小的文件描述符。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
    close(0);
    int fd = open("myfile", O_RDONLY);
    if(fd < 0){
        perror("open");
    return 1;
    }
    printf("fd: %d\n", fd);
    close(fd);
    return 0;
}

此时fd是0,如果关闭的是1,那么本该输出到显示器上的内容会输出到文件中,就做输出重定向。重定向的本质就是在OS内部,更改fd对应的内容的指向。

使用dup2系统调用

#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <sys/types.h>

int main(int argc,char* argv[])
{
    if(argc != 2)
        return 2;
    int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC);
    if(fd<0)
    {
        perror("open");
        return 1;
    }
    dup2(fd,1);// 输出重定向
    fprintf(stdout,"%s\n",argv[1]);

	close(fd);
    return 0;
}

缓冲区

写透模式:亲自去执行,成本高,效率低

写回模式:通过第三方,成本低,效率高

缓冲区刷新策略:立即刷新、行缓冲、全缓冲。

特殊情况:用户强制刷新(fflush),进程退出。缓冲区的刷新策略是一般+特殊

一般而言,显示器是行缓冲,磁盘文件是全缓冲。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
    close(1);
    int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);
    if(fd<0)
    {
        perror("open");
        return 1;
    }
    printf("hello world\n");
    fflush(stdout);
    close(fd);
    // 数据在缓冲区中,但是对应的fd关了,缓冲区无法刷新,就不能打印
    return 0;
}
#include <stdio.h>
#include <string.h>
int main()
{
    const char *msg0="hello printf\n";
    const char *msg1="hello fwrite\n";
    const char *msg2="hello write\n";
    printf("%s", msg0);
    fwrite(msg1, strlen(msg0), 1, stdout);
    write(1, msg2, strlen(msg2));
    fork();
    return 0;
}

运行结果:

 如果对运行结果进行重定向到文件中,

 发现库函数都输出了两遍,而系统调用只输出了一遍。

  1. 一般C写入文件时是全缓冲,而写入显示器是行缓冲
  2. 库函数自带缓冲区,当发生重定向到普通文件时,数据刷新方式就是全缓冲
  3. 在缓冲区的数据不会立即刷新,fork之后也不会
  4. 进程退出后,缓冲区会刷新
  5. fork的时候,发生了写时拷贝,所以有两份数据
  6. 系统调用没有缓冲区。这里的缓冲区都是指用户级缓冲区,该缓冲区是由C标准库维护的

文件系统

将数据存到磁盘就是将数据存到该数组,所以对磁盘的管理就变成了对数组的管理。

  •  super block:文件系统的属性信息
  • Data bloks:虽然磁盘的基本单位是扇区(512字节),但是操作系统和磁盘进程IO的基本单位是4kb,因为512字节太小,需要多次IO,效率低。而且如果操作系统使用和磁盘一样的大小,万一磁盘的大小变了,OS也需要改。Data blocks就是多个4kb的集合,保存的都是特定文件的内容,也可以存其他块的块号
  • inode table:inode是一个大小为128字节的空间,保存的是对应文件的属性。每一个inode块都有一个inode编号,还保存了和他同一个块组的块的编号
  • BlockBitmap:比特位和block是一一对应的,其中比特位为1,代表被占用,否则表示可用
  • inode Bitmap:和inode一一对应,比特位为1,代表占用,否则表示可用
  • GDT:块组描述符,表示块组的信息

创建一个新文件主要的操作:

  1. 存储属性:找到一个空的i节点,将文件信息存入其中
  2. 存储数据
  3. 记录分配情况
  4. 添加文件名到目录,文件名和inode之间的对应关系将文件名和文件的内容及属性连接起来

软硬链接

ln -s testlink1.txt soft.link // 建立软连接
ln testlink2.txt hard.link // 建立硬连接

软硬链接的本质区别就是有无独立的inode。软链接有,说明软链接是一个独立的文件,类似于快捷方式,内容指向文件对应的路径。硬链接就是在指定的目录下,建立了文件名和指定的inode的映射关系,就是取别名,不是真正的创建新文件。属性中有一个数叫做硬链接数,当我们删除一个文件的时候,并不是把inode删除,而是将这个引用计数递减,当它为0的时候,这个文件才被真正删除,就是没有文件名和这个文件关联。默认创建目录,引用计数是2。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java IO(Input/Output)是Java编程语言中用于处理输入和输出的基础库。它提供了一种方便的方式来读取和写入数据,从而与外部世界进行交互。 Java IO库包含多个类和接口,用于在不同的场景下处理输入和输出。这些类和接口可以分为字节流(Byte Stream)和字符流(Character Stream)两种类型。 字节流主要用于处理二进制数据,而字符流则用于处理文本数据。 常用的字节流类有: - InputStream和OutputStream:用于读取和写入字节数据。 - FileInputStream和FileOutputStream:用于读取和写入文件。 - BufferedInputStream和BufferedOutputStream:提供了缓冲功能,以提高读写的效率。 常用的字符流类有: - Reader和Writer:用于读取和写入字符数据。 - FileReader和FileWriter:用于读取和写入文本文件。 - BufferedReader和BufferedWriter:提供了缓冲功能,以提高读写的效率。 除了字节流和字符流之外,Java IO还提供了一些其他的类和接口,用于处理特定类型的输入和输出。例如: - DataInputStream和DataOutputStream:用于读写基本数据类型及字符串。 - ObjectInputStream和ObjectOutputStream:用于读写Java对象。 - PrintWriter:用于格式化输出。 在使用Java IO时,通常需要使用try-catch语句来捕获可能抛出的异常,例如IOException。 总结起来,Java IO是Java编程语言中用于处理输入和输出的基础库,提供了字节流和字符流两种类型的处理方式,并且还包含其他一些类和接口,用于处理特定类型的输入和输出。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值