文件 I/O操作open、lseek、read、write、close详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010765526/article/details/79949662

一,文件描述符、套接字和管道

        对于内核而言,所有打开的打开的文件都通过文件描述符引用。文件描述符是一个非负整数。

        内核为每个进程维护一个结构体struct task_struct,可称为进程控制块(PCB: Process Control Block)或进程描述符,含有一个称为打开文件描述符表的子结构体。普通的文件、套接字和管道都被放入其中,这说明这三者都被抽象为文件,共同占用进程占用的打开文件描述符。

        其中UNIX系统shell使用:

        文件描述符0与进程的标准输入相关联;

        文件描述符1标准输出相关联;

        文件描述符2标准出错输出相关联。


二,文件I/O函数

    1,open 函数可以打开或创建一个文件。

#include <fcntl.h>

int open(const char *pathname, int oflag, ... /* mode_t mode */ );

返回值:成功则返回文件描述符,出错则返回-1。

参数:

    pathname:是要打开或创建文件的名字。

    oflag:说明此函数的多个选项。可将它的选项进行“或”运算构成oflag。

            O_RDONLY            只读打开。

            O_WRONLY            只写打开。

            O_RDWR                读、写打开。

            这三个选项只能制定且必须一个。下列常量可选:

            O_APPEND            每次都从文件尾端写。

            O_CREAT               若文件不存在,则创建它。使用次选项必须带第三个参数。

            O_EXECL                如果指定了O_EXECL,而文件存在,则会出错。可以用它测试一个文件是否存在,如果不存在,则创建它。

            O_TRUNC                如果此文件存在,而且为只写或只读打开,则将其长度截短为0。

    2,create函数创建一个文件

#include <fcntl.h>

int create(const char *pathname, mode_t mode);

    返回值:成功则返回打开的文件描述符,出错则返回-1。

    由于它只能以只写的方式打开所创建的文件,所以等效于:

open(pathname, 0_WRONLY | O_CREAT | O_TRUNC, mode);

    3,close函数关闭一个打开的文件

#include <unistd.h>

int close(int filedes)

    返回值:成功则返回打开的文件描述符,出错则返回-1。

    如果一个进程没有调用close显示关闭,当进程终止时,内核会自动关闭它所有打开的文件。

    4,lseek函数 为一个打开的文件设置偏移量

     每个打开的文件都有一个与其关联的“当前文件偏移量”,它是一个非负整数,用以度量从文件开始处计算的字节数。默认情况下,打开一个文件,该偏移量被设置为0,除非制定了O_APPEND选项。

#include <unistd.h>

off_t lseek(int filedes, off_t offset, int whence)

    返回值:成功则返回新的文件的偏移量,出错则返回-1。

    参数:设置的偏移量offset与whence有关。

        whence     文件的偏移量设置为offset值
SEEK_SET文件开始处offset个字节必须为正数
SEEK_CUR文件偏移量当前值加offset可正可负
SEEK_END文件长度加offset可正可负

    如何确定当前打开文件的偏移量:

int curpose;
curpose = lseek(filedes, 0, SEEK_CUR);

    也可以用来判断所涉及的文件是否可以设置偏移量。因为文件描述符引用的是一个管道、FIFO或网络套接字,则lseek返回-1,并将error设置为ESPIPE。

    注意:lseek(file, 163840, SEEK_SET);如果文件偏移量大于文件的当前长度,对该文件的下一次写将加长该文件,并在文件中构成一个空洞,这些空洞不在磁盘上占用存储区,位于文件中但没有写过的字节都被读为0(即空洞都被读为0)。

    5,read函数 从打开的文件读数据

#include <unistd.h>

ssize_t read(int filedes, void *buf, size_t nbytes);

    返回值:

  • 若成功返回读到的字节数;
  • 若已到文件结尾返回0;
  • 若出错返回-1。        

    实际读到的字节数有可能少于要求读的字节数 nbytes:

  • 读取普通文件时,在读到要求字节数时已到达文件末尾。例如,若在到达文件末尾之前还有30个字节,而要求读100个字节,则read返回30,下一次再调用read时,它将返回0(文件尾端)。
  • 当从终端设备读时,通常一次最多读一行。
  • 当从网络读时,网络中的缓冲机构可能造成返回值小于所要求读的字节数。
  • 当从管道或FIFO读时,如管道包含的字节少于所需的数量,那么read将只返回实际可用的字节数。
  • 当某一信号造成中断,而已经读了部分数据量时。

    6,write函数 向打开的文件写入数据

#include <unistd.h>

ssize_t write(int filedes, const void *buf, size_t nbytes);

    返回值:

  • 若成功返回已写入的字节数;
  • 如出错返回-1。

    返回值通常与参数nbytes的值相同,否则表示出错(比如缓冲区已满)。

               

       

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页