Linux系统编程(第三章)笔记

缓冲I/O

   由于块是文件系统中最小存储单元的抽象,在内核中,所有文件系统操作都是基于块来执行。因此所有I/O操作都是在块大小或者块大小的整数倍上执行。
   假设要读取1024个字节,每次读一个字节需要1024次调用,而如果一个读取1024字节的块则只需要调用一次。对于这种提升其性能的途径是“用户缓冲I/O”。

用户缓冲I/O

   用户缓冲I/O在用户空间完成,类似内核通过延迟写,合并相邻I/O请求以及预读等操作来缓冲数据的这些方法提高性能。
   当数据被写入时,它会被存储到程序地址空间的缓冲区中。当缓冲区数据大小达到给定值,即缓冲区大小,整个缓冲区会通过一次写操作全部写出。同样读操作也是一次读入缓冲区大小且块对齐的数据。

标准I/O

   C标准库中提供了标准I/O库(简称stdio),它实现了跨平台的用户缓冲解决方案。这个标准I/O库使用简单,且功能强大。

文件指针

   标准I/O程序集并不是直接操作文件描述符。相反,它们通过唯一标识符,即文件指针来操作。在C标准库里,文件指针和文件描述符一一映射。
   在标准I/O中,打开的文件称为“流”。流可以被打开用来读(输入流),写(输出流)或者二者兼有(输入/输出流)。

文件操作

   fopen():

#include<stdio.h>
FILE* fopen(const char *path,const char *mode);

   该函数根据mode参数,按指定模式打开path所指向的文件,并给它关联上新的流。
   fdopen():

#include<stdio.h>
FILE* fdopen(int fd,const char *mode);

   fdopen()的可能模式和fopen()相同,而且必须和初始打开文件描述符的模式匹配。可以指定模式w和w+,但是它们不会清空原文件。流指针指向文件描述符指向的文件位置。
   fclose():

#include<stdio.h>
int fclose(FILE *stream);

   在关闭前,所有被缓冲但还没有写出的数据都会被写出。还有一种fcloseall哈数关闭和当前进程相关联的所有流包括标准输入,标准输出和标准错误。Linux特有的。
   一旦文件描述符被转换成流,则在该文件描述符上不应该直接执行I/O操作,虽然这么做是合法的。需要注意的是,文件描述符并没有被复制,而只是关联了一个新的流。关闭流也会关闭相应的文件描述符。
   fgetc():

#include<stdio.h>
int fgetc(FILE *stream);

   该函数从stream中读取一个字符,并把该字符强制类型转换成unsigned int返回。ungetc()把读取的一个字符放回流中。
   fgets():

#include<stdio.h>
char * fgets(char *str,int size,FILE *stream);

   该函数从stream中读取size-1个字节的数据,并把结果保存到str中。读取二进制数据有fread()。
   写入流数据操作有fputc(),fputs(),fwrite()等等。

定位流

   fseek():

#include<stdio.h>
int fseek(FILE *stream,long offset,int whence);

   fseek()函数是标准I/O最常用的定位函数,控制stream指向文件中由参数offset和whence确定的位置。还提供了其他函数:fsetpos(),rewind(),ftell()。

Flush(刷新输出)流

   fflush():

#include<stdio.h>
int fflush(FILE *stream);

   调用该函数时,stream指向的流中所有未写入的数据会被flush到内核中。如果stream是空的,进程中所有打开的流都会被flush。成功时返回0,失败时返回EOF。

错误和文件结束

   ferror():

#include<stdio.h>
int ferror(FILE *stream);

   判定给定的stream是否有错误标志。feof()用于判断指定stream是否设置了文件结束标志,clearer()函数会清空指定stream的错误和EOF标志。

获取关联的文件描述符

   fileno():

#include<stdio.h>
int fileno(FILE *stream);

   成功时返回和指定stream关联的文件描述符。失败时返回-1.

控制缓冲

   setbuf():

#include<stdio.h>
int setvbuf(FILE *stream,char *buf,int mode,size_t size);

   mode值必须是以下之一:_IONBF(无缓冲),_IOLBF(行缓冲),_IOFBF(块缓冲)。

线程安全

   在访问共享数据时,有两种方式可以避免修改它:一是采取数据同步访问机制(通过加锁实现),二是把数据存储在线程的局部变量中。
   标准I/O函数在本质上是线程安全的。在每个函数的内部实现中,都关联了一把锁,一个锁计数器,以及持有该锁并打开一个流的线程,每个线程在执行任何I/0请求之前。必须首先获得锁而且持有该锁。两个或多个运行在同一个流上的线程不会交叉执行标准I/O操作,因此,在单个函数调用中,标准I/O操作是原子操作。

手动文件加锁

   flockfile():

#include<stdio.h>
void flockfile(FILE *stream);

   等待指定stream被解锁,然后增加自己的锁计数,获得锁,该函数的执行线程成为流的持有者,并返回。
   funlockfile():

#include<stdio.h>
void funlockfile(FILE *stream);

   减少和指定stream关联的锁计数。如果锁计数值为0,当前线程会放弃对该流的持有权,另一个线程可以获得锁。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值