第九章学习笔记

第九章:I/O库函数

摘要:

本章讨论了库函数;解释了I/0库函数的作用及其相对于系统调用的优势;
使用

示例程序来说明0库函数和系统调用之间的关系,并解释了它们之间的相似性和基本区
别;

详细介绍了0库函数的算法,包括 i fread、 fwrite i和 I fclose的算法,重点介绍了它们与
rad、 write和 close系统调用的交互;

介绍了I/O库函数的不同模式,包括字符模式、行模式、结构化记录模式和格式化I/0操作;

阐述了文件流缓冲方案,并通过示例程序说明了不同缓冲方案的效果;

阐释了有不同参数的函数以及如何使用 I stdarg宏访问参数。

编程项目将本章的原理与编程技术相结合,以实现一个类 E printf函数,根据格式字符串格式化打印不同数基的字符、字符串和数字。

学到了什么?

  1. I/O库函数,系统调用是文件操作的基础,但它们只支持数据块的读/写。实际上,用户程序可能希望以最适合应用程序的逻辑单元读/写文件,如行、字符、结构化记录等,而系统调用不支持这些逻辑单元。I/O库函数是一系列文件操作函数,既方便用户使用,又提高了整体效率。

  2. I/O库函数与系统调用

    几乎每个支持C语言编程的操作系统都可提供文件I/O库函数。在Unixnux中,I/O库函数建立在系统调用的基础上。书上举的例子如下:

    系统调用函数: open、read、 write、 IseekO、 close();

    I/O库函数: fopen(、 fread、 fwrite)、 fseek(、 fclose。

  3. I/O库函数的算法:

  • fread算法

    fread算法如下:

    (1)在第一次调用 fread A;时,FILE结构体的缓冲区是空的fa使用保存的文件描述符fd发出一个

    n= read(fd, buffer, BLKSTZE);
    

    系统调用,用数据块填充内部的fbuf。然后,它会初始化fbuf的指针、计数器和状态变量,以表明内部缓冲区中有一个数据块。

    接着,通过将数据复制到程序的缓冲区,尝试满足来自内部缓冲区的frad调用。如果内部缓冲区没有足够的数据,则会再发出一个read()系统调用来填充内部缓冲区,将数据从内部缓冲区传输到程序缓冲区,直到满足所需的字节数(或者文件无更多数据)。

    将数据复制到程序的缓冲区之后,它会更新内部缓冲区的指针、计数器等,为下一个 fread()请求做好准。然后,它会返回实际读取的数据对象数量。

    (2)在随后的每次 fread(调用中,它都尝试满足来自FILE结构体内部缓冲区的调用。

    当缓冲区变为空时,它就会发出read)系统调用来重新填内部缓冲区。因此, fread()方面接受来自用户程序的调用,另一方面向操作系统内核发出read系统调用除了read()系统调用之外,所有 fread处理都在用户模式映像中执行。

    它只在需要时才会进入操作系统内核,并且以一种最高效匹配文件的方式进入。它会提供自动缓冲机制,因此用户程序不必担心这些具体操作。

  • fwrite算法

    fwrite算法与 j fread(0算法相似,只是数据传输方向不同。最开始,FE结构体的内部缓冲区是空的。
    在每次调用 fwrite()时,它将据写入内部缓冲区,并调整缓冲区的指针、计数器和状态变量,以跟踪缓冲区中的字数。
    如果缓冲区已满,则发出 write()系统调用,将整个缓冲区写入操作系统内核。

  • fclose算法

    若文件以写的方式被打开, fclose()会先关闭文件流局部缓冲区。然后,它会发出 close(fd)系统调用来关闭FE结构体中的文件述符。最后,它会释放FLE结构体,并将FLE指针重置为NULL。

  • 根据上面所讨论的内容,现在我们可以回答什么时候使用系统调用或库函数进行文件
    处理的问题。
    fread()依赖read()将数据从内核复制到内部缓冲区,然后从内部缓冲区将数据复制到程序的缓冲区。
    所以,它传输了两次数据。相反,read(将数据从内核直接复制到程序的缓冲区,只复制了一次。因此,对于以 BLKSIZE单位的读/写数据来说,read0本来就比read更高效,因为它只需要一个而不是两个复制操作。类似表述也适用wite和writer。

  1. 文件流缓冲

    每个文件流都有一个FILE结构体,其中包含一个内部缓冲区。对文件流进行读写需要遍历FILE结构体的内部缓冲区。文件流可以使用三种缓冲方案中的一种。

  • 无缓冲:从非缓冲流中写入或读取的字符将快单独传输到文件或从文件中传输。

  • 行缓冲:遇到换行符时,写人行缓冲流的字符以块的形式传输。

  • 全缓冲:写入全缓冲流或从中读取的字符以块大小传输到文件或从文件传输。

  1. 变参函数

    在I/O库函数中, printf()相当独特,因为多种不同类型的可变数量参数可以调用它。
    这是允许的,因为最初的C语言不是一种类型检查语言。
    目前,C语言和C会强制执行类型检查,但是为了方便,这两种语言仍然允许参数量可变的函数。这些函数必须至少使用一个参数进行声明。

posted @ 2021-09-18 21:43  李业达  阅读(36)  评论(0编辑  收藏  举报