嵌入式Linux学习笔记之第二阶段---文件I/O
1、文件IO的四个函数
一些术语:
不带缓冲的I/O:
每个read和write都调用内核中的一个系统调用。
文件描述符:
一个非负整数,对内核而言,所以打开的文件都通过文件描述符引用。
①打开或创建一个文件 open(char *path, flag, mode) 在fcntl.h文件中声明
int openat(int fd, const char *path, int flag......)
open 与 openat的区别:①路径,path指定是绝对路径时open==openat;openat可以让线程使用相对路径名打开目录中的文件,而不再只能打开当前工作目录;
②openat解决TOCTTOU问题,两个函数调用之间文件可能改变了,会造成第一个调用的结果不再有效。
char*:包含有文件名和路径
flag:打开文件的方式 O_RDONLY O_WRONLY O_RDWR O_CREAT O_EXCL(测试文件是否存在) O_TRUNC(打开已存在文件时会清空内容) O_APPEND(追加方式打开文件)
mode:创建文件的权限 真正的权限:Mode&(~umask)
返回值:
成功:文件描述符,非负正整数,文件的ID号(ls -lai可以查询)
出错:-1
②write(int fd, void *buf, size_t count)
fd:写到哪个文件
*buf:要写的内容
count:写多少字节
返回值:实际写的字节数
③read(int fd, void *buf, size_t count) --和write差不多
④close(int fd)
2、因为文件存在读写位置指针,所以需要lseek调整读写位置指针:
lseek(int fd, off_t offset, int whence),
该函数的头文件:sys/types.h unistd.h
offset:偏移量,单位是字节的数量,可正可负
whence:当前位置的基点,有三个标志
SEEK_SET:当前位置为文件的开头,新位置为偏移量的大小
SEEK_CUR:当前位置为文件指针的位置,新位置为当前位置加偏移量
SSK_END:当前位置为文件的结尾,新位置为当前位置加偏移量
返回值:成功:文件当前的位置(新的文件偏移量) 出错:-1
允许文件构成一个空洞。(lseek和write相互作用),空洞不占用存储区。
可以 od -c +文件 以字符方式打印文件内容
2、文件共享
不同进程间共享打开文件
内核为所有打开的文件维持一张文件表(同一个文件可以被打开多次,所以同一个文件可以在文件表中占有多项)。每个文件表项包含:
(a)、文件状态标志(读、写、添写、同步和非阻塞等)
(b)、当前文件偏移量(不同的进程当前的文件偏移量是不同的,你想两个不同的进程对同一个文件的操作可能都不一样,那当然文件偏移量是不一样的)
(c)、指向该文件的V节点表项的指针。
3、原子操作
比如open函数的O_CREAT和O_EXCL。
函数pread和pwrite(先调用lseek后调用read或者write)
追加数据到一个文件的O_APPEND
4、函数dup和dup2:复制一个现有的文件描述符
#include <unistd.h>
int dup(int fd)
int dup2(int fd, int fd2)
5、函数sync、fsync和fdatasync:向文件写入数据时,内核先把数据复制到缓冲区中,然后排入队列,晚些再写入磁盘。
#include <unistd.h>
int fsync(int fd) 对指定的文件起作用,等待写磁盘操作结束才返回
int fdatasync(int fd)
int sync(void) 把快缓冲区写入队列,不等待实际写磁盘操作结束,并立即返回
6、函数fcntl:可以改变已经打开文件的属性
#include <fcntl.h>
int fcntl(int fd, int cmd, ...)
https://www.cnblogs.com/xuyh/p/3273082.html
7、函数ioctl
#include <unistd.h>
#include <sys/ioctl.h>
int ioctl(int fd, int request, ...)
I/O操作的杂物箱