文件系统设计中,使用了denty,inode,fs,file等关键性的数据结构其中

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一、Linux的VFS文件系统设计中,使用了denty,inode,fs,file等关键性的数据结构.其中dentry 和inode用来记载相关的单个文件的管理信息,例如文件名字,创建者,创建日期,文件大小,文件物理存储地址等等.
那么,为什么要用两个数据结构,而不是合并成一个数据结构来记载这些信息? (问题1),
file数据结构记载了某个进程使用文件的现场情况,例如文件访问指针等,当用户进程打开文件准备操作时,内核必然要为这个进程创建file数据结构,然后才能依赖此结构分数次访问文件.那么有没有不需要打开操作就可以使用的文件?如果没有这样的经历,那么设想一下,内核有没有必要提供一些默认的不需要用户打开就可以操作的文件,为什么?(问题2),
Linux的文件系统中有三种类型文件: 磁盘文件,设备文件,特殊文件.请从文件的数据和管理信这两方面来分析一下这三类文件的区别(问题3),
文件的权限与系统的数据安全息息相关,请说明Linux操作系统管理文件权限的方法(问题4)
第1小问答案:用一个数据结构的话,在存储数据,会造成数据的冗余性,使得存储量过大,浪费不必要的空间。

第2小问答案:有没有不需要打开操作就可以使用的文件:答,有这样的文件。

内核有没有必要提供一些默认的不需要用户打开就可以操作的文件:答:有
必要。

因为提供这样的文件可以较为方便的操作一些操作系统级别的问题。

第3小问答案:磁盘文件:来自与日常数据,比如各种应用的录入等;
设备文件:来自各硬件的基本信息,比如各种硬件的驱动等;
特殊文件:可能是来自用户的录入信息文件,或者文本文件等,可以归属于磁盘文件。

第4小问答案:Linux中,每一个文件都具有特定的属性。

主要包括文件类型和文件权限两个方面。

可以分为5种不同的类型:普通文件、目录文件、链接文件、设备文件和管道文件。

所谓的文件权限,是指对文件的访问权限,包括对文件的读、写、删除、执行。

Linux 是一个多用户操作系统,它允许多个用户同时登录和工作。

因此Linux 将一个文件或目录与一个用户或组联系起来。

访问控制列表(ACL:Access Control List)为计算机提供更好的访问控制,它的作用是限制包括root用户在内的所有用户对文件、资源或者套接字的访问。

下面就来说说设置方法。

步骤1 检查系统核心
首先检查你的Linux系统的核心是否有支持ACL的功能。

因为Linux系统并不是每一个版本的核心都有支持ACL的功能,而最简单的方法就是检查系统目前的核心能否支持:
[root@mail /]# cat /boot/config-kernel-version grep -i ext3
CONFIG_EXT3_FS=m
CONFIG_EXT3_IDEX=y
CONFIG_EXT3_FS_XA TTR_SHARING=y
CONFIG_EXT3_FS_XA TTR_USER=y
CONFIG_EXT3_FS_XA TTR_TRUSTED=y
CONFIG_EXT3_FS_ACL=y
此时如果能看到上面的几项则表示已经编译到核心中,ext3文件系统已支持ACL功能,这些功能在编译核心选项中都可以找到。

如果编译时找不到,可以到ACL的官方网站来安装Kernel(acl.bestbits.at/)。

步骤2 挂载分区
你可以用下列的方式挂载分区并启用ACL:
#mount -t ext3 -o acl /dev/sda1 /fs1
你也可以直接写在/etc/fstab文件中,这样就可以在开机后支持ACL功能:
#vi /etc/fstab
步骤3 设置ACL权限
ACL常常针对个别用户来进行设置,下面是多个不同的例子:
例如需要创建test1、test2、test3三个用户,可以先用root身份登录系统,然后执行以下命令分别创建三个用户名和密码:
[root@mail root]#adduser test1
[root@mail root]#adduser test2
[root@mail root]#adduser test3
[root@mail root]#passwd test1
[root@mail root]#passwd test2
[root@mail root]#passwd test3
然后mount一个ext3文件到目录/fs1:
[root@mail root]#mount -t ext3 -o acl /dev/sda1 /fs1
再将test1 建立的文件设置读写的权限给test2 :
[root@mail root]#chmod -R 777 /fs1
让所有的用户都能增加文件到目录的权限:
先用test1登录系统,执行命令:
[test1@mail test1]# cd /fs1
[test1@mail fs1]# echo "Create by test1" > test1.txt
[test1@mail fs1]# chmod go-r test1.txt
[test1@mail fs1]# ll test1.txt
-rw------- 1 test1 test1 17 Jul 14 22:11 test1.txt
而如下操作则可以让除了test1有读写的权限外其他人没有读写test1.txt的权限(root除外),先用test2 登录系统后执行以下命令:
[test2@mail test2]# cd /fs1
[test2@mail fs1]# cat test1.txt
cat : test1.txt Permission denied
接着用test1登录系统,执行如下命令:
[test1@mail fs1]# setfacl -m u:test2:rw test1.txt
这样就修改权限允许test2 有这个文件的读写权限。

再看一下它的文件属性的变化:
[test1@mail fs1]# ll
-rw-rw-r--+ 1 test1 test1 10 Feb 16 13:52 test1.txt
会看到后面多了一个“+”,表示这个文件使用ACL的属性设置,再用命令getfacl来看ACL的文件属性设置:
[test1@mail fs1]# getfacl test1.txt
# file: test1.txt
# owner: test1
# group: test1
user::rw-
user:test2:rw-
group::rw-
mask::rw-
other::r--
可以看到test2 有权限读写这个文件。

我们再用test2登录系统执行以下命令,看看发生了什么?[test2@mail test2]# cd /fs1
[test2@mail fs1]# cat test1.txt
Create by test1
原来test2可以读取test1.txt文件了。

[test2@mail fs1]# echo "Modify by test2" >> test1.txt
[test2@mail fs1]# cat test1.txt
Create by test1
Modify by test2
现在test2也可以修改test1.txt文件了。

接着用test3 登录系统:
[test3@mail test3]# cd /fs1
[test3@mail fs1]# cat test1.txt
cat : test1.txt Permission denied
嘿嘿,除了test1、test2外没有其他用户有读写test1.txt的权限(root 除外)。

看着虽然有点晕,其实命令就是这么一两条,主要是把各种情况给大家讲清楚,这样,大家在使用Linux中才会发现,比起脆弱的Windows的权限防护,Linux实在是做得相当不错!
二、要求写出编译和安装2.6.10内核的步骤,以及编译Linux内核的体会...
假设以root用户登录系统,并且已经下载了编译2.6.10内核所需的工具,它们是:
module-init-tools-3.1.tar.bz2,
lvm2-2.00.25-1.01.i386.rpm,
device-mapper-1.00.19-2.i386.rpm,
mkinitrd-4.1.18.1-1.i386rpm,
Linux-2.6.10.tar.gz
1、安装module-init-tools-3.1.tar.bz2.
tar -zxvf module-init-tools-3.1.tar.bz2
cd module-init-tools-3.0
./configure --prefix=/sbin
make
make install
./generate-modprobe.conf /etc/modprobe.conf
2、解压缩内核源代码.把下载的源代码包放到目录/usr/src下,然后
cd /usr/src
tar xvfj Linux-2.6.10.tar.gz
cd Linux-2.6.10
3、#tar xvf device-mapper-1.00.19-2.i386.rpm
Make
Make install
编译Linux内核的体会:俗话说:"功夫不负有心人",通过编译Linux内核时才能真正体会到.曾经也失败过无数次,放弃过一段时间编译.最后通过自己不断的实践和在网上收集这方面资料,终于在编译成功了.
题目三:请简述Linux系统启动的一般过程
Linux内核的主要组成部分有哪些
请简要说明Linux的内存管理方案,分析其特点,并用图示说明这种方案中逻辑地址转换为物理地址的过程
1、Linux系统启动的一般过程:当用户打开PC的电源,BIOS开机自检,按BIOS中设置的启动设备(通常是硬盘)启动,接着启动设备上安装的引导程序lilo或grub开始引导Linux,Linux首先进行内核的引导,接下来执行init程序,init程序调用了rc.sysinit和rc等程序,rc.sysinit和rc当完成系统初始化和运行服务的任务后,返回init;init启动了mingetty后,打开了终端供用户登录系统,用户登录成功后进入了Shell,这样就完成了从开机到登录的整个启动过程。

2、Linux内核的主要组成部分有哪些
Linux内核主要由五个子系统组成:进程调度,内存管理,虚拟文件系统,网络接口,进程间通信。

3.Linux的内存管理方案,分析其特点,并用图示说明这种方案中逻辑地址转换为物理地址的过程
一、逻辑地址转线性地址
机器语言指令中出现的内存地址,都是逻辑地址,需要转换成线性地址,再经过MMU(CPU中的内存管理单元)转换成物理地址才能够被访问到。

我们写个最简单的hello world程序,用gccs编译,再反编译后会看到以下指令:
mov 0x80495b0, %eax
这里的内存地址0x80495b0就是一个逻辑地址,必须加上隐含的DS数据段的基地址,才能构成线性地址。

也就是说0x80495b0是当前任务的DS数据段内的偏移。

在x86保护模式下,段的信息(段基线性地址、长度、权限等)即段描述符占8个字节,段信息无法直接存放在段寄存器中(段寄存器只有2字节)。

Intel的设计是段描述符集中存放在GDT或LDT中,而段寄存器存放的是段描述符在GDT或LDT内的索引值(index)。

Linux中逻辑地址等于线性地址。

为什么这么说呢?因为Linux所有的段(用户代码段、用户数据段、内核代码段、内核数据段)的线性地址都是从0x00000000开始,长度4G,这样线性地址=逻辑地址+ 0x00000000,也就是说逻辑地址等于线性地址了。

这样的情况下Linux只用到了GDT,不论是用户任务还是内核任务,都没有用到LDT。

GDT的第12和13项段描述符是__KERNEL_CS和__KERNEL_DS,第14和15项段描述符是__USER_CS和__USER_DS。

内核任务使用__KERNEL_CS和__KERNEL_DS,所有的用户任务共用__USER_CS和__USER_DS,也就是说不需要给每个任务再单独分配段描述符。

内核段描述符和用户段描述符虽然起始线性地址和长度都一样,但DPL(描述符特权级)是不一样的。

__KERNEL_CS和__KERNEL_DS的DPL值为0(最高特权),__USER_CS和__USER_DS的DPL 值为3。

用gdb调试程序的时候,用info reg显示当前寄存器的值:
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
可以看到ds值为0x7b,转换成二进制为00000000 01111011,TI字段值为0,表示使用GDT,GDT索引值为01111,即十进制15,对应的就是GDT内的__USER_DATA用户数据段描述符。

从上面可以看到,Linux在x86的分段机制上运行,却通过一个巧妙的方式绕开了分段。

Linux主要以分页的方式实现内存管理。

二、线性地址转物理地址
前面说了Linux中逻辑地址等于线性地址,那么线性地址怎么对应到物理地址呢?这个大家都知道,那就是通过分页机制,具体的说,就是通过页表查找来对应物理地址。

准确的说分页是CPU提供的一种机制,Linux只是根据这种机制的规则,利用它实现了内存管理。

在保护模式下,控制寄存器CR0的最高位PG位控制着分页管理机制是否生效,如果PG=1,分页机制生效,需通过页表查找才能把线性地址转换物理地址。

如果PG=0,则分页机制无效,线性地址就直接做为物理地址。

分页的基本原理是把内存划分成大小固定的若干单元,每个单元称为一页(page),每页包含4k字节的地址空间(为简化分析,我们不考虑扩展分页的情况)。

这样每一页的起始地址都是4k字节对齐的。

为了能转换成物理地址,我们需要给CPU提供当前任务的线性地址转物理地址的查找表,即页表(page table)。

注意,为了实现每个任务的平坦的虚拟内存,每个任务都有自己的页目录表和页表。

为了节约页表占用的内存空间,x86将线性地址通过页目录表和页表两级查找转换成物理地址。

32位的线性地址被分成3个部分:
最高10位Directory 页目录表偏移量,中间10位Table是页表偏移量,最低12位Offset 是物理页内的字节偏移量。

页目录表的大小为4k(刚好是一个页的大小),包含1024项,每个项4字节(32位),项目里存储的内容就是页表的物理地址。

如果页目录表中的页表尚未分配,则物理地址填0。

页表的大小也是4k,同样包含1024项,每个项4字节,内容为最终物理页的物理内存起始地址。

每个活动的任务,必须要先分配给它一个页目录表,并把页目录表的物理地址存入cr3寄存器。

页表可以提前分配好,也可以在用到的时候再分配。

还是以mov 0x80495b0, %eax 中的地址为例分析一下线性地址转物理地址的过程。

前面说到Linux中逻辑地址等于线性地址,那么我们要转换的线性地址就是0x80495b0。

转换的过程是由CPU自动完成的,Linux所要做的就是准备好转换所需的页目录表和页表(假设已经准备好,给页目录表和页表分配物理内存的过程很复杂,后面再分析)。

内核先将当前任务的页目录表的物理地址填入cr3寄存器。

线性地址0x80495b0 转换成二进制后是0000 1000 0000 0100 1001 0101 1011 0000,最高10位0000 1000 00的十进制是32,CPU查看页目录表第32项,里面存放的是页表的物理地址。

线性地址中间10位00 0100 1001 的十进制是73,页表的第73项存储的是最终物理页的物理起始地址。

物理页基地址加上线性地址中最低12位的偏移量,CPU就找到了线性地址最终对应的物理内存单元。

我们知道Linux中用户进程线性地址能寻址的范围是0 -3G,那么是不是需要提前先把这3G虚拟内存的页表都建立好呢?一般情况下,物理内存是远远小于3G的,加上同时有很多进程都在运行,根本无法给每个进程提前建立3G的线性地址页表。

Linux利用CPU的一个机制解决了这个问题。

进程创建后我们可以给页目录表的表项值都填0,CPU在查找页表时,如果表项的内容为0,则会引发一个缺页异常,进程暂停执行,Linux内核这时候可以通过一系列复杂的算法给分配一个物理页,并把物理页的地址填入表项中,进程再恢复执行。

当然进程在这个过程中是被蒙蔽的,它自己的感觉还是正常访问到了物理内存。

本文来自:我爱研发网() - R&D大本营
详细出处:/Blog/Archive_Thread.asp?SID=26930。

相关文档
最新文档