***嵌入式产品的研发过程:
①系统移植工作:将Linux系统在硬件上跑起来;
②基于Linux开发应用程序,实现具体的嵌入式功能。
应用编程:通过调用Linux内部的API接口来实现需要完成的任务。
操作系统的API:实质是函数,是由Linux系统提供支持的,由应用层程序进行使用。 应用程序需要调用API来调用系统的各种功能。
常用的文件IO接口API: open close write read lseek
***块设备例如NANDFLAH和SD只能进行一块一块的读写操作,更改起来很不灵活,而内存可以按照字节为单位进行读写操作,还可以随机操作,所以在打开或者修改一个文件时内存的特殊位置就会赋值一份文件,在操作完成进行保存之后原块设备的文件就会和这份文件保持同步,在此之前源文件不会发生变化。
***文件描述符:实质是一个数字,用来区分一个程序打开的多个文件,而这个数字在进程之中表示一个特殊的含义。 具体的含义:在open打开一个文件时,操作系统会在内存中构建一些数据结构来表示动态文件,然后返回给应用程序一个数字作为文件描述符,然后这个数字就和我们内存之中维护的这个动态文件的这些数据结构绑定了,之后应用程序操作动态文件时,只需要用这个文件描述符进行区分。
作用域:只针对当前进程。
***open函数的flag:
1.O_TRUNC:删除原文件的内容,使得目标文件为空。
2.O_APPEND:若原文件的有内容,则继续写入时的写入内容会紧跟着原文件的内容。
3.O_CREAT:若文件不存在则新建一个文件,然后打开;若文件存在则重现创建这个文件然后将其原来的内容覆盖。
4.O_EXCL:这个指令和O_CREAT配合使用可以避免将已有的文件覆盖,当想新创建的文件存在时就会报错。
5.O_NONBLOCK:阻塞(函数的返回值与函数是否完成有关,只有当函数完整的执行完才会有返回值)与非阻塞(无论函数是否完成,都会有返回值)。
6.O_SYNC:一般的应用层的写操作只是将目的数据写入内核缓冲区(数据块、指针块、元数据)就返回至应用层,而结束任务,但是不能保证内核缓冲区的数据是否真正写入了磁盘(硬件)中,则通过O_SYNC,可以阻塞等待底层完全写入才返回到应用层。
避免了缓冲区与相关磁盘文件内容长期处于不一致状态。 同时系统在每个缓冲区中将数据向磁盘传递时会把程序阻塞起来,增加了程序的运行时间。
***当程序内某一步操作失败时,不应将程序继续运行下去,则使用退出程序命令;
1.return:是函数的退出,而不是进程的退出,将函数的信息返回给调用函数使用。
2.exit _exit _Exit:
用于结束进程,正式终止进程的命令,进程所有的文件描述符都被关闭。
***文件IO与标准IO:
1.文件IO:open close write read等API函数构成的一套用来读写的体系,但是效率低。
2.标准IO:应用层的C语言库函数提供了一些用作文件读写的函数列表,由一系列的c库函数(fopen fclose fwrite,fread)构成。
其实也是由文件IO(的API)进行封装得到的,内部调用了文件IO。 标准IO(c库函数)可以在不同的系统之间使用,具有可移植性,但是文件IO(API)在不同的系统间不能同时使用。
封装之后在应用层添加了一个缓冲机构(buff),这样我们通过write写入的数据就不会直接进入内核的缓冲区,而是先进入应用层自己维护的缓冲区(buff),然后封装内部会判断一个效益最高的的cout(写入字节数)在最佳的时间完成数据从应用层写入内核的缓冲区,这就很好的避免了每一次写入数据就直接进入内核的缓冲区而造成的效率低下和浪费。
***Linux管理文件的方式:
1.磁盘中未被打开的静态文件和inode(i节点):而在硬盘内除了储存文件的区域外还有储存硬盘内容管理表的区域,操作系统在读取文件时先得到文件名,然后查询硬盘内容管理表,表内以文件为单位记录了各种文件的各种信息,每一个文件有一个信息列表inode(实质是一个结构体,内部记录了文件的各种详细信息,文件名、扇区号、块号等)。每个inode会有一个的数字编号,对应一个结构体,通过循环的方式可以通过数字编号访问到具体的文件。
2.内存中被打开的文件和vnode(v节点):在程序中打开的文件就属于进程,每一个进程都有一个数据结构来记录这个进程的所有信息(进程信息表),而表中会有一个指针指向一个文件管理表,其中记录了当前进程打开的所有文件的相关信息,文件描述符fd(open函数打开一个文件夹时生成)用来索引各个打开的文件,最终找到一个已经被打开的文件管理结构体vnode。
***lseek函数:
1.文件指针:文件管理表这个结构体里面的一个指针。这个指针不能被直接访问,只能通过lseek函数来访问这个指针。 (动态文件在内存中是文件流的形式)
2.write和read函数自带移动函数指针的功能,当我们writen个字节后文件指针就会自动的后2n位,同时当readn字节后文件指针自定后移n字节。(现象:在一个空的文件内写入n字节的字符,写完read发现读出的字符为空————>write之后文件指针自动移动到n字节的位置,这时进行read时从该文件指针处开始读,即为空)
3.lseek计算文件的长度:
int main(int argc,char *argv[])
{
int fd=-1;
int ret=-1;
if(argc!=2)
printf("usage :%s filename",argv[0]);
_exit(-1);
}
fd=open(argv[1],O_RDWR)
if(-1==fd)
printf("open error");
_exit(-1);
else
printf("open succese,fd=%d",fd);
ret=lseek(fd,0,SEEK_END);
printf("文件的长度是%s字节",ret);
close(fd);
return 0;
注:argc是命令行总的参数个数,argv[]为保存命令行参数的字符串指针,其中第0个参数是程序的全名(a.out),以后的参数为命令行后面跟的用户输入的参数(a.out+要输入的参数),argv参数是字符串指针数组,其各元素值为命令行中各字符串(参数均按字符串处理)的首地址。 指针数组的长度即为参数个数argc。数组元素初值由系统自动赋予。
4.lseek函数构建空洞文件:打开文件后用lseek往后跳一段,然后进行write。用于多线程处理。
***多次打开一个文件和O_APPEND:
1.一个进程内同时对一个文件进行读写操作时,后一次写入的内容会覆盖前一次的内容(覆盖的情况看两次写入内容的字节数);
2.O_APPEND:后一次对于文件的写如会在前一次的之后进行接续写入,不会导致覆盖。
***文件共享的实现:
1.文件共享:同一个文件(同一个inode,同一个pathname)被多个独立的读写个体(对应读个不同的文件描述符fd)去同时操作。————>多线程同时操作同一个文件
2.实现方式:核心:多个文件描述符指向同一个文件。
①同一个进程中多次使用open打开同一个文件;
②不同的进程中open打开同一个文件(这时由于两个fd处于不同的进程,则两个fd相同性不确定);
③Linux提供dup(新复制的描述符的值内核取现在最小的描述符的值进行复制)和dup2(可以规定新复制描述符的值)两个API让进程复制文件描述符。
***文件属性的获取:
1.stat:内核提供给用户以查找文件属性的API,函数内部有一个结构体,输入一个文件之后内核对文件的信息进行读出,将结构体赋值,最后返回输出赋值过得结构变量,输出文件的各种属性;
2.fstat:输入文件的描述符,主要针对已经打开的文件。
注:stat主要是从磁盘读取出目标文件,fstat从内存读取动态文件。
3.lstat:对于符号链接文件,查找符号链接文件本身的属性;
fstat和stat查找符号链接文件所指向的源文件的属性。
***更改文件属性的API:chmod和fchmod
***更改文件属主的API:chown fchown lchown
***目录文件的打开与读:opendir readdir