文章目录
学会用man指令去查open、write、read这些API
要读写文件,需要用到open、read、write函数
不同的函数需要用到不同的头文件,这些很难记住的,所以要善用linux的man手册。
-
man 1 指令
用来查linux里面的shell的,比如ls、cat、pwd、cd等等。 -
man 2 指令
用来查询linux里面的API的,application programme interface -
man 3 指令
用来查询库函数 -
offset
一般普通译为抵消,补偿的意思,但是在计算机系统里面译为偏移量
还记得之前学习结构体的时候呢,有个offsetof宏就是专门来计算结构体内的成员偏移量的,联想记忆! -
incrementor
这个是在看man手册里面记录下来的单词,译为增量器,然后联想到之前记录的auto increment address自动增量地址,大概就是说每执行一次就会自己移位的意思,嗯,继续联想记忆! -
commence
开始
字节操作和块操作与内核文件设计的关系
内存是按照字节为单位操作的,SD卡,nandflash等块设备是按照块区域为单位操作的,所以相比来说内存的操作方式更加好,RAM嘛,random access。
所以内核设计文件操作的时候也是参照RAM来设计的。
也就是说,我们先从文件系统(SD卡这种块设备里面),把需要打开的静态文件取出来,通过open函数丢到内存里面变成动态文件进行操作,最后close之后呢再丢回去块设备里面。
这不就是平时打开文档修改后最后点一下保存的操做lor。
fd文件描述符(file descriptor)
进入到了文件读写这里,会遇到一个新的东东,叫做文件描述符号
文件>file,描述符>descriptor,符号的简写就是fd了,它的作用域在当前的进程,来区分这个程序打开的文件,比如说我开了好几个,那这几个file就用不同的fd来区分。man手册里面好像说fd=-1就是error了,可以查一下。
open函数的具体使用方法
刚刚在part2里面提到了open函数,通过man 2 open或者直接man open也行,就能看到具体的头文件以及使用方法。
OPEN(2) Linux Programmer's Manual OPEN(2)
NAME
open, openat, creat - open and possibly create a file
SYNOPSIS
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
这里截取了部分manshouce,可以看到open函数除了要丢一个const char *类型的指针变量进去之外,还要丢一个int型的flags进去,这里可以打斜杠+要查的东西 /flags 看一下这些flags是啥。
在下面的description里有
The argument flags must include one of the following access modes:
O_RDONLY, O_WRONLY, or O_RDWR. These request opening the file read-
only, write-only, or read/write, respectively.
O_RDWR = open read/write 也就是说open的可读可写。
当然还有很多,例如不同mode下用不同的flags,这些就要有空才去研究了。
打开文件,写/读实例
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(void)
{
//打开文件
int fd = -1;
fd = open("read.txt" ,O_RDWR|O_APPEND); /*设置可读可写,并且文件指针通过O_APPEND移动到了末尾了*/
// 做一个判断,如果写入失败的话fd就不会被改变,只有写入成功才改变。
if (-1 == fd)
{
printf(" file open fail\n");
}
else
printf("file open success , fd = %d \n",fd);
#if 1
//写文件
int w_ret = -1;
char buf2 [] = "abcd\n"; //定义个char类型的缓冲区buf2数组,
//里面存放的字符串用来准备写入文件的。
w_ret = write(fd,buf2,sizeof(buf2));//这里第三个参数直接sizeof(buf2)了,全都写入,也可以自己设置写入多少个字节,反正单位是byte
if (-1 == w_ret)
{
printf("write fail\n");
}
else
{
printf("write success,写入了%d个字节\n",w_ret);
printf("w_ret = %d\n",w_ret);
}
#endif
#if 0
//读取文件,在这个函数里面,如果先执行了write的话,或者打开文件的时候有O_APPEND的话,文件指针被移动到了最后了,所以到时候是read不到东西的。
char buf[100] = {0};//注意这里的buf与上面write的区别,这个buf是用来暂存要读的东西
//也就是说从静态文件里拉出来要读的东西放到这里成为了动态文件。
int ret = -1;
ret = read(fd,buf, 20); //这里第三个参数就设置了要读多少个字节
if (-1 == ret)
{
printf("read file fail");
}
else
{
printf("实际读取了%d字节\n",ret);
printf("文件内容是[%s]\n",buf);
printf("ret = %d\n",ret);
}
#endif
close(fd);
return 0;
}
读写的解析:
-
这里读写的话要注意文件指针,文件指针的位置不一样读写也不一样。
-
.#if #endif是方便调试用的。
-
在open文件函数里面,我不仅设置了O_RDWR,而且还设置了O_APPEND,作用是打开文件的时候顺便把文件指针移动到文件最后一个字符的末尾,这样的话后面我执行write函数的时候就不会覆盖之前的内容。
-
其实很多东西都写在了注释里面,可以好好看。