设为首页 收藏本站
查看: 306|回复: 0

[经验分享] 一步步理解Linux IO(1)–Linux的IO和标准IO库

[复制链接]

尚未签到

发表于 2016-2-25 09:28:00 | 显示全部楼层 |阅读模式
一步步理解Linux IO(1)–Linux的IO和标准IO库


作者:gaopenghigh,转载请注明出处。(原文地址)



Linux文件IO的常用函数


Linux中做文件IO最常用到的5个函数是:open,close,read,write和lseek,不是ISO
C的组成部分,这5个函数是不带缓冲的IO,也即每个read和write都调用了内核的一个系统调用。另外,dup函数和sync函数也经常用到,下面我们大致看一下这7个函数。



open函数


#include <fcntl.h>
int open(const char *pathname, int oflag, ... /* mode_t mode */);
/* 成功返回文件描述符, 失败返回-1 */

open函数打开或创建一个文件。pathname表示文件的路径,oflag表示打开的方式。通过控制oflag,可以规定打开文件的读写和追加模式、是否创建不存在的文件、是否截短为0、是否阻塞、读操作是否等待写操作完成、写操作是否等待物理IO操作完成等等。



close函数


#include <unistd.h>
int close(int filedes);
/* 成功返回0, 失败返回-1 */

关闭一个文件时,还会释放该文件上的所有记录锁。另外,当一个进程终止时,它会自动关闭所有它打开的文件。



lseek函数



每个打开的文件都有一个“当前文件偏移量(current file offset)”,read和write操作都从这个当前文件偏移量开始。


#include <unistd.h>
off_t lseek(int filedes, off_t offset, int whence);
/* 成功返回新的文件偏移量,出错返回-1 */

参数whence表示到底是从文件开始处、文件末尾还是文件当前偏移位置来计算offset。



read函数



read函数从打开的文件中读取数据,数据存放到buf指向的空间中,最大读取的字节数为nbytes。


#include <unistd.h>
ssize_t read(int filedes, void *buf, size_t nbytes);
/* 成功则返回读取到的字节数,若已到文件的结尾返回0,出错返回-1 */

write函数



write函数向打开的文件写入数据,数据由buf指向的空间提供,最大写入的字节数为nbytes。


#include <unistd.h>
ssize_t write(int filedes, void *buf, size_t nbytes);
/* 成功则返回写入的字节数,出错返回-1 */

dup和dup2函数



这两个函数用来复制一个现存的文件描述符。


#include <unistd.h>
int dup(int filedes);
int dup2(int fileds, int filedes2);
/* 成功则返回新的文件描述符,出错返回-1 */

dup函数从当前可用的文件描述符中找一个最小的返回


dup2用filedes2指定新文件描述符的值。


sync, fsync和fdatasync函数


这三个函数都是刷缓存的:


#include <unistd.h>
int fsync(int filedes);     /* 刷filedes指代的文件的缓存到磁盘 */
int fdatasync(int filedes); /* 与fsync类似,但只刷数据,不刷属性 */
/* 成功返回0,失败返回-1 */
void sync(void);            /* 刷所有脏的缓存 */

Linux中的标准IO库

缓冲


标准IO库提供缓冲功能,包括:



  • 全缓冲。即填满IO缓冲区后才进行IO操作。
  • 行缓冲。遇到换行符时执行IO操作。 * 无缓冲。


一般情况下,标准出错无缓冲。如果涉及终端设备,一般是行缓冲,否则是全缓冲。


可用setbuf和setvbuf函数设置缓冲类型已经缓冲区大小,使用fflush函数冲洗缓冲区。


打开流


使用fopen,freopen,fdopen三个函数打开一个流,这三个函数都返回FILE类型的指针。


#include <stdio.h>
FILE *fopen(const char *restrict pathname, const char *restrict type);
FILE *freopen(const char *restrict pathname, const char *restrict type,
FILE *restrict fp);
FILE *dopen(int filedes, const char *type);
/* 成功返回FILE类型指针,出错返回NULL */

其中,




  • fopen打开一个指定的文件。

  • freopen在一个指定的流上打开一个文件,比如在标准输出流上打开某文件。

  • dopen打开指定的文件描述符代表的文件。常用于读取管道或者其他特殊类型的文件,因为这些文件不能直接用fopen打开。


type参数指定操作类型,入读写,追加等等。


关闭流


fclose函数关闭一个流:


#include <stdio.h>
int flose(FILE *fp);
/* 成功返回0,出错返回EOF */
读和写流

每次一个字符的IO

#include <stdio.h>
/* 输入 */
int getc(FILE *fp);
int fgetc(FILE *fp);
int getchar(void);
/* 上面三个函数的返回值为int,因为EOF常实现为-1,返回int就能与之比较 */
/* 判断出错或者结束 */
int ferror(FILE *fp);
int feof(FILE *fp);
void clearerr(FILE *fp); /* 清除error或者eof标志 */
/* 把字符压送回流 */
int ungetc(intc FILE *fp);
/* 输出 */
int putc(int c, FILE *fp);
int fputc(int c, FILE *fp);
int putchar(int c);
每次一行的IO

#include <stdio.h>
/* 输入 */
char *fgets(char *restrict buf, int n, FILE *restrict fp);
char *gets(char *buf);
/* gets由于没有指定缓冲区,所以有可能造成缓冲区溢出,要小心 */
/* 输出 */
int fputs(char *restrict buf, FILE *restrict fp);
int puts(const char *buf);
二进制IO

#include <stdio.h>
size_t fread(void *restrict ptr, size_t size, size_t nobj,
FILE *restrict fp);
size_t fwrite(const void *restrict ptr, size_t size, size_t nobj,
FILE *restrict fp);
/* 返回值:读或写的对象数 */
定位流

#include <stdio.h>
long ftell(FILE *fp);
/* 成功则返回当前文件位置指示,出错返回-1L */
int fseek(FILE *fp, long offset, int whence);
/* 成功返回0, 出错返回非0 */
int fgetpos(FILE *restrict fp, fpos_t *restrict pos);
int fsetpos(FILE *fp, fpos_t *pos);
/* 成功返回0,出错返回非0 */
格式化IO


执行格式化输出的主要是4个printf函数:




  • printf输出到标准输出

  • fprintf输出到指定流

  • sprintf输出到指定数组

  • snprintf输出到指定数组并在数组的尾端自动添加一个null字节


格式化输入主要是三个scanf函数:




  • scanf从标准输入获取

  • fscanf从指定流获取

  • sscanf从指定数组获取


JH, 2013-05-01




参考资料:



  • 《Unix环境高级编程》
  • 《深入理解Linux内核》
  • 《Linux内核设计与实现》

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-182524-1-1.html 上篇帖子: linux chkconfig命令参数及用法详解--linux系统服务设置命令 下篇帖子: 【Linux 驱动】第十章 中断处理
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表