linux 文件IO
1、文件描述符
(1)文件描述符的本质是一个数字,这个数字本质上是进程表中文件描述符表的一个表项,进程通过文件描述符作为index去索引查表得到文件表指针,再间接访问得到这个文件对应的文件表。
(2)文件描述符这个数字是open系统调用内部由操作系统自动分配的,操作系统分配这个fd时也不是随意分配,也是遵照一定的规律的,我们现在就要研究这个规律。
(3)操作系统规定,fd从0开始依次增加。fd也是有最大限制的,在linux的早期版本中(0.11)fd最大是20,所以当时一个进程最多允许打开20个文件。linux中文件描述符表是个数组(不是链表),所以这个文件描述符表其实就是一个数组,fd是index,文件表指针是value
(4)当我们去open时,内核会从文件描述符表中挑选一个最小的未被使用的数字给我们返回。也就是说如果之前fd已经占满了0-9,那么我们下次open得到的一定是10.(但是如果上一个fd得到的是9,下一个不一定是10,这是因为可能前面更小的一个fd已经被close释放掉了)
(5)fd中0、1、2已经默认被系统占用了,因此用户进程得到的最小的fd就是3了。
(6)linux内核占用了0、1、2这三个fd是有用的,当我们运行一个程序得到一个进程时,内部就默认已经打开了3个文件,这三个文件对应的fd就是0、1、2。这三个文件分别叫stdin、stdout、stderr。也就是标准输入、标准输出、标准错误。
(7)标准输入一般对应的是键盘(可以理解为:0这个fd对应的是键盘的设备文件),标准输出一般是LCD显示器(可以理解为:1对应LCD的设备文件)
(8)printf函数其实就是默认输出到标准输出stdout上了。stdio中还有一个函数叫fpirntf,这个函数就可以指定输出到哪个文件描述符中。
2、常用API
open、close、write、read、lseek
2.1OPEN
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode)
const char *pathname为需要打开的文件、
flags通过一些宏设置读写权限
O_RDONLY、 O_WRONLY 、O_RDWR(只读 只写 读写)
O_APPEND O_APPEND属性去打开文件时,如果这个文件中本来是有内容的,则新写入的内容会接续到原来内容的后面
O_TRUNC O_TRUNC属性去打开文件时,如果这个文件中本来是有内容的,则原来的内容会被丢弃。
O_CREAT O_CREAT若不存在则创建。open函数在使用O_CREAT标志去创建文件时,可以使用第三个参数mode来指定要创建的文件的权限。mode使用4个数字来指定权限的,其中后面三个很重要,对应我们要创建的这个文件的权限标志。譬如一般创建一个可读可写不可执行的文件就用0666
O_EXCL 加上O_EXCL如果文件已经被打开则打开失败
O_NONBLOCK 默认为阻塞模式。添加这个设置为非阻塞模式
O_SYNC write阻塞等待底层完成写入才返回到应用层。
2.2 read
ssize_t read(int fd, void *buf, size_t count);
2.3 write
ssize_t write(int fd, const void *buf, size_t count);
2.3lseek
执行read与write函数都会使文件指针移动。lseek函数可以调整文件指针。
off_t lseek(int fd, off_t offset, int whence);
参数解释。第一个代表文件描述符、第二个代表移动个数、第三个设置移动头。
lseek(fd, 0 ,SEEK_SET);//文件指针指向头
SEEK_SET代表指向头
SEEK_END代表尾部
SEEK_CUR代表当前位置
3.3close
可以通过close关闭打开的文件描述符。
3.4dup和dup2函数
(1)dup系统调用对fd进行复制,会返回一个新的文件描述符(譬如原来的fd是3,返回的就是4)
(2)dup系统调用有一个特点,就是自己不能指定复制后得到的fd的数字是多少,而是由操作系统内部自动分配的,分配的原则遵守fd分配的原则
(3)dup2和dup的作用是一样的,都是复制一个新的文件描述符。但是dup2允许用户指定新的文件描述符的数字。
3.5fcntl的原型和作用
fcntl函数是一个多功能文件管理的工具箱,接收2个参数+1个变参。第一个参数是fd表示要操作哪个文件,第二个参数是cmd表示要进行哪个命令操作。变参是用来传递参数的,要配合cmd来使用。
4、标准IO库介绍
4.1、标准IO和文件IO有什么区别
(1)看起来使用时都是函数,但是:标准IO是C库函数,而文件IO是linux系统的API
(2)C语言库函数是由API封装而来的。库函数内部也是通过调用API来完成操作的,但是库函数因为多了一层封装,所以比API要更加好用一些。
(3)库函数比API还有一个优势就是:API在不同的操作系统之间是不能通用的,但是C库函数在不同操作系统中几乎是一样的。所以C库函数具有可移植性而API不具有可移植性。
(4)性能上和易用性上看,C库函数一般要好一些。譬如IO,文件IO是不带缓存的,而标准IO是带缓存的,因此标准IO比文件IO性能要更高。
4.2、常用标准IO函数介绍
(1)常见的标准IO库函数有:fopen、fclose、fwrite、fread、ffulsh、fseek
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc , char *argv[])
{
int fd=-; //fd 文件描述符
char buf[]={};//字符缓冲区
char writebuf[]="ilovezw";//字符缓冲区
int ret;
//第一步打开
//fd = open ("a.txt",O_RDWR|O_APPEND);
fd = open ("a.txt",O_RDWR);
if(- == fd)
{
perror("文件打开错误");
_exit(-);
}
else
{
printf("文件打开成功,fd=%d.\n",fd);
}
//lseek(fd, 3 ,SEEK_SET);//光标位移3 //第二步读写 ret=write(fd,writebuf,strlen(writebuf));//写函数
if(-==ret)
{
//printf("write error");
perror("write error");
_exit(-);
}
else
{
printf("ret=%d\n",ret);
//lseek(fd, -ret ,SEEK_SET);//光标位移3
}
lseek(fd, ,SEEK_SET);//文件指针指向头
ret=read(fd,buf,);//读文件
if(-==ret)
{
//printf("read error");
perror("read error");
_exit(-);
}
else
{
printf("ret=%d,a.txt=%s\n",ret,buf);
}
//第三步关闭
close(fd);
return ;
}
/*标准IO
*/ #include<stdio.h>
#include<stdlib.h>
#include<string.h> int main(int argc,char * argv[])
{
FILE *fp =NULL;
char buf[];
fp = fopen("1.txt","r+");
if(NULL == fp)
{
perror("fopen");
exit(-);
}
memset(buf,,sizeof(buf));
fwrite("",,,fp);
fseek( fp, , SEEK_SET );
fread(buf,,,fp);
printf("%s\n",buf);
fclose(fp);
return ;
}
linux 文件IO的更多相关文章
- 转:Linux 文件IO理解
源地址http://blog.csdn.net/lonelyrains/article/details/6604851 linux文件IO操作有两套大类的操作方式:不带缓存的文件IO操作,带缓存的文件 ...
- 转 漫谈linux文件IO
在Linux 开发中,有几个关系到性能的东西,技术人员非常关注:进程,CPU,MEM,网络IO,磁盘IO.本篇文件打算详细全面,深入浅出.剖析文件IO的细节.从多个角度探索如何提高IO性能.本文尽量用 ...
- 漫谈linux文件IO
在Linux 开发中,有几个关系到性能的东西,技术人员非常关注:进程,CPU,MEM,网络IO,磁盘IO.本篇文件打算详细全面,深入浅出.剖析文件IO的细节.从多个角度探索如何提高IO性能.本文尽量用 ...
- <摘录>linux文件IO
这篇文章写的比较全面,也浅显易懂,备份下.转载自:http://blog.chinaunix.net/uid-27105712-id-3270102.html 在Linux 开发中,有几个关系到性能的 ...
- 2.Linux文件IO编程
2.1Linux文件IO概述 2.1.0POSIX规范 POSIX:(Portable Operating System Interface)可移植操作系统接口规范. 由IEEE制定,是为了提高UNI ...
- linux文件io与标准io
文件IO实际是API,Linux对文件操作主要流程为:打开(open),操作(write.read.lseek),关闭(close). 1.打开文件函数open(): 涉及的头文件: #includ ...
- Linux文件IO操作
来源:微信公众号「编程学习基地」 目录 文件操作 Linux文件类型 Linux文件权限 修改文件权限 Linux error 获取系统调用时的错误描述 打印错误信息 系统IO函数 open/clos ...
- linux文件IO操作篇 (一) 非缓冲文件
文件IO操作分为 2 种 非缓冲文件IO 和 缓冲文件IO 它们的接口区别是 非缓冲 open() close() read() write() 缓冲 fopen() fclose() fread() ...
- Linux文件IO与通用块层的请求合并
本文参考https://mp.weixin.qq.com/s/Imt4BW-zoHPpcOpcKZs_AQ, 公众号“Linux阅码场” 请求合并就是将进程内或者进程间产生的在物理地址上连续的多个IO ...
随机推荐
- Centos7 Ntp 时间服务器
Centos7 Ntp 时间服务器 安装环境 [root@m02 ~]# cat /etc/redhat-release CentOS Linux release 7.4.1708 (Core) 安装 ...
- 用了这么多年的MCU,你知道哪些MCU原厂最牛?
单片机诞生于1971年,经历了SCM.MCU.SoC三大阶段.单片机由以前的1位.4位.8位.16位,发展到现在的32位甚至64位. 90年代后随着消费电子产品大发展,单片机技术得到了巨大提高,相继诞 ...
- Python中import的as语法
在Python中,如果import的语句比较长,导致后续引用不方便,可以使用as语法,比如: import dir1.dir2.mod # 那么,后续对mod的引用,都必须是dir1.dir2.mod ...
- lintcode-387-最小差
387-最小差 给定两个整数数组(第一个是数组 A,第二个是数组 B),在数组 A 中取 A[i],数组 B 中取 B[j],A[i] 和 B[j]两者的差越小越好(|A[i] - B[j]|).返回 ...
- java一些知识
类名前只有两种修饰符:不写(即default,但不能把default写上去)或public.默认不写则此类只能被同一包下的类调用以生成相应的实例.但若是public,则可以被不同包下的类调用以生成其实 ...
- 重写JdbcRDD支持Sql命名参数和分区
Spark提供的JdbcRDD很不好用,没法指定命名参数,而且必须要提供两个Long类型的参数表示分区的范围,如果数据表没有long类型的字段或者不需要条件,那就不能用JdbcRDD了.这里我简单重写 ...
- IDEA设置头注释—自定义author和date
IDEA设置头注释,自定义author和date的方法如下所示: 去掉波浪线的方式:鼠标选中单词 --> 点击鼠标右键 --> spelling --> save 'xxx' to ...
- C# 7.0 本地方法
VS 2017 的 C# 7.0 中引入了本地方法,本地方法是一种语法糖,允许我们在方法内定义本地方法.更加类似于函数式语言,但是,本质上还是基于面向对象实现的. 1. 本地方法 先看一个示例: 1 ...
- Java web 强制301跳转
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); response.setHeader("Location" ...
- 【Linux笔记】Linux中inittab剖析
Linux完成内核(Kernel)引导后,会由init初始化进程调用/etc/inittab配置文件(ps -aux | less,init进程号为始终为1,是所有系统进程的起点,init进程也有一个 ...