系统IO接口

一、系统IO接口说明

  • 基本概念

由于Linux系统下“一切皆文件”,也就是Linux系统下的数据和程序(shell命令)都是以文件的形式存储的,所以Linux内核会提供一组操作文件的函数接口,这组函数接口也被称为系统IO。

同时为了满足用户访问文件的需求以及提高用户程序的可移植性,标准库也提供了一组操作文件的函数接口,这组函数接口也被称为标准IO,只不过标准库提供的标准IO函数都是遵循ANSI C标准设计出来,是为了方便用户在不同的操作系统下可以调用通用的函数来实现对文件的读写访问,但其实标准IO也是基于内核提供的系统IO设计出来的。

  • 两者区别

标准IO的优点是提供了缓冲区并且函数接口非常丰富,虽然标准IO是在系统IO的基础之上实现的,但是由于标准IO提供了输入输出缓冲区,这样可以避免频繁的系统调用,而且不用人为关心缓冲区大小的选择,整体上提高了I/O的效率。但是缺点是没有办法针对某些类型的文件(链接文件、套接字文件)进行访问,所以一般适合访问普通文件。

而系统IO的缺点是不具备输入输出缓冲区,也就是没办法高效处理数据,原因是系统调用与普通函数调用相比通常需要花费更多的时间,因为系统调用的过程中内核要执行一系列的操作:首先内核需要捕获调用,然后再检查系统调用传递的参数的有效性,最后在用户空间和内核空间之间传输数据。但是系统IO的优点是可以针对特定类型文件进行访问,所以一般适合访问数据需要实时刷新的硬件设备(LCD、触摸屏......)。

简单理解:标准I/O可以看成是在系统I/O的基础上封装了缓冲机制。这样可以先读写缓冲区,必要时再访问实际文件,从而减少了系统调用的次数,提高访问效率。

fwrite() --> a.txt -->fwrite(buf,1,1,fp); --> write() --> 100个字节要写--> 调用100次write() -->慢

fwrite() --> a.txt -->fwrite(buf,1,100,fp); -->write() -->100个字节要写-->调用001次write() -->快

  1. 打开文件

Linux内核提供了用于打开文件的open函数,由于该函数属于系统IO函数,所以在C99标准中是查询不到的,可以在Linux系统的man手册的第二个章节中找到系统IO函数的描述。

可以看到,open函数的第三个参数mode只有在open函数的第二个参数flags使用O_CREAT或者O_TMPFILE才会使用,也就是说,打开一个已经存在的文件使用第一个版本的open函数即可,第二个版本的open函数的mode参数是指利用open函数创建新文件时给新创建的文件一个指定权限,被创建的文件的权限其实就是Linux系统下文件的权限,可以分为三种:

一般在Linux系统下可以直接使用shell命令来修改文件的权限,比如指令chmod 777 xxx.txt就是给该文档一个最高权限。注意:mode参数应该采用八进制。

通过man手册可以知道,如果文件打开成功,则open函数返回一个文件描述符,这个文件描述符是一个非负整数,并且这个非负整数是当前进程中未被分配的文件描述符中最小的。如果文件打开失败,则open函数的返回值是-1,并且错误原因采用错误码的方式进行存储。

思考:请问这个open函数的文件描述符有什么作用?这个返回值对应的数字范围是多少???

回答:open函数的返回值可以理解为是被打开文件的代号,内核并不是以被打开文件的路径和名称来管理文件,而是在调用open函数的时候会从未分配的文件描述符中找到一个最小的提供给被打开的文件。在对文件进行读写(R/W)访问时同样是通过这个文件描述符实现。

文件描述符本质就是一个非负整数,从内核源码角度分析,这个整数实际上是内核中的一个称为 fd_array 的数组下标。

打开文件时,内核产生一个指向 file{} 的指针,并将该指针放入一个位于 file_struct{} 中的数组 fd_array[] 中,而该指针所在数组的下标,就被 open() 返回给用户,所以内核把这个数组下标称为文件描述符。

文件描述符从0开始分配,每打开一个文件,就产生一个新的文件描述符。当然,用户可以重复打开同一个文件,每次打开文件都会使内核产生新的结构体,并得到不同的文件描述符。

练习:利用open函数测试默认情况下程序最多可以打开多少个文件。提示:同一个文件可以被多次打开。

  1. 关闭文件

Linux内核提供了用于关闭文件的close函数,由于该函数属于系统IO函数,所以在C99标准中是查询不到的,可以在Linux系统的man手册的第二个章节中找到系统IO函数的描述。

注意:close函数可以对同一个文件反复调用,并且不会出错,因为open函数没有申请堆内存,但是多次调用close函数关闭同一个文件的动作是没有意义。

  1. 文件读取

Linux内核提供了用于读取文件的read函数,由于该函数属于系统IO函数,所以在C99标准中是查询不到的,可以在Linux系统的man手册的第二个章节中找到系统IO函数的描述。

  1. 文件写入

Linux内核提供了用于写入文件的write函数,由于该函数属于系统IO函数,所以在C99标准中是查询不到的,可以在Linux系统的man手册的第二个章节中找到系统IO函数的描述。

  1. 位置偏移

Linux内核提供了用于设置文件位移的lseek函数,由于该函数属于系统IO函数,所以在C99标准中是查询不到的,可以在Linux系统的man手册的第二个章节中找到系统IO函数的描述。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值