Linux文件IO

1.系统调用

(1)基于linux做应用开发,其实就是通过调用linux系统提供的系统调用来实现.
(2)系统调用是一些由linux系统提供的函数,给应用层使用,以完成一定的功能。
(3)常用的文件IO的系统调用函数有open,close,write,read,lseek等。

2.文件IO和标准IO的异同

(1)标准IO是C库函数,文件IO是Linux操作系统提供的;
(2)C库函数由API封装而来;
(3)C库函数具有移植性,而API是针对具体的系统设计的;
(4)标准IO带有缓存,而文件IO没有缓存。

3.文件I/O概念

  1. 不带缓冲
    不带缓冲指的是每个read和write都调用内核中的相应系统调用
    不带缓冲的I/O函数不是ANSI C的组成部分,而是POSIX的组成部分

  2. 通过文件描述符来访问文件

文件I/O常用函数

  • open()/creat()
  • close()
  • read()
  • write()
  • lseek()
  • fcntl
  • ioctl

文件描述符

  • 对于内核而言,所有打开文件都由文件描述符表示。
  • 文件描述符是一个非负整数。当打开一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符。
  • 当读、写一个文件时,用open或creat返回的文件描述符标识该文件,将其作为参数传送给read或write。

3.1 文件I/O_open()/creat()

调用open()/creat()函数可以打开或者创建一个文件。
在这里插入图片描述

  • open()和creat()调用成功返回文件描述符,失败返回-1,并设置errno。
  • open()/creat()调用返回的文件描述符一定是最小的可用文件描述符。
  • creat()等价于open(pathname,O_CREAT|O_WRONLY|O_TRUNC, mode)。
  • open()可以打开设备文件,但是不能创建设备文件

open()

      在这里插入图片描述
详情:

  • mode_t类型的加权数字形式,umask变量
    在这里插入图片描述
  • open返回值,非负整数,代表函数执行成功,用fd表示:file descrpitor文件描述符。

3.2 文件I/O – close()

调用close()函数可以关闭一个打开的文件。
在这里插入图片描述
详情:

  • 调用成功返回0,出错返回-1,并设置errno。
  • 当一个进程终止时,该进程打开的所有文件都由内核自动关闭。
  • 关闭一个文件的同时,也释放该进程加在该文件上的所有记录锁。

example: 关闭一个已经打开的文件:
      在这里插入图片描述

3.3 文件I/O_read()

调用read()函数可以从一个已打开的可读文件中读取数据。
在这里插入图片描述
详情:

  • read()调用成功返回读取的字节数,如果返回0,表示到达文件末尾,如果返回-1,表示出错,通过errno设置错误码。
  • 读操作从文件的当前位移量处开始,在成功返回之前,该位移量增加实际读取的字节数。
  • buf是存放读出的内容的缓冲区。

example: 读取20字节的数据到缓冲区:
      在这里插入图片描述
      上面代码调用read()后,需要检查返回的结果bytes_read,根据bytes_read进行相应的处理。

3.4 文件I/O – write()

调用write()函数可以向一个已打开的可写文件中写入数据。
在这里插入图片描述
详情:

  • write()调用成功返回已写的字节数,失败返回-1,并设置errno。
  • write()的返回值通常与count不同,因此需要循环将全部待写的数据全部写入文件。
  • write()出错的常见原因:磁盘已满或者超过了一个给定进程的文件长度限制。
  • 对于普通文件,写操作从文件的当前位移量处开始,如果在打开文件时,指定了O_APPEND参数,则每次写操作前,将文件位移量设置在文件的当前结尾处,在一次成功的写操作后,该文件的位移量增加实际写的字节数。

3.5 文件I/O_lseek()

调用 lseek()函数可以定位一个已打开的文件。
在这里插入图片描述
详情:
      在这里插入图片描述

  • 每个打开的文件都有一个与其相关的“当前文件位移量”,它是一个非负整数,用以度量从文件开始处计算的字节数。
  • 通常,读/写操作都从当前文件位移量处开始,在读/写调用成功后,使位移量增加所读或者所写的字节数。
  • lseek()调用成功为新的文件位移量,失败返回-1,并设置errno。
  • lseek()只对常规文件有效,对socket、管道、FIFO等进行lseek()操作失败。
  • lseek()仅将当前文件的位移量记录在内核中,它并不引起任何I/O操作。
  • 文件位移量可以大于文件的当前长度,在这种情况下,对该文件的写操作会延长文件,并形成空洞。

3.6文件I/O_fcntl

头文件:#include <unistd.h>
              #include <fctl.h>

原型:int fcntl(int fd, int cmd);
           int fcntl(int fd, int cmd, long arg);
           int fcntl(int fd, int cmd, struct flock *lock);

返回值:
        如果出错,所有命令都返回-1,如果成功则返回某个其他值。
        下面四个命令有特定的返回值:
        (1)F_DUPFD 返回新的文件描述符
        (2)F_GETFD 返回相应标志
        (3)F_GETFL 返回文件状态标记
        (4)F_GETOWN 返回一个正的进程ID或负的进程组

一、fcntl函数有5中功能

  • 复制一个现有的描述符(cm=F_DUPFD)
  • 获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD)
  • 获得/设置文件状态标记(cmd=F_GETFL或F_SETFL)
  • 获得/设置异步I/O所有权((cmd=F_GETOWN或F_SETOWN)
  • 获得/设置记录锁(cmd=F_GETLK或F_SET)

二、调用 fcntl()函数可以设置文件锁
      在这里插入图片描述
三、flock结构体的定义

struct flock {
     hort l_type;
     off_t l_start;
     short l_whence;
     off_t l_len;
     pid_t l_pid;
}
 l_type有三个选项:F_RDLCK : 共享锁,只读用
                 F_WRLCK : 独占锁(写操作锁)
                 F_UNLCK : 解除锁定

 l_start 为相对位移量

 l_whence 必须是以下几个值之一( 在 unistd.h 中定义):
                 SEEK_SET : 文件开始位置
                 SEEK_CUR: 文件当前位置
                 SEEK_END: 文件末尾位置

 l_len 加锁的长度

 l_pid当前文件操作的进程id号

四、修改文件状态标记

  • 可以更改的几个标志是:O_APPEND,O_NONBLOCK,O_SYNC 和 O_ASYNC。
  • 而fcntl的文件状态标志总共有7个:O_RDONLY, O_WRONLY, O_RDWR, O_APPEND, O_NONBLOCK, O_SYNC和O_ASYNC。

示例:见fileappend.c

3.7文件IO_ioctl

ioctl是对设备的I/O通道进行管理的函数,对设备的物理属性进行配置。

“所谓对I/O通道进行管理,就是对设备的一些物理特性进行控制,例如串口的传输波特率、马达的转速等等”。

原型: int ioctl(int handle, int cmd,arg);

其中 :
(1)fd就是用户程序打开设备文件时使用open函数返回的文件描述符;
(2)cmd就是用户程序对设备的控制命令,可调用预定义的宏;
(3)arg指cmd的参数,可有可无

返回值:成功为0,出错为-1

示例:ioctl.c

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值