linux常用文件操作IO
- open()
- write()
- read()
1. open()系统调用
open()调用了sys_open()
/**
* @brief open()函数原型之一
* @param[*pathname] 指向文件名字符串
* @param[flags] 系统调用的标志
* @param[mode] 请求传输的数据长度
* @retval 打开成功返回文件描述符,失败返回-1;
*/
int fd = open(const char *pathname,int flags,mode_t mode)
1.1 flags参数定义如下:
- O_RDONLY 只读
- O_WRONLY 只写
- O_RDWR 可读写
- O_CREAT 如果文件不存在,就创建它
- O_EXCL 对于O_CREAT标志,如果文件已经存在,则失败
- O_NOCTTY 从不把文件看作控制终端
- O_TRUNC 截断文件(删除所有现有内容)
- O_APPEND 总是在文件末尾写
- O_NONBLOCK 没有系统调用在文件上阻塞
- O_NDELAY 与O_NONBLOCK功能相同(但会导致read的返回值不同)
- O_SYNC 同步写(阻塞,直到物理写终止)
- FASYNC 通过信号发出I/O事件通告
- O_DIRECT 直接I/O传输(无内核缓冲)
- O_LARGEFILE 大型文件(长度大于2GB)
- O_DIRECTORY 如果文件不是一个目录,则失败
- O_NOFOLOW 不解释路径名中尾部的符号链接
- O_NOATIME 不更新索引节点的上次访问时间
1.2 open()完成如下工作:
- 检查设备特定的错误(诸如设备未就绪或类似的硬件问题);
- 如果设备是首次打开,则对其进行初始化;
- 如有必要,更新f_op指针;
- 分配并填写至于filp->private_data里的数据结构;
2. write()系统调用
/**
* @brief write函数原型之一
* @param[*filp] 文件指针
* @param[*buff] 指向用户空间缓冲区
* @param[count] 请求传输的数据长度
* @param[*offp] 指向“long offset type(长偏移量类型)”对象指针,指明用户在文件中进行存取操作的位置。
* @retval signed size type(有符号的尺寸类型)
*/
ssize_t write(struct file *filp, const char _ _user *buff, size_t count, loff_t *offp);
参考《LINUX设备驱动程序》-第六章:
如果open()文件是没指定O_NONBLOCK或O_NDELAY则默认是阻塞的。进程会进入休眠状态。
如果open()文件指定O_NONBLOCK或O_NDELAY,则write()操作文件不会阻塞,当文件无数据时直接返回-EAGAIN。
2.1 write()返回值
- 如果返回值等于count,则完成了所请求数目的字节传送;
- 如果返回值是正的,但小于count,则只传输了部分数据。程序很可能再次试图写入余下的数据。
- 如果为0,意味着什么也没写入。这个结果不是错误,而且也没有理由返回一个错误码。标准库会重复调用write。在介绍阻塞式write内容中有详细说明。
- 负值意味发生了错误,有效的错误码定义在linux/errno.h中;
- 如果write的缓冲区没有空间,则有阻塞和非阻塞两种情况(由open()时的参数决定)。非阻塞时返回-EAGAIN。
3. read()系统调用
/**
* @brief read函数原型之一
* @param[*filp] 文件指针
* @param[*buff] 指向用户空间缓冲区
* @param[count] 请求传输的数据长度
* @param[*offp] 指向“long offset type(长偏移量类型)”对象指针,指明用户在文件中进行存取操作的位置。
* @retval signed size type(有符号的尺寸类型)
*/
ssize_t read(struct file *filp, char _ _user *buff, size_t count, loff_t *offp);
参考《LINUX设备驱动程序》-第六章:
如果open()文件是没指定O_NONBLOCK或O_NDELAY则默认是阻塞的。进程会进入休眠状态。
如果open()文件指定O_NONBLOCK或O_NDELAY,则read()操作文件不会阻塞,当文件无数据时直接返回-EAGAIN。
3.1 read()的返回值
- 返回值等于count参数,说明所请求的字节数传输成功完成。最理想的情况。
- 返回值是正,但比count小,说明只有部分数据成功传送。该情况因设备不同可能有许多原因。大部分情况下,程序会重新读数据。
例如,如果用fread函数读数据,这个库函数就会不断的调用系统调用,直至所请求的数据传输完毕为止。 - 返回值为0,则表示已经到达文件尾。
- 负值意味着发生了错误,该值指明了发生的具体错误,错误码在linux/errno.h中定义。如:-EINTR(系统调用被中断),-EFAULT(无效地址)。
- 假如当前文件没有数据可读,则有阻塞和非阻塞两种情况(由open()时的参数决定)。非阻塞时返回-EAGAIN。
参考
- 《LINUX设备驱动程序》
- 《深入理解LINUX内核》