每天需要给自己 定出明确的目标,否则将很难完成任务,自己需要逼自己一把。
人需要目标,就跟船需要灯塔一样,灯塔不会照亮你所有的路,但是起码证明,你所到达的地方是光明的。曾经感觉自己已经是一条破船了,但是现在看来可能自认为是破船,但是修补和装饰下还是一艘新的船,依旧能够从现在 启航,迎接人生未来的挑战。 - 2021.11.25
- 正文:
Linux中的一个基本哲学是一切皆文件,包括普通文件,字符设备,块设备,套接字都是文件,对于这些文件的基本 操作,就是文件打开,文件读写,文件关闭。
普通文件, 设备文件指代系统中的 一个具体设备,管道文件 FIFO文件,是指特殊文件,用于进程间的通信,套接字文件(socket 文件)用于网络通信方面。 - 文件I/O的常用操作:打开:open 关闭:close 读:read 写:write,因为这些是以最基本的系统服务形式提供的,所以称它们为基本I/O函数。
- 文件描述符:fd 进程中用来表示某个文件的数,也叫句柄。 类似于排队拿号中的编号,通过叫号来通知具体的人。对于系统 而言,进程操作的每一个文件,都是通过fd来进行,先调用open或者create来取得该文件的描述符fd,在将fd传给read和write等 文件操作函数。通常情况下,文件描述符0 1 2在 进程启动时已经被占用,分别为 0 标准输入,1 标准输出和2 标准错误。
- fcntl.h 定义了open create等函数, unistd.h定义了read write close lseek等函数
- open函数 打开文件,需要指定打开文件标志,即只读 只写 读写等等
O_RDONLY O_WRONLY O_RDWR O_CREAT O_EXCL O_NOCTTY()O_TRUNC O_APPEND O_NONBLOCK O_SYNC O_NOFOLLOW O_DIRECTORY
mode:创建文件时才会起作用,否则忽略,含义中分为所属 用户权限、组用户权限以及其他 用户权限,所属用户第一位 组用户第二位 其他用户第三位 相关的值则为执行1 写2 读4
creat()的参数 pathname 和 mode 的含义,与 open()的同名参数含义相同,某些条件下调
用 creat()的效果与 open()是相同的,两者的差别:create创建文件,如果文件不存在直接创建文件,如果文件存在则现将文件内容情况,长度截为0,在返回对应的文件描述符;对于open,如果设置了O_CREAT,则 是如果文件不存在,则创建文件,且返回对应的文件描述符,如果文件存在,则直接打开并且返回文件描述符。
-
close:需要的参数仅为文件描述符fd
注:当一个文件被打开多次时,比如被多个进程同时打开,或在同一个进程中被打开多次,
每打开一次,该文件内部的引用计数就增加 1,对该文件每调用一次 close(),文件引用计数
则减 1,当计数值减到 0 时,内核才关闭该文件。当进程终止时,内核会回收进程资源,也
按上述规则关闭进程打开的全部文件。 -
read 从打开的文件读取数据,可以调用read函数实现,
ssize_t read(int fd, void *buf, size_t count);
操作成功,返回实际读取的字节数,如果已到达文件结尾,返回 0,否则返回-1 表示出
错,同时设置全局变量 errno 报告具体错误的原因。所以实际读取的字节数可以小于请求的字节数count。
- write
ssize_t write(int fd, const void *buf, size_t count);
参数 fd 是所打开文件的描述符,buf 是数据缓冲区,存放着准备写入文件的数据,count
是请求写入的字节数。实际写入的字节数可以小于请求写的字节数。
- fsync:
write()函数一旦返回,表明所写的数据已提交到系统内部缓存了,但此时数据并不一定
已经被写入磁盘等持久存储设备中。要确保已修改过的数据全部写入持久存储设备中,正确
的做法是调用 fsync 函数进行文件数据同步,强制把已修改过的文件数据写入持久存储设备
中。
嵌入式系统通常采用闪存(Flash Memory)作系统盘,write()返回后也应该用 fsync()及
时把修改过的文件数据写入闪存中。如果不调用 fsync(),在 write()返回后马上就复位或重新
上电,则所作的修改就可能没有被更新,从而造成文件数据丢失。
int fsync(int fd);
fsync()针对打开的文件,参数 fd 是已打开文件的描述符,fsync()调用在将该文件已修改
数据全部写入磁盘后才会返回。操作成功返回 0,否则返回-1,同时设置全局变量 errno 报
告具体错误的原因。
- iseek:普通磁盘文件一般都能随机读写,这类文件可通过 lseek()函数改变文件读写位置;而顺序读写文件只能从头到尾,按顺序进行读写,如管道(pipe)文件、套接字(socket)文件或 FIFO,都是按顺序读写的,不支持 lseek 操作,不能像普通磁盘文件那样可以随机读写。设备文件是否支持lseek 操作,则与具体的设备有关。
off_t lseek(int fd, off_t offset, int whence);
lseek()的参数 fd 是所打开文件的描述符,offset 是目标位置,其偏移的参照点由第 3 个
参数 whence 决定,whence 有效值是 SEEK_SET、SEEK_CUR、SEEK_END,
- ioctl:文件的I/O操作 中还有很多不好归到read/write中的,只好放到这个函数中,很多设备文件也可以通过ioctl函数提供设备特意的操作,比如修改设备寄存器 的值。ioctl()的 cmd 操作命令是文件专有的,不同的文件,cmd 往往是不同的,没有共用性,