00. 目录
01. 命令概述
chattr命令用来改变文件属性。这项指令可改变存放在ext2文件系统上的文件或目录属性,这些属性共有以下几种模式:
参数 | 作用 |
---|---|
i | 无法对文件进行修改;若对目录设置了该参数,则仅能修改其中的子文件内容而不能新建或删除文件 |
a | 仅允许补充(追加)内容,无法覆盖/删除内容(Append Only) |
S | 文件内容在变更后立即同步到硬盘(sync) |
s | 彻底从硬盘中删除,不可恢复(用0填充原文件所在硬盘区域) |
A | 不再修改这个文件或目录的最后访问时间(atime) |
b | 不再修改文件或目录的存取时间 |
D | 检查压缩文件中的错误 |
d | 使用dump命令备份时忽略本文件/目录 |
c | 默认将文件或目录进行压缩 |
u | 当删除该文件后依然保留其在硬盘中的数据,方便日后恢复 |
t | 让文件系统支持尾部合并(tail-merging) |
x | 可以直接访问压缩文件中的内容 |
如果想要把某个隐藏功能添加到文件上,则需要在命令后面追加“+参数”,如果想要把某个隐藏功能移出文件,则需要追加“-参数”。
02. 命令格式
用法:chattr [参数] 文件
- 1
03. 常用选项
-R:递归处理,将指令目录下的所有文件及子目录一并处理;
-v<版本编号>:设置文件或目录版本;
-V:显示指令执行过程;
+<属性>:开启文件或目录的该项属性;
-<属性>:关闭文件或目录的该项属性;
=<属性>:指定文件或目录的该项属性。
- 1
- 2
- 3
- 4
- 5
- 6
04. 参考示例
4.1 设置无法对文件进行修改
[root@itcast test]# chattr +i file
[root@itcast test]# echo "神马程序员" >> file
-bash: file: 权限不够
[root@itcast test]#
- 1
- 2
- 3
- 4
4.2 撤销i属性
[root@itcast test]# chattr +i file
[root@itcast test]# echo "C++" >> file
-bash: file: 权限不够
[root@itcast test]# chattr -i file
[root@itcast test]# echo "C++" >> file
[root@itcast test]#
- 1
- 2
- 3
- 4
- 5
- 6
4.3 允许补充(追加)内容,无法覆盖/删除内容
[root@itcast test]# chattr +a file
[root@itcast test]# rm -f file
rm: 无法删除"file": 不允许的操作
[root@itcast test]# echo "hello itcast" >> file
[root@itcast test]# cat file
hello itcast
[root@itcast test]#
- 1
- 2
- 3
- 4
- 5
- 6
- 7
4.4 撤销a属性
[root@itcast test]# chattr -a file
[root@itcast test]# echo > file
[root@itcast test]#
- 1
- 2
- 3
4.5 显示指令执行过程
[root@itcast test]# chattr -V +i file
chattr 1.42.9 (28-Dec-2013)
file的标志被设为 ----i-----------
[root@itcast test]#
- 1
- 2
- 3
- 4
4.6 设置文件或目录版本
[root@itcast test]# chattr -v 1 -V -i file
chattr 1.42.9 (28-Dec-2013)
file的标志被设为 ----------------
Version of file set as 1
chattr: 对设备不适当的 ioctl 操作 while setting version on file
[root@itcast test]#
- 1
- 2
- 3
- 4
- 5
- 6
4.7 删除a属性,增加c属性
[root@itcast test]# chattr -V -v 2 -a +c file
chattr 1.42.9 (28-Dec-2013)
file的标志被设为 --------c-------
chattr: 不支持的操作 while setting flags on file
[root@itcast test]#
- 1
- 2
- 3
- 4
- 5
05. 总结
06. 附录
虚实映射是指系统通过内存管理单元(Memory Management Unit,MMU)将进程空间的虚拟地址(VA)与实际的物理地址(PA)做映射,并指定相应的访问权限、缓存属性等。程序执行时,CPU访问的是虚拟内存,通过MMU找到映射的物理内存,并做相应的代码执行或数据读写操作。MMU的映射由页表(Page Table)来描述,页表保存虚拟地址和物理地址的映射关系以及访问权限等。每个进程在创建的时候都会创建一个页表,页表由一个个页表条目(Page Table Entry, PTE)构成,每个页表条目描述虚拟地址区间与物理地址区间的映射关系。页表数据在内存区域存储位置的开始地址叫做转换表基地址/页表基地址(Translation Table Base,TTB)。MMU中有一块页表缓存,称为快表(Translation Lookaside Buffers, TLB),它缓存最近查找过的VA对应的页表项。做地址转换时,MMU首先在TLB中查找,如果找到对应的页表项,则可直接进行转换,否则就要去物理内存中读取页表项。TLB缓存可以减少访问物理内存的次数,提升查询效率。
本文中所涉及的源码,以OpenHarmony LiteOS-A
内核为例,均可以在开源站点 https://gitee.com/openharmony/kernel_liteos_a 获取。如果涉及开发板,则默认以hispark_taurus
为例。MMU相关的操作函数主要在文件arch/arm/arm/src/los_arch_mmu.c
中定义。
虚实映射其实就是一个建立页表的过程。MMU支持多级页表,LiteOS-A内核采用二级页表描述进程空间。首先介绍下一级页表和二级页表。
1、一级页表L1和二级页表L2
1.1 页表项基础概念
L1页表将全部的4GiB虚拟内存地址空间划分为4096份,每份大小1MiB。每份对应一个32位的页表项,内容是L2页表基地址TTB或某个1MiB大小的物理内存的地址。其中高12位记录页号,用于对页表项定位,也就是4096个页表项的索引;低20位记录页内偏移值,虚实地址页内偏移值相等。使用虚拟地址中的虚拟页号查询页表得到对应的物理页号,然后与虚拟地址中的页内位移组成物理地址。每个L1页表项将1MiB的虚拟内存地址转换为物理地址。如下图所示:
对于用户进程,每个一级页表条目描述符占用4个字节(即32位的L1页表项),可表示1MiB的内存空间的映射关系,即1GiB用户空间(LiteOS-A内核中用户空间占用1GiB)的虚拟内存空间需要1024个L1页表项。系统创建用户进程时,在内存中申请一块4KiB大小(=4byte*1024)的内存块作为一级页表项的存储区域,系统根据当前进程的需要会动态申请内存作为二级页表的存储区域。现在我们就知道,在虚拟内存章节,用户进程虚拟地址空间初始化函数OsCreateUserVmSpace()
申请了4KiB的内存作为页表存储区域的依据了:VADDR_T *ttb = LOS_PhysPagesAllocContiguous(1);
,这段内存的开始地址就是TTB页表基地址。每个用户进程需要申请自己的页表项存储区域,对于内核进程,页表项存储区域是固定的,即UINT8 g_firstPageTable[0x4000]
,大小为16KiB。
L1页表项的低2位用于定义页表项的类型,页表项类型有如下3种:
-
Invalid 无效页表项,虚拟地址没有映射到物理地址,访问会产生缺页异常;
-
Page Table 指向L2页表的页表项;
-
Section Section 页表项对应1MiB大小的内存块,直接使用页表项的最高12位替代虚拟地址的高12位即可得到物理地址。
L2页表把1MiB的地址范围按4KiB的内存页大小继续分成256个小页。内存的高20位记录页号,用于对页表项定位;低12位记录页内偏移值,虚实地址页内偏移值相等。使用虚拟地址中的虚拟页号查询页表得到对应的物理页号,然后与虚拟地址中的页内位移组成物理地址。每个L2页表项将4KiB的虚拟内存地址转换为物理地址。如下图所示:
L2页表项的低2位用于识别页表项的类型,类型有如下4种:
- Invalid 无效页表项,虚拟地址没有映射到物理地址,访问会产生缺页异常;
- Large Page 大页表项,支持64KiB大页,暂不支持;
- Small Page 小页表项,支持4KiB小页的二级页表映射;
- Small Page XN 小页表项扩展。
在文件arch/arm/arm/include/los_mmu_descriptor_v6.h
中定义了页表项类型,代码如下:
/* L1 descriptor type */
#define MMU_DESCRIPTOR_L1_TYPE_INVALID (0x0 << 0)
#define MMU_DESCRIPTOR_L1_TYPE_PAGE_TABLE (0x1 << 0)
#define MMU_DESCRIPTOR_L1_TYPE_SECTION (0x2 << 0)
#define MMU_DESCRIPTOR_L1_TYPE_MASK (0x3 << 0)
/* L2 descriptor type */
#define MMU_DESCRIPTOR_L2_TYPE_INVALID (0x0 << 0)
#define MMU_DESCRIPTOR_L2_TYPE_LARGE_PAGE (0x1 << 0)
#define MMU_DESCRIPTOR_L2_TYPE_SMALL_PAGE (0x2 << 0)
#define MMU_DESCRIPTOR_L2_TYPE_SMALL_PAGE_XN (0x3 << 0)
#define MMU_DESCRIPTOR_L2_TYPE_MASK (0x3 << 0)
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
评论记录:
回复评论: