码迷,mamicode.com
首页 > 系统相关 > 详细

嵌入式 Linux系统编程(三)——标准IO库

时间:2016-07-06 18:47:15      阅读:310      评论:0      收藏:0      [点我收藏+]

标签:嵌入式 linux 系统编程 标准io

嵌入式 Linux系统编程(三)——标准IO

    与文件IO函数相类似,标准IO库中提供的是fopenfclosefreadfwrite等面向流对象的IO函数,这些函数在实现时本身就要调用linux的文件IO这些系统调用。

一、标准IO库函数的缓冲机制

    由于IO设备的访问速度与CPU的速度相差好几个数量级,为了协调IO设备与CPU的速度的不匹配,对于块设备内核使用了页高速缓存,即数据会先被拷贝到操作系统内核的页缓存区中,然后才会从操作系统内核的缓存区拷贝到应用程序的地址空间。

当应用程序尝试读取某块数据的时候,如果这块数据已经存放在页缓存中,那么这块数据就可以立即返回给应用程序,而不需要经过实际的物理读盘操作。当然,如果数据在应用程序读取之前并未被存放在页缓存中,那么就需要先将数据从磁盘读到页缓存中去。对于写操作来说,应用程序也会将数据先写到页缓存中去,数据是 否被立即写到磁盘上去取决于应用程序所采用的写操作机制:如果用户采用的是同步写机制,那么数据会立即被写回到磁 盘上,应用程序会一直等到数据被写完为止;如果用户采用的是延迟写机制,那么应用程序就完全不需要等到数据全部被 写回到磁盘,数据只要被写到页缓存中去 就可以了。在延迟写机制的情况下,操作系统会定期地将放在页缓存中的数据刷到磁盘上。与异步写机制不同的是,延迟写机制在数据完全写到磁盘上得时候不会通 知应用程序,而异步写机制在数据完全写到磁盘上得时候是会返回给应用程序的。所以延迟写机制本省是存在数据丢失的风险的,而异步写机制则不会有这方面的担心。定义多大的缓冲大小才能使IO性能达到最大呢?

技术分享

    从上可以知道当缓冲达到4096大小的时候,继续增加缓冲大小对IO性能影响不大。这个4096大小由文件系统的块大小决定,由于上面的测试所用的文件系统是Linux ext2,块大小是4096

    标准IO库则很好的解决了设置缓冲大小的问题,标准IO会选择最佳的缓存大小,使得我们不用再关心设置缓存大小的问题,事实上标准IO库会对每个IO流自动进行缓冲管理,从而避免了应用程序需要考虑这一点所带来的麻烦。

标准IO提供三种类型的缓冲机制:

全缓冲:

    填满标准IO缓冲区后才进行实际的IO操作。对于在磁盘上的文件通常由标准IO库实施全缓冲的。在一个流上执行第一次I/O操作时,相关标准I/O函数通常调用malloc获得需使用的缓存区。

行缓冲:

    当在输入和输出中遇到换行符时,标准IO库执行IO操作。通常涉及到终端(例如标准输入和标准输出)使用的是行缓冲。

    对于行缓冲有两个限制。第一,因为标准IO库用来收集每一行的缓冲区的长度是固定的,所以只要填满了缓冲区,那么即使还没有写一个换行符,也进行IO操作。第二,任何时候只要通过标准IO库要求从(a)一个不带缓存的流,或者(b)一个行缓存的流(它要求从内核得到数据)得到输入数据,那么就会造成冲洗所有行缓冲输出流(因为后面读取的数据可能就是前面输出的数据)。其实第二种情况我们会经常遇到,当我们先调用printf输出一串不带换行符的字符时,执行完这条printf语句并不会立刻在屏幕中显示我们输出的数据,当我们接下来调用scanf从标准输入读取数据时,我们才看到前面输出的数据。

不带缓冲:

    标准IO库不对字符进行存储。例如,如果用标准IO函数fputs15个字符到不带缓冲的流中,则该函数很可能直接调用write系统调用将这些字符立即写到相关的文件中。标准出错流stderr是不带缓冲的,这样为了让出错的信息可以尽快的显示出来。


 二、标准IO库函数

#include <stdio.h>

 

FILE *fopen(const char *path, const char *mode);//mode为操作权限

FILE *fdopen(int fd, const char *mode);

FILE *freopen(const char *path, const char *mode, FILE *stream);

成功返回一个FILE文件流指针,失败返回NULL,并且设置errno全局变量。

Mode:

r:只读方式打开文件,返回的文件流指针位于文件开始

r+ :读写方式打开文件,返回的文件流指针位于文件开始

w:如果文件存在,清除文件写,如果文件不存在,创建文件写

w+:读写方式打开文件,文件不存在创建文件,存在则清空文件

a:追加写方式打开文件,如果不存在则创建文件,流指针位于文件尾

a+:读和追加写方式打开,如果文件不存在则创建文件,

 

#include <stdio.h>

 

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

Ptr:读取的数据存储的位置

Size:读取的每个单元的大小

Nmemb:读取的单元数量

Stream:从哪个文件流读取数据

成功返回读取的字节数,到达文件尾返回0,失败返回一个短数。

Fread不能区分到达文件尾和错误,因此必须使用feofferror函数确定是到达文件尾,还是发生错误。

size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);

Ptr:写入的数据的位置

Size:每次写入的单元的大小

Nmemb:写入的单元数

Stream:写入到哪个文件流

成功返回写入的字节数,到达文件尾返回0,失败返回一个短数。

 

#include <stdio.h>

int fclose(FILE *fp);

成功返回0,刷新缓存,失败返回EOF,并且设置errno

 

#include <stdio.h>

 

int fseek(FILE *stream, long offset, int whence);

long ftell(FILE *stream);

void rewind(FILE *stream);

rewind()函数无返回值,fseek成功返回0ftell成功返回当前偏移量,失败返回-1,并且设置errno



参考博文:

Linux标准IO缓存(博客园 在于思考

Linux manual

本文出自 “生命不息,奋斗不止” 博客,转载请与作者联系!

嵌入式 Linux系统编程(三)——标准IO库

标签:嵌入式 linux 系统编程 标准io

原文地址:http://9291927.blog.51cto.com/9281927/1796583

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!