【Linux】IO基本操作及原理

 

目录

一、库函数

1.fopen

2.fclose

3.fwrite

4.fread

5.fseek

二、系统调用

1.open 

 2.close

3.write

4.read

5.lseek

三、文件流指针和文件描述符


        我们最早接触IO操作函数应该就是c语言了吧,所有今天我们从c语言中的函数出发,逐层剥离,回归到IO操作的本质。

一、库函数

1.fopen

FILE *fopen( const char*path , const char *mode);

//path:需要打开文件的地址,也包括文件名,若文件在当前路径下,可直接使用文件名。

//mode:打开文件的参数,具体参数如下
r:只读模式打开

r+:可读可写模式打开

w:若文件存在,清空文件内容;若文件不存在,则创建一个新文件

a:若文件存在,就在文件原有内容后接着写;若不存在,就创建文件

a+:可读也可追加写。若文件不存在,就创建文件

返回值

       成功:文件流指针

       失败:NULL

2.fclose

int close(FILE *fp);
//fp:文件流指针

3.fwrite

size_t fwrite(const void *buf , size_t size ,size_t nmemb,FILE *stream)
//buf:写的内容
//size:定义往文件中写的时候一个块多大,单位字节。
//nmemb:期望写多少个块
//stream:文件流指针

返回值

         成功写入的块的个数

4.fread

size_t fread( void *ptr , size_t size ,size_t nmemb,FILE *stream)
//ptr:将文件内容读到ptr指向的内存空间中
//size:定义文件中读的时候一个块多大,单位字节。
//nmemb:期望读多少个块
//stream:文件流指针

返回值

       成功写入的块的个数

5.fseek

int fseek(FILE *stream,long offset,int whence);
//stream:文件流指针
//offset:偏移量
/*whence:将文件流指针偏移到什么位置
    SEEK_SET:文件开头
    SEEK_CUR: 当前文件流指针的位置
    SEEK_END:文件末尾*/

返回值

       成功:0

       失败:-1

       以上为c语言标准库函数,下边为系统调用函数,系统调用是操作系统提供的接口,主要是面向硬件的,库函数一般是大牛程序员将系统调用封装简化之后给其他程序员的,目的是为了方便编程。如果你想写程序,使用系统调用和库函数都是可以的。

二、系统调用

1.open 

int open (const char *pathname,int flags);
int open(const char *pathname,int flags,mode_t mode);
/*pathname:要打开的目标文件
flags:打开文件的3个参数(有且只能有一个)
        O_RDONLY:只读打开
        O_WRONLY:只写打开
        O_RDWR:读写打开
    可选参数:
        O_CREAT:若文件不存在,则创建
        O_APPEND:追加写
mode:打开文件的权限*/

例子:

int open(  buf  , O_RDWR  |  O_CREAT , 0664);

 2.close

int close(int *fd);

3.write

int write(int fd,const void *buf,size_t count);
/*
fd:文件描述符
buf:将buf指向的内容写到文件中去
count:期望写多少字节
*/

返回值

       返回写的字节数量

4.read

int read(int fd,void *buf,size_t count);
/*
fd:文件描述符
buf:将文件中的内容读到buf指向的内存空间中去
count:期望读多少字节
*/

返回值

       返回读的字节数量

5.lseek

off_t lseek(int fd,off_t offset,int whence);
/*
fd:文件流指针
offset:偏移量
whence:将文件流指针偏移到什么位置
    SEEK_SET:文件开头
    SEEK_CUR: 当前文件流指针的位置
    SEEK_END:文件末尾
*/

返回值

      成功:返回偏移位置

      失败:-1

三、文件流指针和文件描述符

      此时你会发现,系统调用传参都是文件描述符,库函数封装之后就是文件流指针。

“文件流指针”是一个被称为FILE结构的数据结构,这个结构体实际上定义了一个缓冲区和一个文件描述符值。

Q:为什么库函数封装的时候要增加定义这个缓冲区?

       因为IO操作太耗费时间,cpu要是阻塞等待IO操作的话,效率太低,于是人们想出一个办法,在读写时不用每个字节都进行IO操作,可以等信息积攒到一定量之后,再进行IO操作。积攒的这个过程,信息就放在缓冲区。这样就能减少IO次数,提高效率。

Q:我不使用库函数,直接使用系统调用是不是就不用经过缓冲区了?

对的,库函数才定义了缓冲区,系统调用传递的参数是文件描述符,所以是实时进行IO操作的。

Q:文件流指针具体是如何封装文件描述符的?

                                                           系统调用简单工作原理

           左边的框是进程控制信息,后边的博客我会讲解,pcb中的一个成员变量是文件指针,文件指针结构体其实是一个数组,这个数组保存着这个进程打开的所有文件信息,数组的下标其实就是文件描述符。实际系统调用时其实传递的就是这个数组下标,然后就能找到对应的属于具体文件的结构体指针,通过指针指向的空间就能找到文件信息。

文件流指针原理

     

       读写缓冲区其实就是三个指针,分别指向缓冲区开始、结束、当前读写位置,当读写指针到达缓冲区尾时,刷新缓冲区。

Q:那我自己可以指定文件和文件描述符的关系吗?

       当然可以,这个时候就要使用重定向函数了,它的作用将newfd的值变为oldfd.

int dup2(int oldfd,int newfd);
//newfd,oldfd都是文件描述符

  成功:

         关闭newfd;

         newfd指向oldfd所指的结构体

 失败:

        保持原样

以上就是全部关于文件描述符和文件流指针的操作了,希望各位看官老爷看的开心。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一颗二叉树_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值