Linux应用基础
1. 基础概念
1.1 系统调用
系统调用实际上是Linux内核为上层应用程序提供的API接口,方便应用程序进行调用,类似于SVC。
1.2 库函数
库函数是应用层里边的东西,在系统调用的上层,通常以动态库文件(.so)形式提供。与系统调用区别是:库函数是属于应用层,而系统调用是内核提供给应用层的编程接口,属于系统内核的一部分; 库函数运行在用户空间,调用系统调用会由用户空间(用户态)陷入到内核空间(内核态); 库函数通常是有缓存的,而系统调用是无缓存的,所以在性能、效率上,库函数通常要优于系统调 用; 可移植性:库函数相比于系统调用具有更好的可移植性。
2. I/O基础
open/write/read/close等,主要说一下lseek。lseek函数用于设置文件读写偏移量,其他详细信息看手册。
3. Linux系统下的文件管理
3.1 静态文件与inode
静态文件:电脑硬盘、移动硬盘、U 盘等外部存储设 备,文件存放在磁盘文件系统中,并且以一种固定的形式进行存放,我们把他们称为静态文件。
inode:实际上是一个结构体,记录了文件的不同信息;并且一个inode对应一个文件,多个inode组成一个inode表。可通过命令“ls -i”查看inode号。
3.2 磁盘分区
磁盘分为数据区和inode区,数据区用于存储文件中的数据;inode区用于存放inode表。
快速格式化:仅删除了u盘的inode区,但是没有删除数据区,因此可以找回数据。
3.3 文件状态
文件打开过程:首先系统根据文件名找对文件对应的inode编号;然后通过该编号去inode表里边寻找对应的inode结构体;最后根据结构体里边记录的信息,确定文件的数据所在的扇区,最后读出数据。
文件打开状态:调用open函数去打开文件的时候,内核会申请一段内存(一段缓冲区),并且将静态文件的数 据内容从磁盘这些存储设备中读取到内存中进行管理、缓存(也把内存中的这份文件数据叫做动态文件、内 核缓冲区)。打开文件后,以后对这个文件的读写操作,都是针对内存中这一份动态文件进行相关的操作, 而并不是针对磁盘中存放的静态文件。 当我们对动态文件进行读写操作后,此时内存中的动态文件和磁盘设备中的静态文件就不同步了,数据 的同步工作由内核完成,内核会在之后将内存这份动态文件更新(同步)到磁盘设备中。
进程控制块(PCB):是一个结构体用于记录进程的状态信息、运行特征等。
文件描述符表、文件表及inode之间的关系:如下图所示:
PCB中有一个指针指向文件描述符表,该表中的每个元素对应一个文件表;文件表中存在inode指针指向inode用于读取文件数据。
3.4 perror函数
该函数用于查看详细的报错信息。比如当调用open函数打开某文件时,如果失败的话回返回-1,但是并不知道错误的详细原因;因此采用这个函数即可了解,其用法如下所示:
如果失败,会打印 “open error:加具体原因” 。
3.5 exit、_exit、_Exit函数
这三个函数都用于结束进程,类似于return;。调用_exit()函数会 清除其使用的内存空间,并销毁其在内核中的各种数据结构,关闭进程的所有文件描述符,并结束进程、将 控制权交给操作系统。_exit()和_Exit()两者等价。
exit()函数_exit()函数都是用来终止进程的,exit()是一个标准C库函数,而_exit()和_Exit()是系统调用。 执行exit()会执行一些清理工作,最后调用_exit()函数。一般用exit()。
用法如下:
3.6 空洞文件
比如说现在一个文件a大小是4K;然后我调用了lseek函数将读写位置偏印到文件头部6k个字节处写数据,那么此时0-4k处有数据,6k处之后有数据,但是4k-6k处没有数据。该区域就成为文件空洞区域,该文件也被称为空洞文件。
空洞文件逻辑大小和物理大小:ls命令查看到空洞文件的大小是8K,使用ls命令查看到的大小是文件的逻辑大小,自然是包括了 空洞部分大小和真实数据部分大小;当使用du命令查看空洞文件时,其大小显示为4K,du命令查看到的 大小是文件实际占用存储块的大小。
3.7 O_APPEND和O_TRUNC标志
O_APPEND标志是,调用open函数打开文件, 当每次使用write()函数对文件进行写操作时,都会自动把文件当前位置偏移量移动到文件末尾,从文件末 尾开始写入数据,也就是意味着每次写入数据都是从文件末尾开始。用法为fd=open("./src_file",O_APPEND);
O_TRUNC标志是:如果使用了这个标志,调用open函数打开文件的时候会将文件 原本的内容全部丢弃,文件大小变为0。
3.8 多次打开同一文件
一个进程内多次open打开同一个文件,那么会得到多个不同的文件描述符fd,同理在关闭文件的 时候也需要调用close依次关闭各个文件描述符。
一个进程内多次open打开同一个文件,在内存中并不会存在多份动态文件。此处动态文件指的是调用open函数时会将磁盘上的数据读到一个缓存区,这个区域的文件数据就叫动态文件。
同一个文件被多次打开,会得到多个不同的文件描述符,也就意味着会有多个不同的文件表,而文件读 写偏移量信息就记录在文件表数据结构中,所以从这里可以推测不同的文件描述符所对应的读写偏移量是 相互独立的,并没有关联在一起,并且文件表中i-node指针指向的都是同一个inode。