emerge -av gnome
ninja: build stopped: subcommand failed.
* ERROR: net-libs/webkit-gtk-2.38.3::gentoo failed (compile phase):
* ninja -v -j5 -l0 failed
*
* Call stack:
* ebuild.sh, line 136: Called src_compile
* environment, line 3968: Called cmake_src_compile
* environment, line 1782: Called cmake_build
* environment, line 1751: Called eninja
* environment, line 2206: Called die
* The specific snippet of code:
* "$@" || die -n "${*} failed"
*
* If you need support, post the output of `emerge --info '=net-libs/webkit-gtk-2.38.3::gentoo'`,
* the complete build log and the output of `emerge -pqv '=net-libs/webkit-gtk-2.38.3::gentoo'`.
* The complete build log is located at '/var/tmp/portage/net-libs/webkit-gtk-2.38.3/temp/build.log'.
* The ebuild environment file is located at '/var/tmp/portage/net-libs/webkit-gtk-2.38.3/temp/environment'.
* Working directory: '/var/tmp/portage/net-libs/webkit-gtk-2.38.3/work/webkitgtk-2.38.3_build'
* S: '/var/tmp/portage/net-libs/webkit-gtk-2.38.3/work/webkitgtk-2.38.3'
Gentoo下常见masked解决方法小结
masked by: missing keyword
masked by: package.mask
masked by: xxx license(s)
masked by: missing keyword
以app-i18n/ibus-table-wubi-9999为例。
!!! All ebuilds that could satisfy "app-i18n/ibus-table-wubi" have been masked.
!!! One of the following masked packages is required to complete your request:
- app-i18n/ibus-table-wubi-9999 (masked by: missing keyword)
For more information, see the MASKED PACKAGES section in the emerge
man page or refer to the Gentoo Handbook.
在手册上的说明如下:
“missing keyword”意味着这个软件还没有在您机器的体系结构中进行过测试。
您可以咨询相应体系结构移植小组是否能对它进行测试,
或者您自己为他们进行这样的测试并将您得到的结论提交到我们的bugzilla网站。
解决思路,修改/etc/portage/package.keywords,强制标记为稳定。
解决方法,将形如
$OPERATOR$APP_NAME-$VERSION $ARCH_KEYWORD
字段添加到/etc/portage/package.keywords。
对应上例为:
=app-i18n/ibus-table-wubi-9999 **
如果您不知道KEYWORDS该如何写,可以先看一下被masked的包的KEYWORD:
less `equery w app-i18n/ibus-table-wubi`
如果看到的是
KEYWORDS=""
则使用“**”作为ARCH_KEYWORD,“**”表示该包没有keyword。
其他的“~x86”之类,照抄即可。
masked by: package.mask
以sys-kernel/gentoo-sources-2.6.33为例。
!!! All ebuilds that could satisfy "=sys-kernel/gentoo-sources-2.6.33" have been masked.
!!! One of the following masked packages is required to complete your request:
- sys-kernel/gentoo-sources-2.6.33 (masked by: package.mask)
For more information, see the MASKED PACKAGES section in the emerge
man page or refer to the Gentoo Handbook.
解决思路,修改/etc/portage/package.unmask,强制标记为稳定。
解决方法,
在/etc/portage/package.unmask里添加
=sys-kernel/gentoo-sources-2.6.33
masked by: xxx license(s)
以dev-java/sun-jre-bin-1.6.0.17为例。
!!! The following installed packages are masked:
- dev-java/sun-jre-bin-1.6.0.17 (masked by: dlj-1.1 license(s))
A copy of the 'dlj-1.1' license is located at '/usr/portage/licenses/dlj-1.1'.
For more information, see the MASKED PACKAGES section in the emerge
man page or refer to the Gentoo Handbook.
解决思路,修改/etc/make.conf,降低许可敏感级别。
解决方法,
在/etc/make.conf里追加一行
ACCEPT_LICENSE="*"
Last modified by anonymous on 04/03/2010 10:27:28 AM ( ago)
These are the packages that would be merged, in order:
Calculating dependencies... done!
!!! All ebuilds that could satisfy "bochs" have been masked.
!!! One of the following masked packages is required to complete your request:
- app-emulation/bochs-9999::gentoo (masked by: missing keyword)
- app-emulation/bochs-2.7::gentoo (masked by: ~amd64 keyword)
- app-emulation/bochs-2.6.10::gentoo (masked by: ~amd64 keyword)
For more information, see the MASKED PACKAGES section in the emerge
man page or refer to the Gentoo Handbook.
Step1 设置locale
1>编辑/etc/locale.gen,在最后加入两行“zh_CN.UTF-8 UTF-8”和“zh_CN.GBK GBK”,如下
zh_CN.UTF-8 UTF-8
zh_CN.GBK GBK
en_GB.UTF-8 UTF-8
2>运行locale-gen命令,生成locale:
#locale-gen
3>编辑/etc/env.d/02locale,若没有则创建,加入一行“LANG="zh_CN.GBK"”,如下:
#nano /etc/env.d/02locale
##02locale内容简单如下就ok了
LANG="zh_CN.GBK"
4>运行env-update更新环境
#env-update
Step2 安装字体
经过Step1设置后编码已经是中文了,可以运行locale命令查看之,但是由于默认的字体并不能显示中文,而会乱码。所以要换一个字体
1>选择你喜欢的字体,ttc或ttf格式,比如仿宋simsun.ttc
2>复制到任意目录下,比如/usr/share/fonts/ttf下,然后执行如下字体相关的命令
#cp simsun.ttc /usr/share/fonts/ttf/simsun.ttf
#cd /usr/share/fonts/ttf
#sudo chmod 644 simsun.ttf
#sudo mkfontdir
#sudo mkfontscale
3>配置X Window的字体显示
#编辑配置文件
#nano /etc/X11/xorg.conf
#在Files Section中加入,没有就创建,如下
Section "Files"
…
FontPath "/usr/share/fonts/ttf"
…
EndSection
4>更新字体配置
#sudo fc-cache -fv
界面中文:
emerge -av wqy-zenhei
eselect fontconfig enable 44-wqy-zenhei.conf
eselect fontconfig enable 66-wqy-zenhei-sharp.conf
xset fp rehash
其中wqy-zenhei被masked,另外加入"X" USE标记
>=media-libs/libcanberra-0.30-r7 pulseaudio
解决办法
遇到这种事会交给 Gentoo 自己去处理。
1: 先卸掉引起冲突的包。
emerge -C media-libs/libcanberra
2:让 Gentoo 自己来算,应该加哪些 use
emerge -avuDN --autounmask-write world
3:应用一下更改的 use
dispatch-conf
选择u
4:再来:
emerge -vuDN --with-bdeps=y --keep-going world
5:再做些预防工作
python-updater
perl-cleaner --modules
emerge @preserved-rebuild
emerge -v @module-rebuild
(==) Using system config directory "/usr/share/X11/xorg.conf.d"
MESA-LOADER: failed to open iris: /usr/lib64/dri/iris_dri.so: cannot open shared object file: No such file or directory (search paths /usr/lib64/dri, suffix _dri)
failed to load driver: iris
MESA-LOADER: failed to open zink: /usr/lib64/dri/zink_dri.so: cannot open shared object file: No such file or directory (search paths /usr/lib64/dri, suffix _dri)
failed to load driver: zink
/root/.xinitrc: line 2: exec: gnome-session: not found
xinit: connection to X server lost
查询得知双显卡的问题,正在找解决办法
Calculating dependencies... done!
!!! All ebuilds that could satisfy "x11-drivers/nvidia-drivers" have been masked.
!!! One of the following masked packages is required to complete your request:
- x11-drivers/nvidia-drivers-525.85.05::gentoo (masked by: NVIDIA-r2 license(s), ~amd64 keyword)
A copy of the 'NVIDIA-r2' license is located at '/var/db/repos/gentoo/licenses/NVIDIA-r2'.
- x11-drivers/nvidia-drivers-525.78.01::gentoo (masked by: NVIDIA-r2 license(s), ~amd64 keyword)
- x11-drivers/nvidia-drivers-525.60.13::gentoo (masked by: NVIDIA-r2 license(s))
- x11-drivers/nvidia-drivers-525.47.06::gentoo (masked by: package.mask, NVIDIA-r2 license(s), ~amd64 keyword)
/var/db/repos/gentoo/profiles/package.mask:
# Ionen Wolkens <ionen@gentoo.org> (2021-10-09)
# Vulkan beta driver branch aimed at Vulkan developers for testing
# new features. Beside vulkan, it is typically behind the main branch
# and may be buggier or less secure. Only unmask if really wanted.
- x11-drivers/nvidia-drivers-515.86.01::gentoo (masked by: NVIDIA-r2 license(s))
- x11-drivers/nvidia-drivers-510.108.03::gentoo (masked by: NVIDIA-r2 license(s))
- x11-drivers/nvidia-drivers-470.161.03::gentoo (masked by: NVIDIA-r2 license(s))
- x11-drivers/nvidia-drivers-390.157::gentoo (masked by: NVIDIA-r2 license(s))
(dependency required by "x11-base/xorg-drivers-21.1-r2::gentoo[video_cards_nvidia]" [ebuild])
(dependency required by "x11-base/xorg-server-21.1.6::gentoo[xorg]" [ebuild])
(dependency required by "gnome-base/gdm-43.0::gentoo" [ebuild])
(dependency required by "gnome-base/gnome-shell-43.2-r1::gentoo" [ebuild])
(dependency required by "app-eselect/eselect-gnome-shell-extensions-20180306-r1::gentoo" [ebuild])
(dependency required by "gnome-extra/gnome-shell-extensions-43.1::gentoo" [ebuild])
(dependency required by "gnome-base/gnome-40.0-r1::gentoo[classic]" [ebuild])
(dependency required by "gnome-base/gnome" [argument])
For more information, see the MASKED PACKAGES section in the emerge
man page or refer to the Gentoo Handbook.
处理办法:
nano /etc/portage/package.license
添加
x11-drivers/nvidia-drivers NVIDIA-r2
* IMPORTANT: 10 news items need reading for repository 'gentoo'.
* Use eselect news read to view new items.
These are the packages that would be merged, in order:
Calculating dependencies... done!
!!! All ebuilds that could satisfy "sys-kernel/linux-firmware" have been masked.
!!! One of the following masked packages is required to complete your request:
- sys-kernel/linux-firmware-99999999::gentoo (masked by: || ( ) linux-fw-redistributable no-source-code license(s), missing keyword)
A copy of the 'linux-fw-redistributable' license is located at '/var/db/repos/gentoo/licenses/linux-fw-redistributable'.
A copy of the 'no-source-code' license is located at '/var/db/repos/gentoo/licenses/no-source-code'.
- sys-kernel/linux-firmware-20230117::gentoo (masked by: || ( ) linux-fw-redistributable no-source-code license(s), ~amd64 keyword)
- sys-kernel/linux-firmware-20221214::gentoo (masked by: || ( ) linux-fw-redistributable no-source-code license(s))
- sys-kernel/linux-firmware-20221109::gentoo (masked by: || ( ) linux-fw-redistributable no-source-code license(s))
- sys-kernel/linux-firmware-20221012-r1::gentoo (masked by: || ( ) linux-fw-redistributable no-source-code license(s), ~amd64 keyword)
- sys-kernel/linux-firmware-20221012::gentoo (masked by: || ( ) linux-fw-redistributable no-source-code license(s))
- sys-kernel/linux-firmware-20220913-r2::gentoo (masked by: || ( ) linux-fw-redistributable no-source-code license(s))
- sys-kernel/linux-firmware-20220815::gentoo (masked by: || ( ) linux-fw-redistributable no-source-code license(s))
- sys-kernel/linux-firmware-20220708::gentoo (masked by: || ( ) linux-fw-redistributable no-source-code license(s))
- sys-kernel/linux-firmware-20220610::gentoo (masked by: || ( ) linux-fw-redistributable no-source-code license(s))
- sys-kernel/linux-firmware-20220509::gentoo (masked by: || ( ) linux-fw-redistributable no-source-code license(s))
- sys-kernel/linux-firmware-20220411::gentoo (masked by: || ( ) linux-fw-redistributable no-source-code license(s))
- sys-kernel/linux-firmware-20220310::gentoo (masked by: || ( ) linux-fw-redistributable no-source-code license(s))
- sys-kernel/linux-firmware-20220209::gentoo (masked by: || ( ) linux-fw-redistributable no-source-code license(s))
(dependency required by "sys-kernel/genkernel-4.2.6-r8::gentoo[firmware]" [ebuild])
(dependency required by "sys-kernel/genkernel" [argument])
For more information, see the MASKED PACKAGES section in the emerge
man page or refer to the Gentoo Handbook.
解决办法:
nano /etc/portage/package.license
添加:
sys-kernel/linux-firmware linux-fw-redistributable no-source-code
一、 parted的用途及说明
概括使用说明:
parted用于对磁盘(或RAID磁盘)进行分区及管理,与fdisk分区工具相比,支持2TB以上的磁盘分区,并且允许调整分区的大小。
GNU手册说明:
parted是一个用于硬盘分区或调整分区大小的工具。使用它你可以创建、清除、调整、移动和复制ext2、ext3、linux-swap、FAT、FAT32和reiserfs分区;也能创建、调整和移动苹果系统的HFS分区;还能检测jfs、ntfs、ufs和xfs分区。该工具常用于为新安装的操作系统创建空间,重新分配硬盘使用情况,在将数据拷贝到新硬盘的时候也常常使用。
二、 parted的使用方法及步骤
1、对磁盘进行分区
(1)命令行方式
# parted /dev/sdb mklabel gpt mkpart 1 ext3 1 5T
(2)交互式命令方式
命令
解释
# parted /dev/sdb
对/dev/sdb进行分区或管理操作
GNU Parted 1.8.1
使用 /dev/sdb
Welcome to GNU Parted! Type 'help' to view a list of commands.
系统返回值
(parted) mklabel gpt
定义分区表格式
(常用的有msdos和gpt分区表格式,msdos不支持2TB以上容量的磁盘,所以大于2TB的磁盘选gpt分区表格式)
(parted) mkpart p1
创建第一个分区,名称为p1
(p1只是第一个分区的名称,用别的名称也可以,如part1)
File system type? [ext2]? ext3
定义分区格式
(不支持ext4,想分ext4格式的分区,可以通过mkfs.ext4格式化成ext4格式)
Start? 1
定义分区的起始位置
(单位支持K,M,G,T)
End? 5T
定义分区的结束位置
(单位支持K,M,G,T)
(parted) print
查看当前分区情况
Model: ATA VBOX HARDDISK (scsi)
Disk /dev/sda: 21.5GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size File system Name Flags
1 32.3kB 5TB 5TB ext3 p1
系统返回值
2、删除分区
命令
解释
# parted /dev/sdb
对/dev/sdb进行分区或管理操作
(parted) rm
rm删除命令
(删除之前必须确保分区没有被挂载)
Partition number? 1
删除第一个分区
(parted) print
查看当前分区情况
Model: ATA VBOX HARDDISK (scsi)
Disk /dev/sda: 21.5GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size File system Name Flags
系统返回值
3、格式化几个TB的磁盘的说明
在格式化几个TB的磁盘的时候,时间会非常的长,格式化6T的磁盘时间大概在一个半小时左右。(据硬盘实际情况而定)
三、 partd分区实例
fdisk工具虽然很好用,但对于大于2T以上的硬盘分区特别慢,可能一部分容量识别不了,也不支持非交互模式。
用parted就非常方便了,对大硬盘支持很好,也可以实现脚本分区。
默认一般都安装过了,没有的话install it!
yum install parted
parted有个不提示用户参数选项,就是通过这个选项来实现非交互
-s, --script
never prompts for user intervention
下面我们通过一个一块硬盘来说明它的具体操作:
第一个主分区3G
剩余分区都给扩展分区
第一个逻辑卷分区2G
第二个逻辑源用剩余空间
第一个主分区3G
parted -s /dev/sdb mklabel msdos
parted -s /dev/sdb mkpart primary 0 3G
剩余空间给扩展分区
parted -s /dev/sdb mkpart entended 3 100%
在扩展分区上创建第一个逻辑分区
parted -s /dev/sdb mkpart logic 3G 5G
创建第二个逻辑分区
parted -s /dev/sdb mkpart logic 5G 100% #100%代表使用剩余的所有空间
查看分区大小
parted -s /dev/sdb print
Model: ATA QEMU HARDDISK (scsi)
Disk /dev/sdb: 8590MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File system 标志
1 512B 3000MB 3000MB primary
2 3001MB 8590MB 5589MB extended lba
5 5000MB 8590MB 3590MB logical
删除分区
parted -s /dev/sdb rm 5 #rm后面跟的事分区的编号,print出的Number
parted -s /dev/sdb print
Number Start End Size Type File system 标志
1 512B 3000MB 3000MB primary
2 3001MB 8590MB 5589MB extended lba
对/dev/sdc分一个主分区,类型为swap
parted -s /dev/sdc mklabel msdos
parted -s /dev/sdc -- mkpartfs primary linux-swap 0 -1 #从使用所有空间
1,将磁盘上原有的分区删除掉:
进入:#parted /dev/sdb
查看:(parted)p
删除:(parted)rm 1
(parted)rm 2
2,将磁盘格式变成gpt的格式(因为parted只能针对gpt格式的磁盘进行操作)
转换:(parted) mklabel gpt
分区:(parted) mkpart primary 1 500 (分第一个主分区500MB)
分区:(parted) mkpart primary 501 1000 (分第二个主分区500MB)
分区:(parted) mkpart logical 1001 2000 (分第三个逻辑分区1000MB) (parted的逻辑分区不用先分扩展分区,直接一步到位)
查看:(parted) p
退出:(parted)quit ( parted分区自动保存,不用手动保存 )
3,格式化已经分好的区
# mkfs -t ext4 /dev/sdb1
4,挂载
# mount /dev/sdb1 /mnt
5,开机自动挂载:
# echo “/dev/sdb1 /mnt ext4 defaults 0 0” >>/etc/fstab
强烈建议对照官方文档参考
从gentoo官网下载iso,我这里下载的是amd64下的Minimal Installation CD
如果要制作USB启动盘,可以使用Rufus
光盘/U盘启动
网络链接
ping -c 1 www.baidu.com
如果能ping通,直接进行安装,否则通过ifconfig查看网卡名字
如果是有线网卡,网卡名称是enp3s0,执行
ifconfig enp3s0 192.168.1.168 broadcast 192.168.1.255 netmask 255.255.255.0
ip route add via 192.168.1.1 dev enp3s0
echo "nameserver 114.114.114.114" > /etc/resolv.conf
如果是无线网卡,网卡名称是wlp3s0
加密方式是wep
iwlist wlp3s0 scanning #查看附近的ESSID
iw dev wlp3s0 info
iw dev wlp3s0 link
ip link set dev wlp3s0 up
iw dev wlp3s0 connect -w ESSID #没有密码
iw dev wlp3s0 connect -w ESSID key 0:d:1234123412341234abc #密码是16进制
iw dev wlp3s0 connect -w ESSID key 0:some-password #密码是ASCII格式
dhcpcd wlp3s0 #获取ip
iwconfig #查看是否连接指定的SSID
加密方式是wpa/wpa2,这个方法也支持wep加密
在/etc/wpasupplicant/wpa_supplicant.conf里增加
network {
ssid="ESSID"
psk="密码"
priority=1
}
执行
wpa_supplicant -i wlp3s0 -c /etc/wpa_supplicant/wpa_supplicant.conf #运行wpa_supplicant
dhcpcd wlp3s0 #获取ip
iwconfig #查看是否连接指定的SSID
我这里为了安装方便,通过ssh安装
启动ssh服务
/etc/init.d/sshd start
或
rc-service sshd start
修改root密码
passwd
从其他电脑通过ssh连接过来
使用parted进行GPT分区(UEFI必须是GPT分区格式,且用parted或gdisk)
交互式操作
parted -a optimal /dev/sda #-a 优化分区对齐
(parted) mklabel gpt #设置GPT分区格式
(parted) unit mib
(parted) mkpart primary 1 3 #固定为2M的bios启动分区,GPT和GRUB2一起使用时必须要有这个,UEFI下不需要
(parted) name 1 grub
(parted) set 1 bios_grub on
(parted) mkpart primary 3 131 #boot分区
(parted) name 2 boot
(parted) set 2 boot on #当使用UEFI接口来引导系统时(取代BIOS),要将引导分区标识为EFI系统分区。当“boot”选项在这个分区被设置时,Parted可以自动完成此事。
(parted) mkpart primary 131 643 #交换分区
(parted) name 3 swap
(parted) mkpart primary 643 -1 #简单起见,剩下的全部在/分区,实际中可以把home、var等分区独立出来
(parted) name 4 rootfs
(parted) quit
非交互式操作,注释见上方
yes | parted -a optimal /dev/sda mklabel gpt
parted -a optimal /dev/sda unit mib
parted -a optimal /dev/sda mkpart primary 1 3
parted -a optimal /dev/sda name 1 grub
parted -a optimal /dev/sda set 1 bios_grub on
parted -a optimal /dev/sda mkpart primary 3 131
parted -a optimal /dev/sda name 2 boot
parted -a optimal /dev/sda set 2 boot on
parted -a optimal /dev/sda mkpart primary 131 643
parted -a optimal /dev/sda name 3 swap
parted -a optimal -- /dev/sda mkpart primary 643 -1
parted -a optimal /dev/sda name 4 rootfs
parted -a optimal /dev/sda p
格式化分区
mkfs.ext2 /dev/sda2 #UEFI是mkfs.vfat -F 32 /dev/sda2
mkfs.ext4 /dev/sda4
mkswap /dev/sda3
swapon /dev/sda3
挂载分区
mount /dev/sda4 /mnt/gentoo
修改时间,注意参数要替换成具体数字(Month, Day, hour, minute and Year)
date MMDDhhmmYYYY
或者(最好)
ntpd -q -g
安装stage3
cd /mnt/gentoo
去gentoo官网下载对应的stage3包
tar xpf stage3-*.tar.* --xattrs-include='*.*' --numeric-owner
rm -rf stage3-*.tar.*
配置make.conf里的编译选项 查看CPU类型
cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c
在/mnt/gentoo/etc/portage/make.conf里配置
CFLAGS="-march=native -O2 -pipe" #native表示使用当前系统体系结构,-pipe表示使用管道加快速度,如果内存不足,就去掉
CXXFLAGS="${CFLAGS}"
MAKEOPTS="-j3" #cpu核数+1=3
配置源
#按空格选择
mirrorselect -i -o >> /mnt/gentoo/etc/portage/make.conf #相当于再make.conf里增加GENTOO_MIRRORS="https://mirror.bjtu.edu.cn/gentoo/ http://mirrors.163.com/gentoo/ http://gentoo.aditsu.net:8000/ rsync://ftp.iij.ad.jp/pub/linux/gentoo/ http://ftp.iij.ad.jp/pub/linux/gentoo/ http://ftp.jaist.ac.jp/pub/Linux/Gentoo/ rsync://ftp.jaist.ac.jp/pub/Linux/Gentoo/"
mkdir -p /mnt/gentoo/etc/portage/repos.conf
cp /mnt/gentoo/usr/share/portage/config/repos.conf /mnt/gentoo/etc/portage/repos.conf/gentoo.conf
拷贝DNS信息
cp -L /etc/resolv.conf /mnt/gentoo/etc/
chroot
mount -t proc proc /mnt/gentoo/proc
mount --rbind /sys /mnt/gentoo/sys
mount --make-rslave /mnt/gentoo/sys #安装systemd支持时所需要
mount --rbind /dev /mnt/gentoo/dev
mount --make-rslave /mnt/gentoo/dev #安装systemd支持时所需要
chroot /mnt/gentoo /bin/bash
source /etc/profile
export PS1="(chroot) $PS1"
挂载boot分区
mkdir /boot
mount /dev/sda2 /boot
安装portage最新快照(通常是24小时内)
emerge-webrsync
查看new,这个环节比较重要,我这里没有影响
通过eselect news list和eselect news read 编号 查看news,以下都是news里的一些信息
如果/和/usr在不同分区,内核必须使用initramfs
更新portage数据库(通常是1小时内)
emerge --sync
选择合适的profile
eselect profile list
#如果是desktop
eselect profile set 16
或
eselect profile set default/linux/amd64/17.0/desktop
#如果是desktop+gnome
eselect profile set 17
或
eselect profile set default/linux/amd64/17.0/desktop/gnome
#如果是systemd
#参考 https://wiki.gentoo.org/wiki/Systemd
eselect profile set 25
或
eselect profile set default/linux/amd64/17.0/systemd
#如果是desktop+systemd
#参考 https://wiki.gentoo.org/wiki/Systemd/In … om_scratch
eselect profile set 18
或
eselect profile set default/linux/amd64/17.0/desktop/gnome/systemd
更新@world
emerge -av -uDN @world
根据提示
eselect pinentry set pinentry-gnome3
我习惯用vim
emerge -av vim
eselect vi set vim # eselect vi set 1
eselect vi list
eselect editor set /usr/bin/vi # eselect editor set 3
eselect editor list
. /etc/profile
配置make.conf
查看当前的USE设置
emerge --info | grep ^USE
查看cpu支持的指令集
emerge -1v app-portage/cpuid2cpuflags
cpuid2cpuflags #记下执行结果,下一步用到
修改/etc/portage/make.conf,显卡配置参考Xorg/Guide
LINGUAS="zh_CN en" #安装软件包的时候,如果有中文语言包,就顺便装上
L10N="zh-CN" #安装thunderbird(bin版本中文显示有问题)、libreoffice-l10n的时候,安装中文包
VIDEO_CARDS="intel i965" #请根据自己的显卡类型填入,virtualbox虚拟机里是virtualbox
INPUT_DEVICES="libinput evdev keyboard mouse synaptics" #synaptics是触摸板,libinput已经包含evdev
USE="python pulseaudio git subversion mercurial sync-plugin-portage gnome-keyring bash-completion vim-syntax tk icu" #icu是安装chromium需要
CPU_FLAGS_X86="mmx mmxext sse sse2 sse3 sse4_1 ssse3" #上一步看到的指令集
ABI_X86="32 64" #安装32位和64位,如果存在循环依赖,可以先注释掉
#UEFI
#GRUB_PLATFORMS="efi-32 efi-64 pc"
GRUB_PLATFORMS="efi-64"
设置时区
echo "Asia/Shanghai" > /etc/timezone
emerge --config sys-libs/timezone-data #时间可能不对,查看下是否需要设置
设置字符集
在/etc/locale.gen里增加
en_US ISO-8859-1
en_US.UTF-8 UTF-8
zh_CN.UTF-8 UTF-8
zh_CN.GB2312 GB2312
zh_CN.GBK GBK
zh_CN GB18030
更新
locale-gen
eselect locale list
eselect locale set zh_CN.utf8 # eselect locale set 10
. /etc/profile
继续
在/etc/env.d/02locale里增加
LC_COLLATE="C"
env-update && source /etc/profile && export PS1="(chroot) $PS1"
分区挂载设置(使用genkernel需要先设置好boot挂载)
编辑/etc/fstab,注意,如果是UEFI,则boot分区挂载为vfat(非ext2)
/dev/sda2 /boot ext2 defaults,noatime 0 2
/dev/sda3 none swap sw 0 0
/dev/sda4 / ext4 noatime 0 1
/dev/cdrom /mnt/cdrom auto noauto,user 0 0
安装内核和常用工具,注意,systemd下是genkernel-next
emerge -av gentoo-sources pciutils genkernel app-portage/eix mcelog gentoolkit #iproute2已安装
cd /usr/src/linux
#如果使用systemd
ln -sf /proc/self/mounts /etc/mtab
配置参考Configuring the Linux kernel
蓝牙、打印机等配置参考Gentoo_Kernel_Configuration_Guide
显卡配置参考Xorg/Guide
无线网卡参考Wifi
声卡配置参考ALSA 蓝牙配置参考Bluetooth 电源管理配置参考Power management/Guide USB管理配置参考USB/Guide ipv6配置参考IPv6_router_guide
systemd配置参考systemd和systemd/Installing Gnome3 from scratch 照参考进行配置,CPU类型需要按照实际选择
设置CONFIG_SND_HDA_PREALLOC_SIZE为2048,HD-Audio Driver的配置 设置CONFIG_PPP_BSDCOMP,ppp用到
emerge -av sys-kernel/linux-firmware #这个是无线网卡的驱动,参考https://wiki.gentoo.org/wiki/Wifi,一般已在上一步自动安装了
#如果需要支持lvm或raid,增加参数--lvm --mdadm
genkernel --menuconfig all #如果不设置,可以直接genkernel all
网络设置,enp3s0是网卡名字,请替换为自己的网卡名字
编辑/etc/conf.d/hostname
hostname="home"
编辑/etc/hosts,增加主机名到127.0.0.1后面
安装netifrc
emerge --noreplace netifrc
设置网络,编辑/etc/conf.d/net,修改如下 前三行是固定ip,第四行是动态ip,选择一个就可以了
config_enp3s0="192.168.1.173 netmask 255.255.255.0 brd 192.168.1.255"
routes_enp3s0="default via 192.168.1.1"
dns_servers="114.114.114.114 223.5.5.5 192.168.1.1"
config_enp3s0="dhcp"
如果是多ip,第一行改成
config_enp3s0="192.168.1.173 netmask 255.255.255.0 brd 192.168.1.255
192.168.1.174 netmask 255.255.255.0 brd 192.168.1.255
192.168.1.175 netmask 255.255.255.0 brd 192.168.1.255"
设置自启动
cd /etc/init.d
ln -s net.lo net.enp3s0
rc-update add net.enp3s0 default
设置新系统的root密码,一定要做,否则重启后无法登陆
passwd
安装一些必要的系统工具
emerge -av syslog-ng cronie mlocate net-misc/dhcpcd logrotate sudo
#如果是pppoe
emerge -av ppp
#如果是无线网络
emerge -av wpa_supplicant
rc-update add syslog-ng default
rc-update add cronie default
rc-update add sshd default
rc-update add dhcpcd default
这里普通用户用crontab -l报'/var/spool/cron/crontabs' is not a directory, bailing out.(现在已经不需要了)
chmod o+rx /var/spool/cron
安装引导,os-prober是多系统的时候有用
emerge -av sys-boot/grub os-prober
grub的默认配置在/etc/default/grub,比如可以把超时时间改成3秒
/dev/sda是启动分区所在
#如果是BIOS
grub-install /dev/sda
#如果是UEFI
grub-install --target=x86_64-efi --efi-directory=/boot
#如果报错:Could not prepare Boot variable: Read-only file system,先执行下面命令再执行install
mount -o remount,rw /sys/firmware/efi/efivars
#如果重启没有出现grub界面,参考https://www.linuxidc.com/Linux/2017-10/147754.htm
#注意引导命令是\EFI\gentoo\grubx64.efi
#进入后执行grub-install --target=x86_64-efi --efi-directory=/boot --removable会自动生成
#/boot/EFI/BOOT/BOOTX64.EFI文件,然后就可以重启成功了
grub-mkconfig -o /boot/grub/grub.cfg
安装完成,重启,建议在shutdown后才把光盘取出,否则可能会报io错误
exit
cd
umount -l /mnt/gentoo/dev{/shm,/pts,}
umount -R /mnt/gentoo{/boot,/proc,}
shutdown -h now
1.进程和线程以及他们的区别
进程:进程是对运行时程序的封装,是系统进行资源调度和分配的基本单位,实现操作系统的并发。
线程:线程是进程的子任务,是CPU调度和分配的基本单位。
一个程序至少拥有一个进程,一个进程至少拥有一个线程,线程依赖于进程而存在。进程执行时拥有独立的内存单元,而多个线程共享进程的内存。
2.进程间的通信方式
管道及命名管道:管道可用于具有父子亲缘关系的进程间的通信,有名管道除了具有管道所具有的功能外,它还允许无亲缘关系的进程间的通信。
信号:信号是一种比较复杂的通信方式,用于接收进程某个事件已发生。
消息队列:消息队列是消息的链接表,它克服了,以上两种通信方式中信号量有限的缺点,具有写权限的进程可以按照一定的规则向消息队列中添加新信息,具有读权限的进程可以从消息队列中读取信息。
共享内存:可以说是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程对共享内存中数据的更新。这种方式依赖于某种同步操作,如互斥锁和信号量等。
信号量:主要作为进程之间及同一进程的不同线程之间的同步和互斥手段。
套接字:这是一种更为一般的进程间通信机制,他可以用于网络中不同机器之间的进程间的通信,应用非常广泛。
3.线程的同步方式
互斥量:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以可以保证公共资源不会同时被多个线程访问。
信号量:它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量。
事件(信号):通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作。
4.死锁,死锁产生条件
死锁:在两个或多个并发进程中,如果每个进程持有某种资源而等待其他进程释放它或者它们保持的资源,再改变这种状态之前,都不能向前推进,称这一组进程产生了死锁。(由于不合理的推进顺序或者资源分配导致产生了环路等待)
死锁产生的四个必要条件:
互斥:至少一个资源处于非共享模式,即一次只能被一个进程使用;若其他进程申请使用该资源,则必须等到该资源被释放为止。
占有并等待:一个进程必须占有至少一个资源,并等待另一个资源,而该资源为其他进程所占有
非抢占:进程不能被强占,即资源只能被进程在完成任务后自愿释放。
循环等待:若干进程之间形成一种头尾相接的环形等待资源关系。
5.死锁处理的基本策略和常用方法:
预防死锁,避免死锁,检测死锁,解除死锁,鸵鸟算法(把头埋进沙子里,当做啥也没发生)
6.死锁预防的基本思想:
只要确保死锁发生的四个必要条件中至少一个不成立,就能预防死锁的发生。
具体方法:
打破互斥条件:允许进程同时访问某些资源。但是,有些进程不能被同时访问是由资源的属性决定的,因此这种方法并无实用价值。
打破占有并等待条件:可以实行资源的预先分配策略(进程在运行前一次性向系统申请它所需要的所有资源,若所需全部资源得不到满足,则不分配任何资源,此进程暂不运行;只有当系统满足当前进程所有资源时,才一次性的将全部资源分配给该进程)或者只允许在没有占有资源时才可以申请资源(一个进程可以申请资源并使用他们,但是当前进程申请更多资源前,必须释放所占有资源)。这种策略存在一些缺点,在很多情况下,无法预知一个进程执行前所需的全部资源,因为进程是动态执行的,不可预知的;同时,会降低资源利用率,导致降低进程的并发性。
打破非抢占条件:允许进程强行从占有者那里夺取某些资源。当一个进程占有了一部分资源,在其中请求新的资源且得不到满足,它必须释放所有的资源以使其他线程使用,这种预防死锁的方式实现起来困难会降低系统性能。
打破循环等待条件:实行资源有序分配策略。对所有资源排序编号,所有进程对资源的请求必须严格按照资源序号递增的顺序提出,即只占用了小号资源才能申请大号资源,这样就不会产生环路,预防死锁发生。
7.死锁避免的基本思想
死锁避免的基本思想是动态的检测资源分配状态,以确保循环等待条件不成立,从而确保系统处于安全状态。所谓的安全状态指:如果系统能按照某个顺序为每个进程分配资源,那么系统状态是安全的,换句话说就是,如果存在一个安全序列,那么系统处于安全状态。资源分配图算法和银行家算法是两种经典的死锁避免算法,其可以确保,系统始终处于安全状态。其中资源分配图算法应用场景为每种资源类型只有一个实例(申请边,分配边,需求边,不形成环再允许分配)而银行家算法应用于每种资源类型可以有多个实例的场景。
8.死锁解除的常用方法
进程终止和资源抢占:
所谓进程终止是指简单地终止一个或多个进程以打破循环等待,包括两种方式:终止死锁进程和一次只终止一个进程直到取消死锁循环为止。
所谓资源抢占是指从一个或多个死锁进程那里抢占一个或多个资源,此时需要考虑三个问题:
选择一个牺牲品
回滚,回滚到安全状态
饥饿,在代价因素中加上回滚次数,回滚的越多则越不可能继续被作为牺牲品。避免一个进程被一直回滚。
9.进程有几种状态
就绪状态:进程已获得除处理机外的所需资源,等待分配处理及资源
运行状态:占用处理机资源运行,处于此状态的进程数小于等于CPU数
阻塞状态:进程等待某种条件,条件满足前无法执行
10.线程有哪几种状态
就绪:线程准备运行,不一定立马就能开始执行
运行中:进程正在执行线程代码
等待中:线程处于阻塞状态,等待外部的处理结束
睡眠中:线程被强制睡眠
I/O阻塞:等待I/O操作完成
同步阻塞:等待获取锁
死亡:线程完成了执行
11.分页和分段有什么区别(内存管理)
段式分配管理是一种符合用户视角的内存分配管理方案,在段式存储管理中,将程序的地址空间划分为若干段,堆栈段;这样每个进程有一个二维地址空间,相互独立,互不干扰。段式管理的优点是:没有内碎片(因为段大小可变,改变段大小来消除内碎片)。但段换入换出时,会产生外部碎片(比如4K的段换5K的段,会产生1K的外碎片)
页式存储管理方案是一种用户视角内存与物理内存相分离的内存分配管理方案。在页式存储管理中,将程序的逻辑地址分为固定大小的页,而物理内存划分为同样大小的帧,程序加载时,可以将任意一页放入内存中任意一个帧,这些帧不必连续,从而实现离散分离。页式存储管理的优点是:没有外部碎片(因为页大小固定),单会产生内碎片(一个页可能填充不满)
两者不同点:
目的不同:分页是由于系统管理的需要而不是用户的需要,他是信息的物理单位;分段的目的是为了更好地满足用户的需要,它是信息的逻辑单位,它含有一组其意义相对完整的信息
大小不同:页的大小固定且有系统决定,而段的长度大小却不固定,由其所完成的功能决定
地址空间不同:段向用户提供二维地址空间,页向用户提供的是一维地址空间
信息共享:段是信息的逻辑单位,便于存储保护和信息的共享,页的保护、共享受到限制
内存碎片:页式存储管理的优点是没有外碎片,单会产生内碎片,段式管理的优点是没有内碎片,但段的换入换出时会产生外部碎片
12.操作系统进程调度策略
FCFS(先来先服务,队列实现,非抢占):先请求CPU的进程先分配到CPU
SJF(最短作业优先调度算法):平均等待时间最短,但难以知道下一个CPU区间长度
优先级调度算法(可以是抢占的也可以是非抢占的):优先级越高的越先分配到CPU,相同优先级先到先服务,存在的主要问题是:低优先级进程无穷等待CPU,会导致无穷阻塞式饥饿,解决方案:老化(随着时间推移,那些越老的进程优先级越高)
时间片轮转调度算法(可抢占):队列中没有进程被分配超过一个时间片的CPU时间,除非他是唯一可运行的进程。如果进程的CPU区间超过了一个时间片,那么进程就被抢占并放回就绪队列
多级队列调度算法:将就绪队列分成多个独立的队列,每个队列都有自己独立的调度算法,队列之间采用固定优先级抢占调度,其中,一个进程根据自身属性被永久地分配到一个队列中。
多级反馈队列调度算法:与多级队列调度算法相比,其允许进程在多列之间移动,若进程使用过多CPU时间,那么他会被转移到更低的优先级队列,在较低的优先级队列等待时间过长的进程会被转移到更高优先级的队列,以防饥饿发生。
13.进程同步的机制有哪些
原子操作,信号量机制,自旋锁管理,会合、分布式管理(?)
14.虚拟内存是什么
内存的发展历程:没有内存抽象->有内存抽象->连续内存分配->不连续内存分配
虚拟内存允许执行进程不完全在内存中。虚拟内存的基本思想是:每个进程拥有独立的地址空间,这个空间被分为相等大小的多个块,称为页,每个页都是一段连续的地址。这些页被映射到物理内存,但并不是所有的页都必须在内存中才能运行程序。当程序引用到一部分在物理内存中的地址空间时,由硬件立即进行必要的映射;当程序引用到一部分不在物理内存中的地址空间时,有操作系统负责将缺失的部分装入物理内存并重新执行失败的命令。这样,对于进程而言,逻辑上似乎拥有很大的内存空间,实际其中一部分对应物理内存上的一块(称为帧,通常也和帧大小相等),还有一些没加载在内存中的对应在硬盘上,注意:请求分页系统,请求分段系统和请求段页式系统都是针对虚拟内存的,通常请求实现内存和外村的信息置换,虚拟内存实际上可以比物理内存大。当访问虚拟内存时,会访问内存管理单元去匹配对应的物理地址,如果虚拟内存的页并不存在于物理内存中会产生缺页中断,从磁盘取得缺的页放入内存,如果内存已满,会根据某种算法将磁盘中的页换出。
15.页面置换算法有哪些
FIFO先进先出算法:比如作业调度(实现简单)
LRU最近最少用算法根据使用时间到现在的长短来判断
OPT最优置换算法:理论最优,保证置换出去的页是不再被使用的页(或最长时间里不被使用的页)
LFU最少使用次数算法:根据使用次数判断
16. 虚拟内存的应用与优点有哪些
虚拟内存很适合在多道程序设计系统中使用,许多程序的片段同时保存在内存中。当一个程序等待它的一部分读入内存时,可以吧CPU交给另一个进程使用。
在内存中可以保留多个进程,系统并发性提高
接触了用户与内存间的紧密约束,进程可以比内存的全部空间还大
17.颠簸是什么(抖动)
颠簸本质上是指频繁的页调度行为,具体来讲,进程发生缺页中断,这时必须置换某一个页。然而,其他所有页都在使用,它置换一个页,但又立刻再次需要这个页。因此会不断地产生缺页中断,导致整个系统效率急剧下降,这种现象称为颠簸。
18.如何解决内存颠簸
如果是因为页面置换策略失误,可以修改算法来解决这个问题
如果是因为运行的程序太多,造成程序无法同时将所有频繁访问的页面调入内存,则要降低多道程序的数量
否则,终止该进程或增加物理内存的容量
19.局部性原理是什么
时间上的局限性:最近被访问的页在不久的将来还会被访问
空间上的局限性:内存中被访问的页周围的页很可能被访问
第一章 操作系统概述
1)一个完整的计算机系统是由硬件系统和软件系统两大部分组成
2)计算机软件是指程序和与程序相关的文档的集合
3)按功能可把软件分为“系统软件”和“应用软件”两部分
系统软件:操作系统语言处理程序,数据库管理系统
应用软件:各种管理软件,用于工程计算的软件包,辅助设计软件
4)通常把未配置任何软件的计算机称为“裸机”
5)操作系统可以被看作是计算机系统的核心,统管整个系统资源,制定各种资源的分配策略,调度系统中运行的用户程序,协调它们对资源的需求,从而使整个系统在高效、有序的环境里工作。
6)发展的动力:
(1) 提高计算机资源的利用率的需要
(2) 方便用户使用计算机的需要
(3) 硬件技术不断发展的需要
(4) 计算机体系结构发展的需要
7)操作系统是在“裸机”上加载的第一层软件,是对计算机硬件系统功能的首次扩充
8)操作系统的定义:
操作系统是控制和管理计算机硬件和软件资源,合理地组织计算机工作流程,以及方便用户使用计算机的一个大型程序
9)操作系统的功能:
Ø 处理机管理:进程控制,进程同步,进程通信、调度、实施CPU分配
Ø 存储器管理:内存分配,内存保护,地址映射,内存扩充
Ø 设备管理:缓冲管理,设备分配,设备管理
Ø 文件管理:存储空间管理,目录管理,读写管理和保护
Ø 与用户有关的接口:用户接口,程序接口,人机交互
10)操作系统另一种定义:操作系统是一组能有效地组织和管理计算机硬件和软件资源,合理地对各类作业进行调度,以及方便用户使用的程序的集合
操作系统的种类:
1) 单道批处理系统
特点:单路性、独占性、自动性、封闭性、顺序性
缺点:系统的资源得不到充分的利用
2) 多道批处理系统
特点:多路性、共享性、自动型、封闭性、无序性、调度性
好处:
ü 提高CPU的利用率
ü 提高内存和I/O设备的利用率
ü 增加系统吞吐量
缺点:平均周转时间长,无交互能力
3) 分时系统
分时系统是指在一台主机上连接了多个配有显示器和键盘的终端,由此所组成的系统,该系统允许多个用户同时通过自己的终端,以交互方式使用计算机,共享主机中的资源。
采用了“时间片轮转”的处理机调度策略
4) 实时系统
实时系统是指系统能及时响应外部事件的请求,在规定的时间内完成对该事件的处理,并控制所有实时任务协调一致地运行
第二章 处理机管理
1) 进程是指在系统中能独立运行并作为资源分配的基本单位,它是由一组机器指令,数据和堆栈等组成的,是一个能独立运行的活动实体,多个进程可以并发执行和交换信息
2) 程序是一个在时间上严格有序的指令集合
3) 在单道程序设计下,系统具有的特点
a. 资源的独占性
b. 执行的顺序性
c. 结果的再现性
在多道程序设计环境下,系统具有:
a. 执行的并发性
b. 相互的制约性
c. 状态的多变性(不可再现性)
5) 并发、并行、串行
a. 从宏观上看是并行,同时在内存的多个程序都在执行着,互不影响
b. 从微观上看是串行,由于CPU在任何时刻只能执行一个程序,因此这些程序轮流占用CPU,交替执行着
c. 我们把“逻辑上相互独立的程序,在执行时间上相互重叠,一个程序的执行还没有结束,另一个程序的执行已经开始”的这种特性称为程序执行的并发性
6) 对进程的描述
a. 进程是程序的一次执行过程
b. 进程的运行活动是建立在某个数据集合上的
c. 进程是在获得资源的基础上从事自己的运行活动
7) 进程的特征
结构特征、动态性、并发性、独立性、异步性
进程是一个动态的概念
不同进程可以执行同一个程序
每一个进程都有自己的生命周期
进程之间具有并发性,进程间会相互制约
8) 程序和进程的区别
a. 程序是指令的有序集合,是静态的,进程是程序在处理机上的一次执行过程,是动态的。程序的存在时永久的,而进程是有生命周期的,它因创建而产生,因调度而运行,因撤销而消亡
b. 进程是程序的一次执行过程,程序是进程赖以存在的基础
c. 进程具有并发性,而程序并发执行会失去可再现性
d. 进程是系统分配和调度的独立单位,进程由程序、数据集合和进程控制块组成
9) 系统进程的使用级别高于用户进程
10) 进程的状态
创建、就绪、运行、阻塞
a. 一个进程从运行状态变为就绪状态,一定会引起另一个进程从就绪变为运行
b. 一个进程从运行状态变为阻塞状态,一定会引起另一个进程从运行状态变为就绪状态;这种因果变迁绝对不可能发生,因为一个CPU不可能真正同时运行两个进程
c. 一个进程从阻塞状态变为就绪状态,不一定会引起另一个进程从就绪状态变为运行状态
11) 进程的三个组成部分:程序、数据集合、进程控制块(PCB)
12) 进程控制块是进程存在的唯一标示
a. 作用:通过PCB,是原来不能独立运行的程序,成为一个可以独立运行的基本单位,一个能够并发执行的进程
b. 其中的信息:进程标识符、处理机状态、进程调度信息、进程控制信息
13) 操作系统中把做出“决定把CPU分配给谁用”的程序称为“进程调度程序”
14) 常用的进程调度算法:
a. 先来先服务调度算法
b. 时间片轮转调度算法:为就绪队列中的每一个进程分配一个称为“时间片”的时间段,它是允许该进程占用CPU的最长时间长度
c. 优先数调度算法:优先数高的先调度,若相同则先来先服务
d. 多级队列调度算法:时间片调度和优先数调度算法的结合
15) 进程调度程序的主要功能
a. 记录系统中所有进程的有关情况,比如进程的当前状态,优先数等
b. 确定分配处理机的算法
c. 完成处理机的分配
d. 完成处理机的回收
16) 把处理剂分配给进程后,还有一个允许它占用多长时间的问题,有两种处理方式,一种是不可剥夺方式,另一种是剥夺方式
17) 为了对进程进行有效的管理和控制,操作系统要提供若干基本的操作以便能创建进程、撤销进程、阻塞进程、唤醒进程,把具有这种特性的程序称为“原语”,原语的不可分割性,通常利用屏蔽中断的方法
18) 程序接口:操作系统在程序一级给予用户的支持
命令接口:操作系统在控制一级给予用户的支持
19) CPU指令系统中的指令分为两类
a. 操作系统和用户都能使用的指令,非特权指令
b. 只能由操作系统使用的指令,特权指令
20) CPU的两种工作状态:管态、目态
a. 当CPU处于管态时,可以执行包括特权指令在内的一切机器指令
b. 当CPU处于目态时,禁止使用特权指令
21) 访管指令
系统调用命令的程序属于操作系统,它应该在管态下执行
用户程序只有通过计算机系统提供的访管指令才能实现由目态转为管态,进而调用这些功能程序的目的
访管指令属于非特权指令,功能是执行它就会产生一个软中断,促使中央处理机由目态转为管态,进入操作系统并处理该中断
22) 从功能上看,可以把系统调用命令分为五大类:
a. 一是关于进程管理和控制的
b. 二是关于外部设备输入/输出的
c. 三是关于磁盘文件管理的
d. 四是关于访问系统信息的
e. 五是关于存储申请与释放的
23) 从形式上看,操作系统提供的系统调用与一般的过程调用(子程序调用)相似,但它们有着明显 的区别
作业管理:
1) 把一个作业提交给系统时,系统要开辟一个作业控制块JCB,以便随时记录作业的信息
2) 被系统接纳的作业,在没有投入运行之前,称为后备作业。这些作业存放在辅助存储器中,并由他们的JCB连接在一起,形成所谓的后备作业队列
3) 作业调度:按照某种规则,从后备作业队列中挑选作业进入内存,参与处理机的竞争,这个过程称为作业调度
4) 作业的状态:
a. 提交状态:进入辅助存储器,作业的信息还没有全部进入系统,系统也没有为它建立JCB,感知不到它的存在
b. 后备状态:建立起了JCB,并将JCB排到后备作业队列中
c. 运行状态:(阻塞、运行、就绪)都属于运行状态
d. 完成状态:也是一个暂时性的状态
5) 作业的调度算法:
a. 先来先服务:以作业进入后备作业队列的先后次序
周转时间=完成时间-到达时间
注:若分配一定的内存,且不允许作业在内存中移动时,要考虑所占内存大小
b. 短作业优先:从后备作业队列中挑选所需CPU时间最少且资源能够得到满足的作业
注:如果所有作业“同时”到达后备作业队列,那么采用短作业优先的作业调度算法总会获得最小的平均周转时间
c. 响应比高着优先:先调度响应比高着
响应比=已等待时间/所需CPU时间
6) 在确定作业调度算法时应注意的问题:
a. 公平对待后备作业队列中的每一个作业,避免无故或无限期的延迟一个作业的执行,使各类用户感到满意
b. 使进入内存的多个作业,能均衡地使用系统中的资源,避免出现有的资源没有作业使用,有的资源却被多个作业争抢的“忙闲”不均的情况
c. 力争在单位时间内为尽可能多的作业提供服务,提高整个系统的吞吐能力
第三章 存储管理
1) 计算机操作系统的存储器:CPU寄存器,主存,辅存
2) 在考虑计算机存储器的设计时,必须顾及
a. 价格、容量、访问时间
b. 存取时间越快,价格越高,容量越小
3) 高速缓存:介于寄存器和存储器之间的存储器,主要用于备份主存中较常用的数据,以减少处理机对主存储器的访问次数,提高程序执行速度
高速缓存容量远大于寄存器,比内存约小两到三个数量级左右
为了缓和内存与处理机(CPU)速度的不匹配
4) 字(字长):一次传送数据的长度{16、32、64…}依系统而定
(主)内存储器和高速缓存之间是以“块”为单位传递数据的
高速缓存与CPU之间则以“字”为单位传递数据
5) 存储器管理的功能:
a. 内存的分配与回收
b. 存储的保护和共享
c. 地址定位
d. 存储扩充
6) 内存储器由一个个存储单元组成,一个存储单元可存放若干个二进制的位(bit),8个二进制位被称为一个字节(byte)
7) 在操作系统中,把用户程序指令中的相对地址变为所在绝对地址空间中的绝对地址的这个过程,称为地址重定位
8) 地址的定位方式:
a. 绝对定位方式:是在程序装入内存之前,程序指令中的地址就已经是绝对地址,已经正确地反映了它将要进入的存储区的位置,不适用于多道程序设计环境
b. 静态重定位(多道程序环境下)
根据内存的具体情况将装入模块装入到内存的适当位置,会使装入模块中的所有逻辑地址与实际装入内存后的物理地址不同。
这种地址重定位是在程序执行前完成的
c. 动态重定位
将地址重定位的时间推迟到程序执行时再进行
所以装入内存的所有地址都仍是逻辑地址
连续分配存储方式 :
1) 单一连续分配(静态重定位)
a. 单道程序环境下,总体上把内存储器分为两个分区:系统区和用户区
b. 系统总是把整个用户区分配给一个用户使用,把分配给了用户但未被使用的区域称为“内部碎片”
c. 单一连续分区存储管理的缺点:
a) 由于每次只能有一个进入内存,故它不适用于多道程序设计,工作效率不高,资源利用率低
b) 只要作业比用户区小,在用户区里就会形成碎片,造成资源浪费
c) 大作业无法在小内存中运行
d. 为缓解大作业小内存的情况提出覆盖技术和对换技术
a) 覆盖技术:允许一个作业的若干个程序段使用同一个存储区
b) 对换技术:以辅助存储器作为内存的后援(硬盘)
2) 固定分区存储管理(静态):分区数目、大小固定
a. 预先把内存储器中可供分配的用户区划分成若干个连续分区,每个分区的尺寸可以相同,可以不同。每个分区中只允许装入一个作业运行,系统可以为每一个分区设置一个后备作业队列,一个作业到达时,总是进入到“能容纳该作业的最小分区”的那个后备队列中去排队
b. 分区的分配与释放方案:
a) 在队列中挑选出第一个可容纳的作业进入
i. 优点:选择效率高
ii. 缺点:小作业->大内存
b) 在这个队列中进行搜索,找到这个分区能够容纳的最大的那个作业,让它进入运行
i. 优点:存储空间利用率高,产生内部碎片尽可能的小
ii. 缺点:选择效率低
c) 在系统中至少保留一个小的分区,以避免因为运行小作业而被迫分配打分去的发生
d) 为具体管理各个分区,并建立一个“分区分配表”,其中包括每个分区的起始位置大小及状态
c. 特点
a) 它是最简单的,具有“多道”色彩的存储管理方案,提高资源利用率
b) 当把一个分区分配给某个作业时,该作业的程序将一次性的全部装入到分配给他的连续分区里
c) 静态重定位,在分区内的程序不能随意移动
d. 缺点
a) 进入分区的作业尺寸不见得与分区的长度相吻合,势必产生内部碎片,引起资源的浪费
b) 如果到达作业的尺寸比任何一个分区的长度都大,它就无法运行
3) 可变分区存储管理:
分区的边界划分随作业的需求可变,分区的数目随着进入作业的多少可变,消灭了内部碎片(可能会产生内部碎片)。
外部碎片是指无法分配给用户使用的存储区
a. 基本思想:在作业要求装入内存储器时,如果当时内存储器中有足够的存储空间满足该作业的需求,就划分出一个与作业相对地址空间同样大小的分区,并分配给它
b. 要解决的问题
a) 采用一种新的地址重定位技术,动态地址重定位,以便程序能够在内存储器中随意移动,为空闲区的合并提供保证
b) 记住系统中各个分区的使用情况
c) 给出分区分配算法
c. 地址动态重定位过程(在程序执行时动态完成)
a) 为实施地址动态重定位,硬件要增加一个地址转换机构,这个机构一般由地址转换线路和一个定位寄存器(基址寄存器)组成
b) 地址的静态重定位和动态重定位的比较
i. 地址转换时刻:静态重定位是在程序运行之前完成地址转换的,而动态重定位是在程序执行时完成
ii. 谁来完成任务:静态重定位是由软件完成地址转换工作的,而动态重定位则是由一套硬件提供的地址转换机构来完成
iii. 完成的形式:静态重定位是在装入时一次性集中地把程序指令中所有要转换的地址加以转换;而动态重定位则是每执行一条执行时,就对其地址加以转换
iv. 完成的结果:实施静态重定位,原来的指令地址部分被修改了,而动态重定位只是按照所形成的地址去执行这条指令,并不对指令本身做任何修改
d. 空闲区的合并
e. 分区的管理
a) 表格法:一张已分配表,一张空闲表(分区号,分区大小,分区起始地址、状态)
b) 单链表法:一个存放该分区的长度,另一个存放它下一个空闲分区的起始地址
c) 双链表法:还存放上一个空闲区起始地址
f. 空闲分区的分配算法
a) 最先适应算法:要求空闲分区链以地址递增的次序链接(对大作业不利)
b) 最佳适应算法:每次为作业分配内存时,总是把能满足要求,又是最小的空闲分区分配给作业,避免“大材小用” 按其容量
c) 最坏适应算法:挑选一个最大的空闲区,从中分割一部分存储空间给作者使用,以至于存储器中缺乏大的空闲分区,照顾中小作业的需求
d) 循环首次适应算法:从上次分配的位置之后开始查找
g. 可变分区存储管理的特点
a) 作业一次性的全部装入到一个连续的存储分区中
b) 分区是按照作业对存储的需求划分的,所以不会出现内部碎片
c) 为了确保作业能够在内存中移动,要有硬件的支持,实行指令地址的动态重定位
h. 缺点:
a) 仍然没有解决小内存裕兴大作业的问题,只要作业的存储需求大于系统提供的整个用户区,该作业就无法投入运行
b) 虽然避免了内部碎片,但有可能出现极小的翻去暂时分配不出去的情形,引起了外部碎片,
c) 为了形成大的分区,可变分区存储管理通过移动程序来达到分区合并的目的,然而程序的移动是很花费时间的,增加了系统在这方面的投入与开销
4) 分页式存储管理:
需要两次访问内存,目的是提高内存利用率
a. 分页式储存管理是将固定分区方法与动态重定位技术结合在一起,需要硬件支持
基本思想:首先把整个内存储器划分成大小相等的许多分区,每个分区称为“一块”
b. 在分页式存储管理中,块是存储分配的单位
a) 用户作业仍然是相对于“0”进行编址,形成一个连续的相对地址空间
b) 用户程序相对地址空间中的每一个分区被称为“页”,用户相对地址空间中的每一个相对地址,都可以用(页号,页内位移)这样的数对来表示
i. 物理地址=页的大小*页号+页内位移
ii. 页号=相对地址/块尺寸
iii. 页内位移=相对地址%块尺寸
c. 页与块对应关系表称为“页表”
a) 快速寄存器组单独起名为“相联寄存器”,简称“快表”
b) 快表与页表联合工作,先查找快表,若无再查找页表并把数据写入快表
c) (访问页表时间+访问一次内存时间)*命中率+访问快表时间*命中率=平均内存存取时间
d) 页面尺寸大多选在512byte到64kb之间
d. 特点:
a) 内存储器实现被划分成相等尺寸的块,它是进行存储分配的单元
b) 用户作业的相对地址空间按照块的尺寸划分成页,这是在系统内部进行的,用户感觉不到
c) 相对地址空间中的页可以进入内存中的任何一个空闲块,并且分页式存储管理实行的是动态重定位,因此它打破了一个作业必须占据连续的存储空间的限制,作业在不连续的存储区里,也能够得到正确的运行
e. 缺点:
a) 平均每一个作业要浪费半页大小的存储块,会产生内部碎片
b) 作业虽然可以不占据连续的存储区,但是每次仍然要求一次全部进入内存。因此,如果作业很大,其存储需求大于内存,仍然存在小内存不能运行大作业的问题
5) 分段式存储管理:
a. 目的:方便用户使用编程,存储共享,存储保护,动态增长,动态链接
b. 要求用户将自己的整个作业程序以多个相互独立的称为“段”的地址空间提交给系统,每个段都是一个从“0”开始的一维地址空间,长度不一,操作系统按照段长为作业分配内存空间
c. 段表:段号、段长、该段在内存的基址(起始地址){段号,段内位移}
a) 物理地址=段的起始地址+段内地址
b) 逻辑地址=段号+段内地址
d. 分段与分页的区别:
a) 页是信息的物理单位,段是信息的逻辑单位
i. 分页提高内存的利用率,仅仅是系统管理上的需要,用户不可见。段是信息的逻辑单位,它通常包括的是一组意义相对完整的信息,分段段的目的主要在于能更好地满足用户的需要
b) 页的尺寸由系统决定,段的尺寸因段而异
i. 段的长度取决于用户编写的程序,通常由编译程序在对源程序进行编译时根据信息的性质来划分
c) 页的地址空间是一维的,段的地址空间是二维的
i. 分页:用户必须通过链接编辑程序,把各程序段链接成一个相对于0编址的线性空间,程序中是通过地址编号来确定空间中的位置的。因此用户向系统提供的是一个一维的逻辑地址空间。
ii. 分段:用户不把各程序段链接成一个相对于0进行编制的一维线性空间,各程序段之间是通过{段号,段内位移}进行访问的。因此,用户向系统提供的是一个二维的逻辑地址空间
6) 段页式存储管理:(三次访问内存)
a. 基本原理:分段和分页原理的结合,即先将用户程序分成若干个段,再把每个段分成若干个页,并为每一个段赋予一个段名。
a) 作业地址空间结构:主程序段,子程序段,数据段
b) 地址结构:段号,段内页号,页内地址
b. 系统设置了位示图、段表和页表,记录主存的使用情况和作业分配情况
a) 逻辑地址=段号+页号+页内位置
b) 块号*块长+页内地址
c. 虚拟存储器:是具有请求调入功能和置换功能,能从逻辑上对内存容量加以扩充的一种存储器系统,其逻辑容量由内存容量和外存容量之和所决定,其运行速度接近于内存速度。
a) 特征:多次性、对换性、虚拟性、离散性
d. 请求分页式存储管理(需要硬件支持)
a) 是基于分页式存储管理的一种虚拟存储器
“请求分页式”是指当程序运行中需要某一页时,再把它从辅助存储器里调入内存使用,解决了小内存与大作业的矛盾,但会产生内部碎片
b) 缺页中断是指在指令执行期间,若发现所要访问的指令或数据不在内存时,便立即产生和处理缺页中断信号,以便能及时将所缺之页面调入内存
e. 缺页中断与一般中断的区别 {缺页中断率=缺页次数/页面总数}
a) 缺页中断是在执行一条指令中间时产生的中断,并立即去处理,一般中断则是一条指令执行完毕后,当发现有中断请求时,才去响应和处理
b) 缺页中断处理完成后,仍返回到原指令去执行,因为那条指令并未执行;而一般中断则是到下一条指令去执行,因为上一条指令已经执行完毕了
f. 影响缺页中断次数的因素:
a) 分配给作业的内存块数
b) 页面尺寸
c) 程序的实现
7) 页面淘汰(置换)算法:
页面淘汰是由缺页中断引起的,但缺页中断不见得一定引起页面淘汰
a. 先进先出页面淘汰(置换)算法(FIFO)
淘汰最先进入内存的页面 (3个内存块都为空,3次缺页中断)
b. 最近最久未用页面淘汰(置换)算法(LRU)
总是把最长时间未被访问过的页面淘汰出去 (需要寄存器和栈)
c. 最近最少用页面淘汰(置换)算法(LFU)
总是把当前使用的最少的页面淘汰出去
为每个内存中的页面设置一个计数器(移位寄存器) 加1
d. 最优(最佳)页面淘汰(置换)算法(OPT)
把以后不再使用的或最长时间内不会用到的页面淘汰出去(理论上,不会实现)
注:对于FIFO页面淘汰算法,有时增加分配给作业的可用内存块数,它的缺页次数反而上升,通常称为异常现象
第四章 设备管理
1.“设备”泛指计算机系统中的各种外部设备,外设(即主机以外的其他所有设备)在众多的I/O设备中,并不是所有的设备都是可以共享的,可以借助于磁盘,把只能独享的设备变为共享,这就是所谓的“虚拟设备” {SPOOLing技术}
2.设备是指计算机中用以在机器之间进行传送和接收信息,完成用户输入/输出(I/O)操作的那些部件。比如磁盘、磁带、打印机、显示器、鼠标、键盘······
3.计算机I/O系统的组织结构:
(1)底层是具体的设备和硬件接口
(2)中间是系统软件(与设备相关软件、与设备无关软件)
(3)用户程序
4.I/O设备一般是由执行I/O操作的机械部分和执行控制I/O的电子部件组成
(1)执行I/O操作的机械部分就是一般的I/O设备
(2)执行控制I/O的电子部件称为设备控制器或适配器
① 为了能够使CPU设备控制器中的各个寄存器进行通信,通常采用“单独的I/O空间”和“内存映射I/O”两种方法
② 设备控制器是CPU与外围设备之间的接口,是一个可编址设备,每一个地址对应一个设备
功能:
Ø 接收和识别命令
Ø 数据交换
Ø 标识和报告设备的状态
Ø 地址识别
Ø 数据缓冲区
Ø 差错控制
组成:
Ø 设备控制器与处理机(CPU)的接口
Ø 设备控制器与设备的接口
Ø I/O逻辑:用于实现对设备的控制
5.设备驱动程序:
6.设备处理方式:
(1)为每一类设备设置一个进程,专门用于执行这类设备的I/O操作
(2)在整个系统中设置一个I/O进程,专门用于执行系统中所有各类设备的I/O操作
(3)不设置专门的设备处理进程,而只为各类设置相应的设备驱动程序,供用户或系统进程调用
7.设备驱动程序的处理过程
(1)将抽象要求转换为具体要求
(2)对服务请求进行校验,即检查I/O请求的合法性
(3)检查设备的状态
(4)传送必要的参数
(5)启动I/O设备
(6)工作方式的设置
I/O接口程序:是操作系统中与设备无关的软件,它从上层接收用户对设备提出的I/O请求,然后负责吧I/O请求转变成所需要的I/O命令,调用具体的设备驱动程序去执行
系统都是用主设备号和次设备号组成“逻辑设备名”
操作系统提供的设备无关性的优点:
ü 方便用户
ü 提高设备的利用率
8.计算机设备的分类
(1)基于设备的从属关系
a. 系统设备(键盘、显示器、打印机、磁盘驱动)
b. 用户设备
(2)基于设备的分配特性
a. 独享设备(打印机)
b. 共享设备
c. 虚拟设备(SPOOLing技术)
(3)基于设备的工作特性
a. 输入/输出设备(字符设备)
b. 存储设备(块设备) 磁盘、磁带
(4)按信息交换的单位
a. 块设备:用于存储信息,属于结构设备。磁盘、磁带(以块为单位传送信息)
b. 字符设备:以单个字符为单位来传送信息。 键盘
9.设备管理的目标
a. 提高外部设备的利用率
b. 为用户提供便利、统一的使用界面
10.设备管理的功能
a. 提供一组I/O命令
b. 进行设备的分配和回收
c. 对缓冲区进行管理
d. 实现真正的I/O操作
11.输入输出管理步骤
(1)用户在程序中使用系统提供的输入/输出命令发出I/O请求
(2)输入输出管理程序接受这个请求
(3)“设备驱动程序”来具体完成所要求的的I/O操作
(4)实现设备中断处理程序来处理这个请求
设备的输入输出管理程序由3块内容组成:接受用户的I/O请求,组织管理输入输出进行,输入输出的善后处理
设备控制:
1) 设备控制块DCB中存放的是一台具体设备的有关信息,找到一个设备的DCB,就得到了该设备的特性,各种参数,使用情况等,所以DCB是设备管理中最重要的一条数据结构
2) 独享设备中具有排他性,只能采取“静态分配”的策略
a. 静态分配:用户作业开始之前,由系统一次分配给该作业所需的设备,控制器和通道,不会发生死锁
b. 动态分配:在进程执行过程中进行的设备分配,可能造成死锁
对独享设备采用的分配算法:
v 先来先服务
v 优先级高者先服务
3) 共享磁盘的调度
磁盘是一种典型的共享存储设备,允许多个作业进程同时使用,而不是让一个作业在整个运行期间独占。“同时使用”是指当一个作业进程暂时不用时,其他作业进程就可以使用。每一个时刻只有一个作业用
4) 调度算法
a. “先来先服务”调度算法(并不理想)(移臂调度,减少查找时间)
以I/O请求到达的先后次序作为磁盘调度的顺序
b. “最短查找时间”调度算法
把距离磁头当前位置最近的I/O请求作为下一次调度的对象
c. “电梯”调度算法(SCAN)
总是沿着此案移动臂的移动方向选择距离磁头当前位置最近的I/O请求,作为下一次调度的对象
d. “单向扫描”调度算法(循环扫描 CSCAN)
总是从0号柱面开始往里移动移动臂,遇到有I/O请求就进行处理,直到到达最后一个请求柱面,然后移动臂立即带动磁头不做任何服务地快速返回到0号柱面,开始下一次扫描
对I/O设备的控制方式(数据传输方式)
1) 程序循环测试方式(程序查询式)
是指用户进程使用start指令启动设备后,不断地执行test指令,去测试所启动设备的状态寄存器。只有在状态寄存器出现了所需要的状态后,才停止测试工作,完成输入/输出。
数据寄存器:用来存放传输的数据
状态寄存器:用来记录设备当前所处状态
2) 中断方式
所谓“中断”是一种使CPU暂时中止正在执行的程序而转去处理特殊时间的操作。
引起中断的时间称为中断源。
程序中产生的中断,由CPU的某些错误结果(如,计算机溢出)产生的中断称为“内中断”,由外部设备控制器引起的中断称为“外中断”
3) 直接存储器存取方式(DMA方式)
特点:能使I/O设备直接和内存储器进行成批数据的快速传输。(单位:块数据)
DMA控制器包括四个寄存器:数据寄存器,状态寄存器,地址寄存器,字节计数器
DMA控制器的组成:主机与DMA控制器的接口;DMA控制器与块设备的接口;I/O控制逻辑
4) 通道方式
通道方式能够使CPU彻底从I/O中解放出来。CPU进行善后处理和启动。
通道是一个独立于CPU的,专门用来管理输入/输出操作的处理机。
通道是通过执行通道程序并与设备控制器共同实现对I/O设备的控制的。
它规定了设备应该执行的各种操作的顺序。由一系列通道指令所构成,CPU对I/O请求只去做启动和善后处理工作,输入/输出的管理以及数据传输等事宜,全部由通道独立完成。
缓冲:
1) 原因:
a. 缓和CPU与I/O设备间速度不匹配的矛盾
b. 减少对CPU的中断频率,放宽对CPU中断响应时间的限制
c. 解决数据粒度不匹配的问题
d. 提高CPU和I/O设备之间的并行性
2) 缓冲的实现
a. 采用专门的硬件寄存器,比如设备控制器里的数据寄存器,“硬件缓冲”
b. 在内存储器中开辟出n个单元,作为专用的I/O缓冲区,以便存放输入/输出的数据,这种缓冲区就是“软件缓冲”
c. 根据缓冲区的个数:单缓冲区、双缓冲区、多缓冲区、缓冲池
3) 虚拟设备
a. 通过多道程序技术可将一台物理CPU虚拟为多台逻辑CPU,需要硬件的支持。作为后援的硬盘(大容量),具有设备与CPU并行工作的能力
4) SPOOLing技术
a. 在主机的直接控制下,实现以前的脱机输入/输出功能,此时的外围操作与CPU对数据的处理同时进行,我们把这种在联机情况下实现的同时外围操作的技术称为SPOOLing技术,或假脱机技术
b. SPOOLing技术是对脱机输入/输出系统的模拟。SPOOLing系统建立在通道技术和多道程序技术的基础上,以高速随机外存(通常为磁盘)为后援存储器
5) 设备无关性:
应用程序中所用的设备,不局限于使用某个具体的物理设备。为每个设备所配置的设备驱动程序是与硬件紧密相关的软件。为了实现设备独立性,必须再在设备驱动程序上设置一层软件,称为与设备无关的I/O软件或设备独立性软件
6) 操作系统中实现虚拟设备的软件功能模块由3部分组成
a. 预输入程序
b. 缓输出程序
c. 井管理程序
7) SPOOLing系统由四部分组成
a. 输入井和输出井
在磁盘上开辟出来的两个存储区域,输入数据,输出数据
b. 输入缓冲区和输出缓冲区
在内存中开辟的两个缓冲区
c. 输入进程和输出进程
模拟外围控制机
d. 井管理程序
特点:
Ø 提高了I/O的速度
Ø 将独占设备改造为共享设备
Ø 实现了虚拟设备的功能
第五章 文件管理
1) 目标:提高外存储空间的利用率
主要任务:对用户文件和系统文件进行管理,方便用户使用,并保证文件的安全性
文件存储设备是以块为单位进行管理的
2) 所谓“文件”是指具有完整逻辑意义的一组相关信息的集合,它是在磁盘上保存信息,而且能方便以后读取的方法,文件用符号名加以标识,这个符号名就被称为“文件名”
3) 文件是指由创建者所定义的,具有文件名的一组相关元素的集合,可分为有结构文件和无结构文件两种。在有结构的文件中,文件由若干个相关记录组成而无结构文件则被看成是一个字符流。文件在文件系统中是一个最大的数据单位,它描述了对象集
文件属性:文件类型、文件长度、文件的物理位置、文件的建立时间(最后一次的修改时间)
4) 文件名:在不同的系统之间,对文件名的规定是不同的。一个文件名是在创建该文件时由用户给出的,操作系统将向用户提供组成文件名的命名规则
5) 很多操作系统采用句点‘.’隔开成两部分的文件名形式,句点之前的部分称为文件名,句点后面的部分称为文件的“扩展名”。又称后缀名,用于指示文件的类型
.bak 备份文件 .bas ABSIC源程序 .bin 可执行的二进制文件
.c C源程序 .dat 数据文件 .doc 文档文件
.hlp 帮助文件 .obj 目标文件 .pas Pascal文件
.txt 一般文本文件 .tmp 临时文件
1) 文件被存在大容量的辅助存储器(外存)中,当用户需要使用时,就通过文件名把相应的文件读到内存
2) “文件系统”是指操作系统中与文件管理有关的那部分软件,被管理的文件,以及管理文件所需要的数据结构(目录、索引表······)的总体
3) 对文件的分类
a. 按文件的性质和用途:系统文件、用户文件、库文件
b. 按文件中数据的形式:源文件、目标文件、可执行文件
c. 按存取控制属性分类:只执行文件、只读文件、读写文件
d. 按文件的保护性质:只读文件、读写文件、可执行文件、不保护文件
e. 按文件的保护期限:临时文件、档案文件、永久文件
f. 按文件的存取方式:顺序存取文件、随机存取文件
g. 按设备的类型:磁盘文件、磁带文件、打印文件
h. 按文件的物理结构:连续文件、链接文件、索引文件
i. 按文件的内容(组织形式和处理方式):普通文件、目录文件、特殊文件
j. 按文件的逻辑结构:流式文件、记录式文件
4) 文件的逻辑结构
a. 从用户使用的角度出发组织的文件,被称为是文件的逻辑结构,一类是有结构的文件,这是指由一个以上的记录构成的文件,故又称为记录式文件
b. 从文件的组织方式来分,可以分为顺序文件,索引文件,索引顺序文件
c. UNIX操作系统总是以流失作为文件的逻辑结构
5) 文件的物理结构
a. 文件按不同的组织方式在辅存上存放,就会得到不同的物理结构,文件的物理结构有时也称为文件的“存储结构”
b. 文件在辅存(外存)上可以有3种不同的存放方式:连续存放、链接块存放以及索引表存放
c. 对应地文件就有3种物理结构,分别叫做顺序结构,链接结构和索引结构,也叫作连续文件,串联文件,索引文件
6) 存放方式
a. 连续存放—连续文件
不足之处:
v 必须预先知道文件的最大长度
v 会造成磁盘碎片
b. 链接块存放—串联文件
不会因为磁盘碎片而浪费存储空间,但使用的指针要占去一些字节,每个磁盘块存储数据的字节数不再是2的幂,从而降低了系统的运行效率
c. 索引表存放—索引文件
7) 文件的存取
a. 顺序存取
b. 随机存取
8) 磁盘空间的管理
a. 磁盘是以块为单位进行分配的
b. 磁盘与内存之间是以磁盘块为信息传输的单位
c. 选定了块的大小,还要对它们进行管理,即要记住哪些已经分配,哪些仍然空闲。
d. 常采用的磁盘存储空间管理方案有:位示图,空闲块表,空闲块链
9) 文件的操作:
创建文件、删除文件、打开文件、关闭文件、读文件、写文件
10) 系统是通过文件的目录来管理文件的
文件目录也是一种数据结构,用于标识系统中的文件及其物理地址
11) 为每一个文件开辟一个存储区,在它的里面记录着该文件的有关信息。
我们把该存储区称为“文件控制块”(FCB) 也是一个目录项
随系统的不同,一个文件的FCB中所包含的内容及大小也不尽相同
包含内容:
Ø 文件名称
Ø 文件在辅存中存放的物理位置
Ø 文件的逻辑结构
Ø 文件的物理结构
Ø 文件的存取控制信息
Ø 文件管理信息
12) 目录的层次结构
如果把所有文件的FCB都登记在一个文件目录中,这样由文件名查文件目录项,直接就能够找到所需要的文件,那么就成这种文件目录为一级目录结构
a) 优点:
i. 简单,能实现目录管理中最基本的功能—按名存取
b) 缺点:
i. 查找速度慢,不允许重名,不便于实现文件共享
二级目录结构:
由“主目录”与“用户目录”二级构成,在主目录(根目录)中,每个目录项的内容只是给出文件主名以及它的目录所在的磁盘地址。在一个个用户目录中,才是由问价的呢FCB组成的目录,用户目录,实际上就是一级目录
1) 两级目录结构的优点:
a. 提高了检索目录的速度
b. 在不同的文件目录中,可以使用相同的文件名
c. 不同用户还可使用不同的文件名访问系统中的同一个共享文件
2) 缺点:
a. 若一个用户可以拥有很多文件,则查找时间仍然很长
b. 用户无法对自己的文件进行再分类安排
3) 树型目录结构
允许每个用户可以拥有多个目录,即在用户目录的下面可以再分子目录,子目录的下面还可以再有子目录。但每个文件目录中,只能有一个根目录,每个文件和每个目录都只能有一个父目录
4) 从根目录出发到具体文件所经过的各层名字,就构成了文件的“路径名”,从根目录出发的这个路径名,也称为文件的“绝对路径名”。
文件的绝对路径名必须从根目录出发,且是唯一的,从分隔符开头
在UNIX系统中,路径名各部分之间是用“/”分隔
在MS-DOS系统中,路径各部分是用“\”分隔
在MVLTICS系统中,路径各部分之间是用“>”分隔
在当前目录下的文件的路径名,称为文件的相对路径名
5) 文件的“共享”是指一个文件可以被多个授权用户共同使用
分两种:
Ø 任何时刻只允许一个用户使用共享文件
Ø 允许多个用户同时使用同一个共享文件,只进行读操作
第六章 进程间的制约关系
1) 在多道程序设计环境下,进程程序的执行具有并发性,在相同的前提条件下,两次执行的结果有可能不相同,使得一个进程对另一个进程的影响无法预测,在操作系统里把这种由于时间因素的影响而产生的错误称为:“与时间有关的错误”
2) 进程间具有两种制约关系:互斥和同步
a. 由于对共享资源的争夺,导致进程之间出现互斥关系
b. 由于对任务的协调工作,导致进城之间出现同步关系
3) 把那些可以共享的资源(文件、队列、缓冲区、表格、变量······)统称为共享变量或临界资源
与一个共享变量(或共享资源)交往的多个进程,为了保证它们各自运行结果的正确性,当其中的一个进程正在对该变量(临界资源)进行操作时,就不允许其他进程同时对它操作。进程的这种制约关系被称为“互斥”
4) 注意(互斥进程)
a. 作为具有互斥关系的进程,它的一部分程序可能用于内部的计算以及内部的数据处理等,那么只有设计共享变量的那一部分程序,才真正需要保证互斥地执行,把进程程序中“真正需要保证互斥执行”的那一段程序(或在每个进程中访问临界资源的那段代码)称为该进程的临界区(临界段)
b. 具有互斥关系的进程,并不关心对方的存在,即使对方不存在,自己也能够正确地运行
c. 具有互斥关系的那些进程程序中的临界区,虽然都是针对同一个共享变量的程序,但在其上执行的操作可以相同也可以不同
d. 进程的临界区是相对于某个共享变量而言的,不同共享变量的临界区之间,不存在互斥关系
信号量及其定义在信号量上的P、V操作:
1) 如何来保证进程在临界区执行的互斥性,由信号量及其定义在信号量上的P、V操作具体完成,但遵循如下规则
a. 如果有若干个进程希望进入临界区时,至少应该允许一个进入,而不能谁也进不去
b. 每次只允许一个进程进入临界区
c. 进入临界区的进程不能无限期地把持临界区
2) 同步
a. 需要在某些点上协调相互的动作,谁先到达谁后到达是有顺序要求的
b. 这些进程都应该了解对方的工作,对方如果不存在,或任何一方单独运行,就会出现差错
c. 一方或双方的运行会直接地依赖于对方所产生的的信息,或发出的消息
3) 一个进程运行到某一点时,除非合作进程已经完成了某种操作或发来了信息,否则就必须暂时等待那些操作的完成或信息的到来。
进程间的这种关系被称为“同步”,暂停以取得同步的那一点称为“同步点”,需要等待一个进程完成的操作或发送的信息,称为“同步条件”
4) 一个信号量的建立必须经过说明,即应该准确说明S的意义和初值(不能为负)
每个信号量都有相应的队列,在建立信号量时,队列为空
可进行原子操作 P(wait)、V(signal)操作
5) 信号量S上的P操作
① Vs = Vs-1,把当前信号量S的取值减1
② 若Vs >= 0,则调用进程继续运行,若Vs < 0,则调用进程由运行状态变为阻塞状态,到与该信号量有关的队列Vq上排队等待,直到其他进程在S上执行V操作将其释放为止
6) 信号量S上的V操作
① Vs = Vs + 1,把当前信号量S的取值加1
② 若Vs > 0,则调用进程继续执行,若Vs <= 0,则先从与该信号量有关的队列Vq上摘下一个等待进程,让它从阻塞状态变为就绪状态,到就绪队列里排队,然后调用进程继续执行
注意:
a. 设置的信号量初值一定是一个非负的整数。而运行过程中,信号量的取值就不再受“非负”所限了
b. 只要进入了P(S)或V(S),这两个动作就必须顺序地做完,中间不能被打断,为保证执行时的不可分割性,常采用关、开中断的方法来具体实现信号量上的P、V操作
c. 如果一个进程在做P操作后被阻塞,到关于信号量的队列上去排队等待,其含义是让进程的PCB到此队列上排队
7) 用P、V操作实现资源分配
做P操作即是申请一个资源,做V操作即是释放一个用完的资源
P操作后,若Vs > 0时,Vs的值就是这种资源的剩余数
若Vs < 0时,表示现在已经没有资源可以分配,申请资源的进程只能被阻塞到申请队列Vq上去排队等待,Vs的绝对值表示提出资源请求,但没有分配到资源的进程个数
V操作后,若Vs <= 0,表示申请资源的等待队列上有进程在等待该资源(表示V操作之前Vs <= -1,即至少有一个进程在队列上等待使用该资源),所以将该队列上的一个进程摘下,让它到就绪队列中排队
若Vs > 0,表示V操作之前Vs >= 0,即资源等待队列上没有进程在等待,只是收回了一个资源
1) 死锁:多个进程因竞争资源而造成的一种僵局,若无外力作用,这些进程将无法向前推进
2) 定义:即指系统中若存在一组(至少两个或以上)进程,它们中的每一个都占用了某种资源而又都在等待其中另一个所占用的资源,这种等待永远不会结束,这就是死锁
3) 产生死锁的4个必要条件
a. 互斥条件:进程对所分配的资源进行排它性使用,即在一段时间内,某资源只能被一个进程占用
b. 部分分配条件(占用并等待):进程由于申请不到所需要的资源而等待时,仍然占据着已经分配到的资源
c. 非剥夺条件:已经分配给进程的资源,别的进程不能强行夺取资源,只能被占用它的进程自己释放
d. 循环等待条件:在多个进程之间,由于资源的占有和请求关系,从而形成了一个循环等待的态势
4) 处理死锁的方法:
a. 预防死锁:破坏产生死锁的4个必要条件之一,使系统不具备产生思索的条件
b. 忽略死锁:任凭死锁出现,当系统中出现死锁时,就将系统重新启动
c. 避免死锁:在资源的动态分配过程中,用某种方法防止系统进入不安全状态,从而可以避免死锁
d. 检测死锁并恢复:在死锁发生后,采取相应措施加以恢复。如:撤销一些进程,回收它们的资源,将它们分配给已处于阻塞状态的进程,使其继续执行
5) 预防死锁:
a. 互斥条件是非共享设备所必须的,不仅不能改变,还应加以保证
b. 破坏占用并等待条件:所有进程在开始运行之前,必须一次性地申请其在整个过程中所需要的全部资源,一次性分配
c. 破坏“分剥夺条件”:当进程提出新的资源请求得不到满足时,它必须释放已经保持的所有资源,待以后需要时再重新申请
d. 破坏循环等待条件:将系统中的所有资源进行统一编号,进程按编号的顺序,由小到大提出对资源使用的申请
6) 在信号量上的P、V操作,可以看作是进程间的一种通信方式,这种通信并不在进程间真正交换信息,而只是双方事先的一种约定。因此,用P、V操作实现的通信,称为进程间的一种低级通信
为了使进程间能够真正交换数据,操作系统备有高级通信命令,提供给用户在程序一级使用
高级进程通信分为直接通信和间接通信两种方式
间接通信是指通过信箱来传递消息
一、硬盘的物理结构:
硬盘存储数据是根据电、磁转换原理实现的。硬盘由一个或几个表面镀有磁性物质的金属或玻璃等物质盘片以及盘片两面所安装的磁头和相应的控制电路组成(图1),其中盘片和磁头密封在无尘的金属壳中。
硬 盘工作时,盘片以设计转速高速旋转,设置在盘片表面的磁头则在电路控制下径向移动到指定位置然后将数据存储或读取出来。当系统向硬盘写入数据时,磁头中 “写数据”电流产生磁场使盘片表面磁性物质状态发生改变,并在写电流磁场消失后仍能保持,这样数据就存储下来了;当系统从硬盘中读数据时,磁头经过盘片指 定区域,盘片表面磁场使磁头产生感应电流或线圈阻抗产生变化,经相关电路处理后还原成数据。因此只要能将盘片表面处理得更平滑、磁头设计得更精密以及尽量 提高盘片旋转速度,就能造出容量更大、读写数据速度更快的硬盘。这是因为盘片表面处理越平、转速越快就能越使磁头离盘片表面越近,提高读、写灵敏度和速 度;磁头设计越小越精密就能使磁头在盘片上占用空间越小,使磁头在一张盘片上建立更多的磁道以存储更多的数据。
二、硬盘的逻辑结构。
硬盘由很多盘片(platter)组成,每个盘片的每个面都有一个读写磁头。如果有N个盘片。就有2N个面,对应2N个磁头(Heads),从0、1、 2开始编号。每个盘片被划分成若干个同心圆磁道(逻辑上的,是不可见的。)每个盘片的划分规则通常是一样的。这样每个盘片的半径均为固定值R的同心圆再逻 辑上形成了一个以电机主轴为轴的柱面(Cylinders),从外至里编号为0、1、2……每个盘片上的每个磁道又被划分为几十个扇区(Sector), 通常的容量是512byte,并按照一定规则编号为1、2、3……形成Cylinders×Heads×Sector个扇区。这三个参数即是硬盘的物理参 数。我们下面的很多实践需要深刻理解这三个参数的意义。
三、磁盘引导原理。
3.1 MBR(master boot record)扇区:
计算机在按下power键以后,开始执行主板bios程序。进行完一系列检测和配置以后。开始按bios中设定的系统引导顺序引导系统。假定现在是硬 盘。Bios执行完自己的程序后如何把执行权交给硬盘呢。交给硬盘后又执行存储在哪里的程序呢。其实,称为mbr的一段代码起着举足轻重的作用。 MBR(master boot record),即主引导记录,有时也称主引导扇区。位于整个硬盘的0柱面0磁头1扇区(可以看作是硬盘的第一个扇区),bios在执行自己固有的程序以 后就会jump到mbr中的第一条指令。将系统的控制权交由mbr来执行。在总共512byte的主引导记录中,MBR的引导程序占了其中的前446个字 节(偏移0H~偏移1BDH),随后的64个字节(偏移1BEH~偏移1FDH)为DPT(Disk PartitionTable,硬盘分区表),最后的两个字节“55 AA”(偏移1FEH~偏移1FFH)是分区有效结束标志。
MBR不随操作系统的不同而不同,意即不同的操作系统可能会存在相同的MBR,即使不同,MBR也不会夹带操作系统的性质。具有公共引导的特性。
我们来分析一段mbr。下面是用winhex查看的一块希捷120GB硬盘的mbr。
你的硬盘的MBR引导代码可能并非这样。不过即使不同,所执行的功能大体是一样的。这是wowocock关于磁盘mbr的反编译,已加了详细的注释,感兴趣可以细细研究一下。
我们看DPT部分。操作系统为了便于用户对磁盘的管理。加入了磁盘分区的概念。即将一块磁盘逻辑划分为几块。磁盘分区数目的多少只受限于C~Z的英文字母 的数目,在上图DPT共64个字节中如何表示多个分区的属性呢?microsoft通过链接的方法解决了这个问题。在DPT共64个字节中,以16个字节 为分区表项单位描述一个分区的属性。也就是说,第一个分区表项描述一个分区的属性,一般为基本分区。第二个分区表项描述除基本分区外的其余空间,一般而 言,就是我们所说的扩展分区。这部分的大体说明见表1。
表1 图2分区表第一字段
字节位移 字段长度 值 字段名和定义
0x01BE BYTE 0x80 引导指示符(Boot Indicator) 指明该分区是否是活动分区。
0x01BF BYTE 0x01 开始磁头(Starting Head)
0x01C0 6位 0x01 开始扇区(Starting Sector) 只用了0~5位。后面的两位(第6位和第7位)被开始柱面字段所使用
0x01C1 10位 0x00 开始柱面(Starting Cylinder) 除了开始扇区字段的最后两位外,还使用了1位来组成该柱面值。开始柱面是一个10位数,最大值为1023
0x01C2 BYTE 0x07 系统ID(System ID) 定义了分区的类型,详细定义,请参阅图4
0x01C3 BYTE 0xFE 结束磁头(Ending Head)
0x01C4 6位 0xFF 结束扇区(Ending Sector) 只使用了0~5位。最后两位(第6、7位)被结束柱面字段所使用
0x01C5 10位 0x7B 结束柱面(Ending Cylinder) 除了结束扇区字段最后的两位外,还使用了1位,以组成该柱面值。结束柱面是一个10位的数,最大值为1023
0x01C6 DWORD 0x0000003F 相对扇区数(Relative Sectors) 从该磁盘的开始到该分区的开始的位移量,以扇区来计算
0x01CA DWORD 0x00DAA83D 总扇区数(Total Sectors) 该分区中的扇区总数
注:上表中的超过1字节的数据都以实际数据显示,就是按高位到地位的方式显示。存储时是按低位到高位存储的。两者表现不同,请仔细看清楚。以后出现的表,图均同。
也可以在winhex中看到这些参数的意义:
说明: 每个分区表项占用16个字节,假定偏移地址从0开始。如图3的分区表项3。分区表项4同分区表项3。
1、0H偏移为活动分区是否标志,只能选00H和80H。80H为活动,00H为非活动。其余值对microsoft而言为非法值。
2、重新说明一下(这个非常重要):大于1个字节的数被以低字节在前的存储格式格式(little endian format)或称反字节顺序保存下来。低字节在前的格式是一种保存数的方法,这样,最低位的字节最先出现在十六进制数符号中。例如,相对扇区数字段的值 0x3F000000的低字节在前表示为0x0000003F。这个低字节在前的格式数的十进制数为63。
3、系统在分区时,各分区都不允许跨柱面,即均以柱面为单位,这就是通常所说的分区粒度。有时候我们分区是输入分区的大小为7000M,分出来却是 6997M,就是这个原因。 偏移2H和偏移6H的扇区和柱面参数中,扇区占6位(bit),柱面占10位(bit),以偏移6H为例,其低6位用作扇区数的二进制表示。其高两位做柱 面数10位中的高两位,偏移7H组成的8位做柱面数10位中的低8位。由此可知,实际上用这种方式表示的分区容量是有限的,柱面和磁头从0开始编号,扇区 从1开始编号,所以最多只能表示1024个柱面×63个扇区×256个磁头×512byte=8455716864byte。即通常的8.4GB(实际上 应该是7.8GB左右)限制。实际上磁头数通常只用到255个(由汇编语言的寻址寄存器决定),即使把这3个字节按线性寻址,依然力不从心。 在后来的操作系统中,超过8.4GB的分区其实已经不通过C/H/S的方式寻址了。而是通过偏移CH~偏移FH共4个字节32位线性扇区地址来表示分区所 占用的扇区总数。可知通过4个字节可以表示2^32个扇区,即2TB=2048GB,目前对于大多数计算机而言,这已经是个天文数字了。在未超过 8.4GB的分区上,C/H/S的表示方法和线性扇区的表示方法所表示的分区大小是一致的。也就是说,两种表示方法是协调的。即使不协调,也以线性寻址为 准。(可能在某些系统中会提示出错)。超过8.4GB的分区结束C/H/S一般填充为FEH FFH FFH。即C/H/S所能表示的最大值。有时候也会用柱面对1024的模来填充。不过这几个字节是什么其实都无关紧要了。
虽然现在的系统均采用线性寻址的方式来处理分区的大小。但不可跨柱面的原则依然没变。本分区的扇区总数加上与前一分区之间的保留扇区数目依然必须是柱面容 量的整数倍。(保留扇区中的第一个扇区就是存放分区表的MBR或虚拟MBR的扇区,分区的扇区总数在线性表示方式上是不计入保留扇区的。如果是第一个分 区,保留扇区是本分区前的所有扇区。
附:分区表类型标志如图4
3.2 扩展分区:
扩展分区中的每个逻辑驱动器都存在一个类似于MBR的扩展引导记录( Extended Boot Record, EBR),也有人称之为虚拟mbr或扩展mbr,意思是一样的。扩展引导记录包括一个扩展分区表和该扇区的标签。扩展引导记录将记录只包含扩展分区中每个 逻辑驱动器的第一个柱面的第一面的信息。一个逻辑驱动器中的引导扇区一般位于相对扇区32或63。但是,如果磁盘上没有扩展分区,那么就不会有扩展引导记 录和逻辑驱动器。第一个逻辑驱动器的扩展分区表中的第一项指向它自身的引导扇区。第二项指向下一个逻辑驱动器的EBR。如果不存在进一步的逻辑驱动器,第 二项就不会使用,而且被记录成一系列零。如果有附加的逻辑驱动器,那么第二个逻辑驱动器的扩展分区表的第一项会指向它本身的引导扇区。第二个逻辑驱动器的 扩展分区表的第二项指向下一个逻辑驱动器的EBR。扩展分区表的第三项和第四项永远都不会被使用。
通过一幅4分区的磁盘结构图可以看到磁盘的大致组织形式。如图5:
关于扩展分区,如图6所示,扩展分区中逻辑驱动器的扩展引导记录是一个连接表。该图显示了一个扩展分区上的三个逻辑驱动器,说明了前面的逻辑驱动器和最后一个逻辑驱动器之间在扩展分区表中的差异。
除了扩展分区上最后一个逻辑驱动器外,表2中所描述的扩展分区表的格式在每个逻辑驱动器中都是重复的:第一个项标识了逻辑驱动器本身的引导扇区,第二个项 标识了下一个逻辑驱动器的EBR。最后一个逻辑驱动器的扩展分区表只会列出它本身的分区项。最后一个扩展分区表的第二个项到第四个项被使用。
表2 扩展分区表项的内容
扩展分区表项 分区表项的内容
第一个项 包括数据的开始地址在内的与扩展分区中当前逻辑驱动器有关的信息
第二个项 有关扩展分区中的下一个逻辑驱动器的信息,包括包含下一个逻辑驱动器的EBR的扇区的地址。如果不存在进一步的逻辑驱动器的话,该字段不会被使用
第三个项 未用
第四个项 未用
扩展分区表项中的相对扇区数字段所显示的是从扩展分区开始到逻辑驱动器中第一个扇区的位移的字节数。总扇区数字段中的数是指组成该逻辑驱动器的扇区数目。总扇区数字段的值等于从扩展分区表项所定义的引导扇区到逻辑驱动器末尾的扇区数。
有时候在磁盘的末尾会有剩余空间,剩余空间是什么呢?我们前面说到,分区是以1柱面的容量为分区粒度的,那么如果磁盘总空间不是整数个柱面的话,不够一个 柱面的剩下的空间就是剩余空间了,这部分空间并不参与分区,所以一般无法利用。照道理说,磁盘的物理模式决定了磁盘的总容量就应该是整数个柱面的容量,为 什么会有不够一个柱面的空间呢。在我的理解看来,本来现在的磁盘为了更大的利用空间,一般在物理上并不是按照外围的扇区大于里圈的扇区这种管理方式,只是 为了与操作系统兼容而抽象出来CHS。可能其实际空间容量不一定正好为整数个柱面的容量吧。
四、FAT分区原理。
先来一幅结构图:
现在我们着重研究FAT格式分区内数据是如何存储的。FAT分区格式是MICROSOFT最早支持的分区格式,依据FAT表中每个簇链的所占位数(有关概念,后面会讲到)分为fat12、fat16、fat32三种格式"变种",但其基本存储方式是相似的。
仔细研究图7中的fat16和fat32分区的组成结构。下面依次解释DBR、FAT1、FAT2、根目录、数据区、剩余扇区的概念。提到的地址如无特别提示均为分区内部偏移。
4.1 关于DBR.
DBR区(DOS BOOT RECORD)即操作系统引导记录区的意思,通常占用分区的第0扇区共512个字节(特殊情况也要占用其它保留扇区,我们先说第0扇)。在这512个字节 中,其实又是由跳转指令,厂商标志和操作系统版本号,BPB(BIOS Parameter Block),扩展BPB,os引导程序,结束标志几部分组成。 以用的最多的FAT32为例说明分区DBR各字节的含义。见图8。
图8的对应解释见表3
单击此处查看PDF版全文
表3 FAT32分区上DBR中各部分的位置划分
字节位移 字段长度 字段名 对应图8颜色
0x00 3个字节 跳转指令
0x03 8个字节 厂商标志和os版本号
0x0B 53个字节 BPB
0x40 26个字节 扩展BPB
0x5A 420个字节 引导程序代码
0x01FE 2个字节 有效结束标志
图9给出了winhex对图8 DBR的相关参数解释:
根据上边图例,我们来讨论DBR各字节的参数意义。
MBR将CPU执行转移给引导扇区,因此,引导扇区的前三个字节必须是合法的可执行的基于x86的CPU指令。这通常是一条跳转指令,该指令负责跳过接下来的几个不可执行的字节(BPB和扩展BPB),跳到操作系统引导代码部分。
跳转指令之后是8字节长的OEM ID,它是一个字符串, OEM ID标识了格式化该分区的操作系统的名称和版本号。为了保留与MS-DOS的兼容性,通常Windows 2000格式化该盘是在FAT16和FAT32磁盘上的该字段中记录了“MSDOS 5.0”,在NTFS磁盘上(关于ntfs,另述),Windows 2000记录的是“NTFS”。通常在被Windows 95格式化的磁盘上OEM ID字段出现“MSWIN4.0”,在被Windows 95 OSR2和Windows 98格式化的磁盘上OEM ID字段出现“MSWIN4.1”。
接下来的从偏移0x0B开始的是一段描述能够使可执行引导代码找到相关参数的信息。通常称之为BPB(BIOS Parameter Block),BPB一般开始于相同的位移量,因此,标准的参数都处于一个已知的位置。磁盘容量和几何结构变量都被封在BPB之中。由于引导扇区的第一部 分是一个x86跳转指令。因此,将来通过在BPB末端附加新的信息,可以对BPB进行扩展。只需要对该跳转指令作一个小的调整就可以适应BPB的变化。图 9已经列出了项目的名称和取值,为了系统的研究,针对图8,将FAT32分区格式的BPB含义和扩展BPB含义释义为表格,见表4和表5。
表4 FAT32分区的BPB字段
字节位移 字段长度(字节) 图8对应取值 名称和定义
0x0B 2 0x0200 扇区字节数(Bytes Per Sector) 硬件扇区的大小。本字段合法的十进制值有512、1024、2048和4096。对大多数磁盘来说,本字段的值为512
0x0D 1 0x08 每簇扇区数 (Sectors Per Cluster),一簇中的扇区数。由于FAT32文件系统只能跟踪有限个簇(最多为4 294 967 296个),因此,通过增加每簇扇区数,可以使FAT32文件系统支持最大分区数。一个分区缺省的簇大小取决于该分区的大小。本字段的合法十进制值有1、 2、4、8、16、32、64和128。Windows 2000的FAT32实现只能创建最大为32GB的分区。但是,Windows 2000能够访问由其他操作系统(Windows 95、OSR2及其以后的版本)所创建的更大的分区
0x0e 2 0x0020 保留扇区数(Reserved Sector) 第一个FAT开始之前的扇区数,包括引导扇区。本字段的十进制值一般为32
0x10 1 0x02 FAT数(Number of FAT) 该分区上FAT的副本数。本字段的值一般为2
0x11 2 0x0000 根目录项数(Root Entries)只有FAT12/FAT16使用此字段。对FAT32分区而言,本字段必须设置为 0
0x13 2 0x0000 小扇区数(Small Sector)(只有FAT12/FAT16使用此字段)对FAT32分区而言,本字段必须设置为0
0x15 1 0xF8 媒体描述符( Media Descriptor)提供有关媒体被使用的信息。值0xF8表示硬盘,0xF0表示高密度的3.5寸软盘。媒体描述符要用于MS-DOS FAT16磁盘,在Windows 2000中未被使用
0x16 2 0x0000 每FAT扇区数(Sectors Per FAT)只被FAT12/FAT16所使用,对FAT32分区而言,本字段必须设置为0
0x18 2 0x003F 每道扇区数(Sectors Per Track) 包含使用INT13h的磁盘的“每道扇区数”几何结构值。该分区被多个磁头的柱面分成了多个磁道
0x1A 2 0x00FF 磁头数(Number of Head) 本字段包含使用INT 13h的磁盘的“磁头数”几何结构值。例如,在一张1.44MB 3.5英寸的软盘上,本字段的值为 2
0x1C 4 0x0000003F 隐藏扇区数(Hidden Sector) 该分区上引导扇区之前的扇区数。在引导序列计算到根目录的数据区的绝对位移的过程中使用了该值。本字段一般只对那些在中断13h上可见的媒体有意义。在没有分区的媒体上它必须总是为0
0x20 4 0x007D043F 总扇区数(Large Sector) 本字段包含FAT32分区中总的扇区数
0x24 4 0x00001F32 每FAT扇区数(Sectors Per FAT)(只被FAT32使用)该分区每个FAT所占的扇区数。计算机利用这个数和 FAT数以及隐藏扇区数(本表中所描述的)来决定根目录从哪里开始。该计算机还可以从目录中的项数决定该分区的用户数据区从哪里开始
0x28 2 0x00
扩展标志(Extended Flag)(只被FAT32使用)该两个字节结构中各位的值为:
位0-3:活动 FAT数(从0开始计数,而不是1).
只有在不使用镜像时才有效
位4-6:保留
位7:0值意味着在运行时FAT被映射到所有的FAT
1值表示只有一个FAT是活动的
位8-15:保留
0x2A 2 0x0000 文件系统版本(File ystem Version)只供FAT32使用,高字节是主要的修订号,而低字节是次要的修订号。本字段支持将来对该FAT32媒体类型进行扩展。如果本字段非零,以前的Windows版本将不支持这样的分区
0x2C 4 0x00000002 根目录簇号(Root Cluster Number)(只供FAT32使用) 根目录第一簇的簇号。本字段的值一般为2,但不总是如此
0x30 2 0x0001 文件系统信息扇区号 (File System Information SectorNumber)(只供FAT32使用) FAT32分区的保留区中的文件系统信息(File System Information, FSINFO)结构的扇区号。其值一般为1。在备份引导扇区(Backup Boot Sector)中保留了该FSINFO结构的一个副本,但是这个副本不保持更新
0x34 2 0x0006 备份引导扇区(只供FAT32使用) 为一个非零值,这个非零值表示该分区保存引导扇区的副本的保留区中的扇区号。本字段的值一般为6,建议不要使用其他值
0x36 12 12个字节均为0x00 保留(只供FAT32使用)供以后扩充使用的保留空间。本字段的值总为0
表5 FAT32分区的扩展BPB字段
字节位移 字段长度(字节) 图8对应取值 字段名称和定义
0x40 1 0x80 物理驱动器号( Physical Drive Number) 与BIOS物理驱动器号有关。软盘驱动器被标识为0x00,物理硬盘被标识为0x80,而与物理磁盘驱动器无关。一般地,在发出一个INT13h BIOS调用之前设置该值,具体指定所访问的设备。只有当该设备是一个引导设备时,这个值才有意义
0x41 1 0x00 保留(Reserved) FAT32分区总是将本字段的值设置为0
0x42 1 0x29 扩展引导标签(Extended Boot Signature) 本字段必须要有能被Windows 2000所识别的值0x28或0x29
0x43 4 0x33391CFE 分区序号(Volume Serial Number) 在格式化磁盘时所产生的一个随机序号,它有助于区分磁盘
0x47 11 "NO NAME" 卷标(Volume Label) 本字段只能使用一次,它被用来保存卷标号。现在,卷标被作为一个特殊文件保存在根目录中
0x52 8 "FAT32" 系统ID(System ID) FAT32文件系统中一般取为"FAT32"
DBR的偏移0x5A开始的数据为操作系统引导代码。这是由偏移0x00开始的跳转指令所指向的。在图8所列出的偏移0x00~0x02的跳转指令"EB 58 90"清楚地指明了OS引导代码的偏移位置。jump 58H加上跳转指令所需的位移量,即开始于0x5A。此段指令在不同的操作系统上和不同的引导方式上,其内容也是不同的。大多数的资料上都说win98, 构建于fat基本分区上的win2000,winxp所使用的DBR只占用基本分区的第0扇区。他们提到,对于fat32,一般的32个基本分区保留扇区 只有第0扇区是有用的。实际上,以FAT32构建的操作系统如果是win98,系统会使用基本分区的第0扇区和第2扇区存储os引导代码;以FAT32构 建的操作系统如果是win2000或winxp,系统会使用基本分区的第0扇区和第0xC扇区(win2000或winxp,其第0xC的位置由第0扇区 的0xAB偏移指出)存储os引导代码。所以,在fat32分区格式上,如果DBR一扇区的内容正确而缺少第2扇区(win98系统)或第0xC扇区 (win2000或winxp系统),系统也是无法启动的。如果自己手动设置NTLDR双系统,必须知道这一点。
DBR扇区的最后两个字节一般存储值为0x55AA的DBR有效标志,对于其他的取值,系统将不会执行DBR相关指令。上面提到的其他几个参与os引导的扇区也需以0x55AA为合法结束标志。
FAT16 DBR:
FAT32中DBR的含义大致如此,对于FAT12和FAT16其基本意义类似,只是相关偏移量和参数意义有小的差异,FAT格式的区别和来因,以后会说 到,此处不在多说FAT12与FAT16。我将FAT16的扇区参数意义列表。感兴趣的朋友自己研究一下,和FAT32大同小异的。
表6 一个FAT16分区上的引导扇区段
字节位移 字段长度(字节) 字段名称
0x00 3 跳转指令(Jump Instruction)
0x03 8 OEM ID
0x0B 25 BPB
0x24 26 扩展BPB
0x3E 448 引导程序代码(Bootstrap Code)
0x01FE 4 扇区结束标识符(0x55AA)
表7 FAT16分区的BPB字段
字节位移 字段长度(字节) 例值 名称和定义
0x0B 2 0x0200 扇区字节数(Bytes Per Sector) 硬件扇区的大小。本字段合法的十进制值有512、1024、2048和4096。对大多数磁盘来说,本字段的值为512
0x0D 1 0x40 每簇扇区数 (Sectors Per Cluster) 一个簇中的扇区数。由于FAT16文件系统只能跟踪有限个簇(最多为65536个)。因此,通过增加每簇的扇区数可以支持最大分区数。分区的缺省的簇的大 小取决于该 分区的大小。本字段合法的十进制值有 1、2、4、8、16、32、64和128。导致簇大于32KB(每扇区字节数*每簇扇区数)的值会引起磁盘错误和软件错误
0x0e 2 0x0001 保留扇区数(Reserved Sector) 第一个FAT开始之前的扇区数,包括引导扇区。本字段的十进制值一般为1
0x10 1 0x02 FAT数(Number of FAT)该分区上FAT的副本数。本字段的值一般为2
0x11 2 0x0200 根目录项数 (Root Entries) 能够保存在该分区的根目录文件夹中的32个字节长的文件和文件夹名称项的总数。在一个典型的硬盘上,本字段的值为512。其中一个项常常被用作卷标号 (Volume Label),长名称的文件和文件夹每个文件使用多个项。文件和文件夹项的最大数一般为511,但是如果使用的长文件名,往往都达不到这个数
0x13 2 0x0000 小扇区数(Small Sector) 该分区上的扇区数,表示为16位(<65536)。对大于65536个扇区的分区来说,本字段的值为0,而使用大扇区数来取代它
0x15 1 0xF8 媒体描述符( Media Descriptor)提供有关媒体被使用的信息。值0xF8表示硬盘,0xF0表示高密度的3.5寸软盘。媒体描述符要用于MS-DOS FAT16磁盘,在Windows 2000中未被使用
0x16 2 0x00FC 每FAT扇区数(Sectors Per FAT) 该分区上每个FAT所占用的扇区数。计算机利用这个数和FAT数以及隐藏扇区数来决定根目录在哪里开始。计算机还可以根据根目录中的项数(512)决定该 分区的用户数据区从哪里开始
0x18 2 0x003F 每道扇区数(Sectors Per Trark)
0x1A 2 0x0040 磁头数(Number of head)
0x1C 4 0x0000003F 隐藏扇区数(Hidden Sector) 该分区上引导扇区之前的扇区数。在引导序列计算到根目录和数据区的绝对位移的过程中使用了该值
0x20 4 0x003EF001 大扇区数(Large Sector) 如果小扇区数字段的值为0,本字段就包含该FAT16分区中的总扇区数。如果小扇区数字段的值不为0,那么本字段的值为0
表8 FAT16分区的扩展BPB字段
字节位移 字段长度(字节) 图8对应取值 字段名称和定义
0x24 1 0x80 物理驱动器号( Physical Drive Number) 与BIOS物理驱动器号有关。软盘驱动器被标识为0x00,物理硬盘被标识为0x80,而与物理磁盘驱动器无关。一般地,在发出一个INT13h BIOS调用之前设置该值,具体指定所访问的设备。只有当该设备是一个引导设备时,这个值才有意义
0x25 1 0x00 保留(Reserved) FAT16分区一般将本字段的值设置为0
0x26 1 0x29 扩展引导标签(Extended Boot Signature) 本字段必须要有能被Windows 2000所识别的值0x28或0x29
0x27 2 0x52368BA8 卷序号(Volume Serial Number) 在格式化磁盘时所产生的一个随机序号,它有助于区分磁盘
0x2B 11 "NO NAME" 卷标(Volume Label) 本字段只能使用一次,它被用来保存卷标号。现在,卷标被作为一个特殊文件保存在根目录中
0x36 8 "FAT16" 文件系统类型(File System Type) 根据该磁盘格式,该字段的值可以为FAT、FAT12或FAT16
4.2 关于保留扇区
在上述FAT文件系统DBR的偏移0x0E处,用2个字节存储保留扇区的数目。所谓保留扇区(有时候会叫系统扇区,隐藏扇区),是指从分区DBR扇区开始 的仅为系统所有的扇区,包括DBR扇区。在FAT16文件系统中,保留扇区的数据通常设置为1,即仅仅DBR扇区。而在FAT32中,保留扇区的数据通常 取为32,有时候用Partition Magic分过的FAT32分区会设置36个保留扇区,有的工具可能会设置63个保留扇区。
FAT32中的保留扇区除了磁盘总第0扇区用作DBR,总第2扇区(win98系统)或总第0xC扇区(win2000,winxp)用作OS引导代码扩 展部分外,其余扇区都不参与操作系统管理与磁盘数据管理,通常情况下是没作用的。操作系统之所以在FAT32中设置保留扇区,是为了对DBR作备份或留待 以后升级时用。FAT32中,DBR偏移0x34占2字节的数据指明了DBR备份扇区所在,一般为0x06,即第6扇区。当FAT32分区DBR扇区被破 坏导致分区无法访问时。可以用第6扇区的原备份替换第0扇区来找回数据。
4.3 FAT表和数据的存储原则。
FAT表(File Allocation Table 文件分配表),是Microsoft在FAT文件系统中用于磁盘数据(文件)索引和定位引进的一种链式结构。假如把磁盘比作一本书,FAT表可以认为相当 于书中的目录,而文件就是各个章节的内容。但FAT表的表示方法却与目录有很大的不同。
在FAT文件系统中,文件的存储依照FAT表制定的簇链式数据结构来进行。同时,FAT文件系统将组织数据时使用的目录也抽象为文件,以简化对数据的管理。
★存储过程假想:
我们模拟对一个分区存储数据的过程来说明FAT文件系统中数据的存储原则。
假定现在有一个空的完全没有存放数据的磁盘,大小为100KB,我们将其想象为线形的空间地址。为了存储管理上的便利,我们人为的将这100KB的空间均 分成100份,每份1KB。我们来依次存储这样几个文件:A.TXT(大小10KB),B.TXT(大小53.6KB),C.TXT(大小 20.5KB)。
最起码能够想到,我们可以顺序的在这100KB空间中存放这3个文件。同时不要忘了,我们还要记下他们的大小和开始的位置,这样下次要用时才能找的到,这 就像是目录。为了便于查找,我们假定用第1K的空间来存储他们的特征(属性)。还有,我们设计的存储单位是1KB,所以,A.TXT我们需要10个存储单 位(为了说明方便,我们把存储单位叫做“簇”吧。也能少打点字,呵呵。),B.TXT需要54个簇,C.TXT需要21个簇。可能有人会说B.TXT和 C.TXT不是各自浪费了不到1簇的空间吗?干嘛不让他们紧挨着,不是省地方吗?我的回答是,如果按照这样的方式存储,目录中原本只需要记下簇号,现在还 需要记下簇内的偏移,这样会增加目录的存储量,而且存取没有了规则,读取也不太方便,是得不偿失的。
根据上面所说的思想,我们设计了这样的图4.3.1所示的存储方式。
我们再考虑如何来写这三个文件的目录。对于每个文件而言,一定要记录的有:文件名,开始簇,大小,创建日期、时间,修改日期、时间,文件的读写属性等。这 里大小能不能用结束簇来计算呢?一定不能,因为文件的大小不一定就是整数个簇的大小,否则的话像B.TXT的内容就是54KB的内容了,少了固然不行,可 多了也是不行的。那么我们怎么记录呢?可以想象一下。为了管理上的方便,我们用数据库的管理方式来管理我们的目录。于是我把1KB再分成10份,假定开始 簇号为0,定义每份100B的各个位置的代表含义如图4.3.2
这样设计的结构绝对可以对文件进行正确的读写了。接着让我们设计的文件系统工作吧。先改动个文件,比如A.TXT,增加点内容吧!咦?增加后往哪里放呀, 虽然存储块的后面有很多空间,但紧随其后B.TXT的数据还顶着呢?要是把A.TXT移到后边太浪费处理资源,而且也不一定解决问题。这个问题看来暂时解 决不了。
那我们换个操作,把B.txt删了,b.txt的空间随之释放。这时候空间如图4.3.3,目录如图4.3.4
这个操作看来还可以,我们接着做,在存入一个文件D.txt(大小为60.3KB),总共100簇的空间只用了31簇,还有68簇剩余,按说能放下。可是?往那里放呢?没有61个连续的空间了,目录行没办法写了,看来无连续块存储暂时也不行。
你一定能够想到我们可以在连续空间不够或增加文件长度的时候转移影响我们操作的其他文件,从而腾出空间来,但我要问你,那不是成天啥也不要干了,就是倒腾东西了吗?
看来我们设计的文件系统有致命的漏洞,怎么解决呢?。。。。
。。。。。。
其实可以这样解决:
首先我们允许文件的不连续存储。目录中依然只记录开始簇和文件的大小。那么我们怎么记录文件占用那些簇呢,以文件映射簇不太方便,因为文件名是不固定的。 我们换个思想,可以用簇来映射文件,在整个存储空间的前部留下几簇来记录数据区中数据与簇号的关系。对于上例因为总空间也不大,所以用前部的1Kb的空间 来记录这种对应,假设3个文件都存储,空间分配如图4.3.5,同时修改一下目录,如图4.3.6
第一簇用来记录数据区中每一簇的被占用情况,暂时称其为文件分配表。结合文件分配表和文件目录就可以达到完全的文件读取了。我们想到,把文件分配表做成一个数据表,以图4.3.7的形式记录簇与数据的对应。
用图4.3.7的组织方式是完全可以实现对文件占有簇的记录的。但还不够效率。比如文件名在文件分配表中记录太多,浪费空间,而实际上在目录中已经记录了文件的开始簇了。所以可以改良一下,用链的方式来存放占有簇的关系,变成图4.3.8的组织方式。
参照图4.3.8来理解一下文件分配表的意义。如文件a.txt我们根据目录项中指定的a.txt的首簇为2,然后找到文件分配表的第2簇记录,上面登记 的是3,我们就能确定下一簇是3。找到文件分配表的第3簇记录,上面登记的是4,我们就能确定下一簇是4......直到指到第11簇,发现下一个指向是 FF,就是结束。文件便丝毫无误读取完毕。
我们再看上面提到的第三种情况,就是将b.txt删除以后,存入一个大小为60.3KB的d.txt。利用簇链可以很容易的实现。实现后的磁盘如图4.3.9 4.3.10 4.3.11
上面是我们对文件存储的一种假设,也该揭开谜底的时候了。上面的思想其实就是fat文件系统的思想的精髓(但并不是,尤其像具体的参数的意义与我们所举的例子是完全不同的。请忘掉上边细节,努力记忆下边)。
★FAT16存储原理:
当把一部分磁盘空间格式化为fat文件系统时,fat文件系统就将这个分区当成整块可分配的区域进行规划,以便于数据的存储。一般来讲,其划分形式如图7所示。我们把FAT16部分提取出来,详细描述一下:
FAT16是Microsoft较早推出的文件系统,具有高度兼容性,目前仍然广泛应用于个人电脑尤其是移动存储设备中,FAT16简单来讲由图 4.3.11所示的6部分组成(主要是前5部分)。引导扇区(DBR)我们已经说过,FAT16在DBR之后没有留有任何保留扇区,其后紧随的便是FAT 表。FAT表是FAT16用来记录磁盘数据区簇链结构的。像前面我们说过的例子一样,FAT将磁盘空间按一定数目的扇区为单位进行划分,这样的单位称为 簇。通常情况下,每扇区512字节的原则是不变的。簇的大小一般是2n (n为整数)个扇区的大小,像 512B,1K,2K,4K,8K,16K,32K,64K。实际中通常不超过32K。 之所以簇为单位而不以扇区为单位进行磁盘的分配,是因为当分区容量较大时,采用大小为512b的扇区管理会增加fat表的项数,对大文件存取增加消耗,文 件系统效率不高。分区的大小和簇的取值是有关系的,见表9
图4.3.11 Fat16的组织形式
引导扇区 FAT1 FAT2(重复的) 根文件夹 其他文件夹及所有文件 剩余扇区
1扇区 实际情况取大小 同FAT1 32个扇区 开始簇编号(从2开始) 不足一簇
表9 FAT16分区大小与对因簇大小
分区空间大小 每个簇的扇区 簇空间大小
0MB-32MB 1 512个字节
33MB-64MB 2 1k
65MB-128MB 4 2k
129MB-225MB 8 4k
256MB-511MB 16 8k
512MB-1023MB 32 16k
1024MB-2047MB 64 32k
2048MB-4095MB 128 64k
注意:少于32680个扇区的分区中,簇空间大小可最多达到每个簇8个扇区。不管用户是使用磁盘管理器来格式化分区,还是使用命令提示行键入format 命令格式化,格式化程序都创建一个12位的FAT。少于16MB的分区,系统通常会将其格式化成12位的FAT,FAT12是FAT的初始实现形式,是针 对小型介质的。FAT12文件分配表要比FAT16和FAT32的文件分配表小,因为它对每个条目使用的空间较少。这就给数据留下较多的空间。所有用 FAT12格式化的5.25英寸软盘以及1.44MB的3.5英寸软盘都是由FAT12格式化的。除了FAT表中记录每簇链结的二进制位数与FAT16不 同外,其余原理与FAT16均相同,不再单独解释。。。
格式化FAT16分区时,格式化程序根据分区的大小确定簇的大小,然后根据保留扇区的数目、根目录的扇区数目、数据区可分的簇数与FAT表本身所占空间 来确定FAT表所需的扇区数目,然后将计算后的结果写入DBR的相关位置。
FAT16 DBR参数的偏移0x11处记录了根目录所占扇区的数目。偏移0x16记录了FAT表所占扇区的数据。偏移0x10记录了FAT表的副本数目。系统在得到这几项参数以后,就可以确定数据区的开始扇区偏移了。
FAT16文件系统从根目录所占的32个扇区之后的第一个扇区开始以簇为单位进行数据的处理,这之前仍以扇区为单位。对于根目录之后的第一个簇,系统并不 编号为第0簇或第1簇 (可能是留作关键字的原因吧),而是编号为第2簇,也就是说数据区顺序上的第1个簇也是编号上的第2簇。
FAT文件系统之所以有12,16,32不同的版本之分,其根本在于FAT表用来记录任意一簇链接的二进制位数。以FAT16为例,每一簇在FAT表中占 据2字节(二进制16位)。所以,FAT16最大可以表示的簇号为0xFFFF(十进制的65535),以32K为簇的大小的话,FAT32可以管理的最 大磁盘空间为:32KB×65535=2048MB,这就是为什么FAT16不支持超过2GB分区的原因。
FAT表实际上是一个数据表,以2个字节为单位,我们暂将这个单位称为FAT记录项,通常情况其第1、2个记录项(前4个字节)用作介质描述。从第三个记录项开始记录除根目录外的其他文件及文件夹的簇链情况。根据簇的表现情况FAT用相应的取值来描述,见表10
表10 FAT16记录项的取值含义(16进制)
FAT16记录项的取值 对应簇的表现情况
0000 未分配的簇
0002~FFEF 已分配的簇
FFF0~FFF6 系统保留
FFF7 坏簇
FFF8~FFFF 文件结束簇
看一幅在winhex所截FAT16的文件分配表,图10:
如图,FAT表以"F8 FF FF FF" 开头,此2字节为介质描述单元,并不参与FAT表簇链关系。小红字标出的是FAT扇区每2字节对应的簇号。
相对偏移0x4~0x5偏移为第2簇(顺序上第1簇),此处为FF,表示存储在第2簇上的文件(目录)是个小文件,只占用1个簇便结束了。
第3簇中存放的数据是0x0005,这是一个文件或文件夹的首簇。其内容为第5簇,就是说接下来的簇位于第5簇——〉 FAT表指引我们到达FAT表的第5簇指向,上面写的数据是"FF FF",意即此文件已至尾簇。
第4簇中存放的数据是0x0006,这又是一个文件或文件夹的首簇。其内容为第6簇,就是说接下来的簇位于第6簇——〉FAT表指引我们到达FAT表的第 6簇指向,上面写的数据是0x0007,就是说接下来的簇位于第7簇——〉FAT表指引我们到达FAT表的第7簇指向……直到根据FAT链读取到扇区相对 偏移0x1A~0x1B,也就是第13簇,上面写的数据是0x000E,也就是指向第14簇——〉14簇的内容为"FF FF",意即此文件已至尾簇。
后面的FAT表数据与上面的道理相同。不再分析。
FAT表记录了磁盘数据文件的存储链表,对于数据的读取而言是极其重要的,以至于Microsoft为其开发的FAT文件系统中的FAT表创建了一份备 份,就是我们看到的FAT2。FAT2与FAT1的内容通常是即时同步的,也就是说如果通过正常的系统读写对FAT1做了更改,那么FAT2也同样被更 新。如果从这个角度来看,系统的这个功能在数据恢复时是个天灾。
FAT文件系统的目录结构其实是一颗有向的从根到叶的树,这里提到的有向是指对于FAT分区内的任一文件(包括文件夹),均需从根目录寻址来找到。可以这样认为:目录存储结构的入口就是根目录。
FAT文件系统根据根目录来寻址其他文件(包括文件夹),故而根目录的位置必须在磁盘存取数据之前得以确定。FAT文件系统就是根据分区的相关DBR参数 与DBR中存放的已经计算好的FAT表(2份)的大小来确定的。格式化以后,跟目录的大小和位置其实都已经确定下来了:位置紧随FAT2之后,大小通常为 32个扇区。根目录之后便是数据区第2簇。
FAT文件系统的一个重要思想是把目录(文件夹)当作一个特殊的文件来处理,FAT32甚至将根目录当作文件处理(旁:NTFS将分区参数、安全权限等好 多东西抽象为文件更是这个思想的升华),在FAT16中,虽然根目录地位并不等同于普通的文件或者说是目录,但其组织形式和普通的目录(文件夹)并没有不 同。FAT分区中所有的文件夹(目录)文件,实际上可以看作是一个存放其他文件(文件夹)入口参数的数据表。所以目录的占用空间的大小并不等同于其下所有 数据的大小,但也不等同于0。通常是占很小的空间的,可以看作目录文件是一个简单的二维表文件。其具体存储原理是:
不管目录文件所占空间为多少簇,一簇为多少字节。系统都会以32个字节为单位进行目录文件所占簇的分配。这32个字节以确定的偏移来定义本目录下的一个文件(或文件夹)的属性,实际上是一个简单的二维表。
这32个字节的各字节偏移定义如表11:
表11 FAT16目录项32个字节的表示定义
字节偏移(16进制) 字节数 定义
0x0~0x7 8 文件名
0x8~0xA 3 扩展名
0xB 1 属性字节 00000000(读写)
00000001(只读)
00000010(隐藏)
00000100(系统)
00001000(卷标)
00010000(子目录)
00100000(归档)
0xC~0x15 10 系统保留
0x16~0x17 2 文件的最近修改时间
0x18~0x19 2 文件的最近修改日期
0x1A~0x1B 2 表示文件的首簇号
0x1C~0x1F 4 表示文件的长度
对图10中的一些取值进行说明:
(1)、对于短文件名,系统将文件名分成两部分进行存储,即主文件名+扩展名。 0x0~0x7字节记录文件的主文件名,0x8~0xA记录文件的扩展名,取文件名中的ASCII码值。不记录主文件名与扩展名之间的"." 主文件名不足8个字符以空白符(20H)填充,扩展名不足3个字符同样以空白符(20H)填充。0x0偏移处的取值若为00H,表明目录项为空;若为 E5H,表明目录项曾被使用,但对应的文件或文件夹已被删除。(这也是误删除后恢复的理论依据)。文件名中的第一个字符若为“.”或“..”表示这个簇记 录的是一个子目录的目录项。“.”代表当前目录;“..”代表上级目录(和我们在dos或windows中的使用意思是一样的,如果磁盘数据被破坏,就可 以通过这两个目录项的具体参数推算磁盘的数据区的起始位置,猜测簇的大小等等,故而是比较重要的)
(2)、0xB的属性字段:可以看作系统将0xB的一个字节分成8位,用其中的一位代表某种属性的有或无。这样,一个字节中的8位每位取不同的值就能反映各个属性的不同取值了。如00000101就表示这是个文件,属性是只读、系统。
(3)、0xC~0x15在原FAT16的定义中是保留未用的。在高版本的WINDOWS系统中有时也用它来记录修改时间和最近访问时间。那样其字段的意义和FAT32的定义是相同的,见后边FAT32。
(4)、0x16~0x17中的时间=小时*2048+分钟*32+秒/2。得出的结果换算成16进制填入即可。也就是:0x16字节的0~4位是以2秒为单位的量值;0x16字节的5~7位和0x17字节的0~2位是分钟;0x17字节的3~7位是小时。
(5)、0x18~0x19中的日期=(年份-1980)*512+月份*32+日。得出的结果换算成16进制填入即可。也就是:0x18字节0~4位是日期数;0x18字节5~7位和0x19字节0位是月份;0x19字节的1~7位为年号,原定义中0~119分别代表1980~2099,目前高版本的Windows允许取0~127,即年号最大可以到2107年。
(6)、0x1A~0x1B存放文件或目录的表示文件的首簇号,系统根据掌握的首簇号在FAT表中找到入口,然后再跟踪簇链直至簇尾,同时用0x1C~0x1F处字节判定有效性。就可以完全无误的读取文件(目录)了。
(7)、普通子目录的寻址过程也是通过其父目录中的目录项来指定的,与数据文件(指非目录文件)不同的是目录项偏移0xB的第4位置1,而数据文件为0。
对于整个FAT分区而言,簇的分配并不完全总是分配干净的。如一个数据区为99个扇区的FAT系 统,如果簇的大小设定为2扇区,就会有1个扇区无法分配给任何一个簇。这就是分区的剩余扇区,位于分区的末尾。有的系统用最后一个剩余扇区备份本分区的 DBR,这也是一种好的备份方法。
早的FAT16系统并没有长文件名一说,Windows操作系统已经完全支持在FAT16上的长文件名了。FAT16的长文件名与FAT32长文件名的定义是相同的,关于长文件名,在FAT32部分再详细作解释。
★FAT32存储原理:
FAT32是个非常有功劳的文件系统,Microsoft成功地设计并运用了它,直到今天NTFS铺天盖地袭来的时候,FAT32依然占据着 Microsoft Windows文件系统中重要的地位。FAT32最早是出于FAT16不支持大分区、单位簇容量大以致空间急剧浪费等缺点设计的。实际应用中,FAT32 还是成功的。
FAT32与FAT16的原理基本上是相同的,图4.3.12标出了FAT32分区的基本构成。
图4.3.12 Fat32的组织形式
引导扇区 其余保留扇区 FAT1 FAT2(重复的) 根文件夹首簇 其他文件夹及所有文件 剩余扇区
1扇区 31个扇区 实际情况取大小 同FAT1 第2簇 不足一簇
保留扇区 ┗━━━━━━━━数据区━━━━━━━━┛
FAT32在格式化的过程中就根据分区的特点构建好了它的DBR,其中BPB参数是很重要的,可以回过头来看一下表4和表5。首先FAT32保留扇区的数 目默认为32个,而不是FAT16的仅仅一个。这样的好处是有助于磁盘DBR指令的长度扩展,而且可以为DBR扇区留有备份空间。上面我们已经提到,构建 在FAT32上的win98或win2000、winXP,其操作系统引导代码并非只占一个扇区了。留有多余的保留扇区就可以很好的拓展OS引导代码。在 BPB中也记录了DBR扇区的备份扇区编号。备份扇区可以让我们在磁盘遭到意外破坏时恢复DBR。
FAT32的文件分配表的数据结构依然和FAT16相同,所不同的是,FAT32将记录簇链的二进制位数扩展到了32位,故而这种文件系统称为 FAT32。32位二进制位的簇链决定了FAT表最大可以寻址2T个簇。这样即使簇的大小为1扇区,理论上仍然能够寻址1TB范围内的分区。但实际中 FAT32是不能寻址这样大的空间的,随着分区空间大小的增加,FAT表的记录数会变得臃肿不堪,严重影响系统的性能。所以在实际中通常不格式化超过 32GB的FAT32分区。WIN2000及之上的OS已经不直接支持对超过32GB的分区格式化成FAT32,但WIN98依然可以格式化大到 127GB的FAT32分区,但这样没必要也不推荐。同时FAT32也有小的限制,FAT32卷必须至少有65527个簇,所以对于小的分区,仍然需要使 用FAT16或FAT12。
分区变大时,如果簇很小,文件分配表也随之变大。仍然会有上面的效率问题存在。既要有效地读写大文件,又要最大可能的减少空间的浪费。FAT32同样规定了相应的分区空间对应的簇的大小,见表12:
表12 FAT32分区大小与对因簇大小
分区空间大小 每个簇的扇区 簇空间大小
<8GB 8 4k
>=8GB且<16GB 16 8k
>=16GB且<32GB 32 16k
>=32GB 64 32k
簇的取值意义和FAT16类似,不过是位数长了点罢了,比较见表13:
表13 FAT各系统记录项的取值含义(16进制)
FAT12记录项的取值 FAT16记录项的取值 FAT32记录项的取值 对应簇的表现情况
000 0000 00000000 未分配的簇
002~FFF 0002~FFEF 00000002~FFFFFFEF 已分配的簇
FF0~FF6 FFF0~FFF6 FFFFFFF0~FFFFFFF6 系统保留
FF7 FFF7 FFFFFFF7 坏簇
FF8~FFF FFF8~FFFF FFFFFFF8~FFFFFFFF 文件结束簇
FAT32的另一项重大改革是根目录的文件化,即将根目录等同于普通的文件。这样根目录便没有了FAT16中512个目录项的限制,不够用的时候增加簇 链,分配空簇即可。而且,根目录的位置也不再硬性地固定了,可以存储在分区内可寻址的任意簇内,不过通常根目录是最早建立的(格式化就生成了)目录表。所 以,我们看到的情况基本上都是根目录首簇占簇区顺序上的第1个簇。在图4.3.12中也是按这种情况制作的画的。
FAT32对簇的编号依然同FAT16。顺序上第1个簇仍然编号为第2簇,通常为根目录所用(这和FAT16是不同的,FAT16的根目录并不占簇区空间,32个扇区的根目录以后才是簇区第1个簇)
FAT32的文件寻址方法与FAT16相同,但目录项的各字节参数意义却与FAT16有所不同,一方面它启用了FAT16中的目录项保留字段,同时又完全支持长文件名了。
对于短文件格式的目录项。其参数意义见表14:
表14 FAT32短文件目录项32个字节的表示定义
字节偏移(16进制) 字节数 定义
0x0~0x7 8 文件名
0x8~0xA 3 扩展名
0xB* 1 属性字节 00000000(读写)
00000001(只读)
00000010(隐藏)
00000100(系统)
00001000(卷标)
00010000(子目录)
00100000(归档)
0xC 1 系统保留
0xD 1 创建时间的10毫秒位
0xE~0xF 2 文件创建时间
0x10~0x11 2 文件创建日期
0x12~0x13 2 文件最后访问日期
0x14~0x15 2 文件起始簇号的高16位
0x16~0x17 2 文件的最近修改时间
0x18~0x19 2 文件的最近修改日期
0x1A~0x1B 2 文件起始簇号的低16位
0x1C~0x1F 4 表示文件的长度
* 此字段在短文件目录项中不可取值0FH,如果设值为0FH,目录段为长文件名目录段
说明:
(1)、这是FAT32短文件格式目录项的意义。其中文件名、扩展名、时间、日期的算法和FAT16时相同的。
(2)、由于FAT32可寻址的簇号到了32位二进制数。所以系统在记录文件(文件夹)开始簇地址的时候也需要32位来记录,FAT32启用目录项偏移0x12~0x13来表示起始簇号的高16位。
(3)、文件长度依然用4个字节表示,这说明FAT32依然只支持小于4GB的文件(目录),超过4GB的文件(目录),系统会截断处理。
FAT32的一个重要的特点是完全支持长文件名。长文件名依然是记录在目录项中的。为了低版本的OS或程序能正确读取长文件名文件,系统自动为所有长文件 名文件创建了一个对应的短文件名,使对应数据既可以用长文件名寻址,也可以用短文件名寻址。不支持长文件名的OS或程序会忽略它认为不合法的长文件名字 段,而支持长文件名的OS或程序则会以长文件名为显式项来记录和编辑,并隐藏起短文件名。
当创建一个长文件名文件时,系统会自动加上对应的短文件名,其一般有的原则:
(1)、取长文件名的前6个字符加上"~1"形成短文件名,扩展名不变。
(2)、如果已存在这个文件名,则符号"~"后的数字递增,直到5。
(3)、如果文件名中"~"后面的数字达到5,则短文件名只使用长文件名的前两个字母。通过数学操纵长文件名的剩余字母生成短文件名的后四个字母,然后加后缀"~1"直到最后(如果有必要,或是其他数字以避免重复的文件名)。
(4)、如果存在老OS或程序无法读取的字符,换以"_"
长文件名的实现有赖于目录项偏移为0xB的属性字节,当此字节的属性为:只读、隐藏、系统、卷标,即其值为0FH时,DOS和WIN32会认为其不合法而 忽略其存在。这正是长文件名存在的依据。将目录项的0xB置为0F,其他就任由系统定义了,Windows9x或Windows 2000、XP通常支持不超过255个字符的长文件名。系统将长文件名以13个字符为单位进行切割,每一组占据一个目录项。所以可能一个文件需要多个目录 项,这时长文件名的各个目录项按倒序排列在目录表中,以防与其他文件名混淆。
长文件名中的字符采用unicode形式编码(一个巨大的进步哦),每个字符占据2字节的空间。其目录项定义如表15。
表15 FAT32长文件目录项32个字节的表示定义
字节偏移
(16进制) 字节数 定义
0x0 1 属性字节位意义 7 保留未用
6 1表示长文件最后一个目录项
5 保留未用
4 顺序号数值
3
2
1
0
0x1~0xA 10 长文件名unicode码①
0xB 1 长文件名目录项标志,取值0FH
0xC 1 系统保留
0xD 1 校验值(根据短文件名计算得出)
0xE~0x19 12 长文件名unicode码②
0x1A~0x1B 2 文件起始簇号(目前常置0)
0x1C~0x1F 4 长文件名unicode码③
系统在存储长文件名时,总是先按倒序填充长文件名目录 项,然后紧跟其对应的短文件名。从表15可以看出,长文件名中并不存储对应文件的文件开始簇、文件大小、各种时间和日期属性。文件的这些属性还是存放在短 文件名目录项中,一个长文件名总是和其相应的短文件名一一对应,短文件名没有了长文件名还可以读,但长文件名如果没有对应的短文件名,不管什么系统都将忽 略其存在。所以短文件名是至关重要的。在不支持长文件名的环境中对短文件名中的文件名和扩展名字段作更改(包括删除,因为删除是对首字符改写E5H),都 会使长文件名形同虚设。长文件名和短文件名之间的联系光靠他们之间的位置关系维系显然远远不够。其实,长文件名的0xD字节的校验和起很重要的作用,此校 验和是用短文件名的11个字符通过一种运算方式来得到的。系统根据相应的算法来确定相应的长文件名和短文件名是否匹配。这个算法不太容易用公式说明,我们 用一段c程序来加以说明。
假设文件名11个字符组成字符串shortname[],校验和用chknum表示。得到过程如下:
int i,j,chknum=0;
for (i=11; i>0; i--)
chksum = ((chksum & 1) ? 0x80 : 0) + (chksum >> 1) + shortname[j++];
如果通过短文件名计算出来的校验和与长文件名中的0xD偏移处数据不相等。系统无论如何都不会将它们配对的。
依据长文件名和短文件名对目录项的定义,加上对簇的编号和链接,FAT32上数据的读取便游刃有余了
Sharing is the most beautiful and effective especially for the peaple like you and me. Please contact me if it is needed. aidon1428@hotmail.com(this address is always avalible)
什么是文件
操作系统对存储设备的物理属性加以抽象,从而定义逻辑存储单位,即文件。文件由操作系统映射到物理设备上,这些存储设备是非易失的。文件是记录在外存上的相关信息的命名组合。从用户角度来看,文件是逻辑外存的最小分配单元,也就是说,数据只有通过文件才能存储到外存。文件的类型有很多,比如文本文件为按行组着的字符序列、源文件为函数序列,每个函数包括声明和可执行语句、可执行文件为一系列代码段,以供加载程序调入内存并执行。
文件属性
为了标示文件的各种特定信息,需要文件属性来存储文件的特定信息。文件属性因操作系统而异。但是通常包括:
名称:符号文件名是以人类可读形式来保存的唯一信息
标识符:这种唯一标记标示文件系统的文件,是文件的非人类可读名称
类型:支持不同类型文件的系统需要这种信息
位置:该信息为指向设备与设备上文件位置的指针
尺寸:该属性包括文件的当前大小(以字节、字、块为单位)以及可能允许的最大尺寸
保护:访问控制信息确定谁能进行读取、写入、执行等
时间、日期和用户标识:文件创建、最后修改、最后使用的相关信息可以保存。这些数据用户保护、安全和使用监控。
有些文件系统还支持扩展文件属性,包括文件的字符编码和安全功能,如文件的校检和。所有的文件的信息保存在目录结构中,该目录结构保存在外存中。
文件操作
为了正确的定义文件,操作系统可以提供系统调用,来对文件进行:创建、写入、读取、重新定位、删除、截断文件等操作。
创建文件:创建文件需要两个步骤:
1、必须在文件系统中为文件找到空闲空间。
2、必须在目录中创建新文件的条目
写文件:使用一个系统调用指定文件名称和要写入的信息。系统搜索目录查找文件的位置。系统应保留写指针用于指向需要进行下次写操作的文件位置。
读文件:指明文件名称和需要文件的下一块该放在哪里(在内存中)。系统需要保留一个读指针指向要进行下一次读取操作的文件位置。当前操作位置可以作为进程的当前文件位置指针。读和写操作都是用相同的指针,可节省空间并降低系统复杂度。
重新定位文件:搜索目录以寻找适当的条目,并且将当前文件位置指针重新定位到给定值
删除文件:释放文件的所有文件空间,并删除指定的目录条目
截断文件:让文件重置为零,并释放它的文件空间,但是允许所有属性保持不变(除了文件长度)
在首次使用文件之前进行系统调用open(),操作系统有一个打开文件表用来维护所有打开文件的信息,open()根据文件名搜索目录,将目录条目复制到打开文件表。当文件不在使用的时候,进程关闭该文件,操作系统从打开文件表中删除它的条目。
当多个进程可以同时打开文件的环境,这可能会发生操作系统采用两级的内部表:每个进程表和整个系统表。每个进程表跟它打开的所有文件,该表存储的是进程对文件的使用信息。
单个进程表的每个条目相应的指向整个系统的打开文件表。系统表包含与进程无关的信息。系统打开文件表为每个文件关联一个打开计数,用来表示多少进程打开了这个文件。当打开计数为0时,可以从系统打开文件表中删除这个文件条目。
每个打开文爱你具有如下的关联信息:
文件指针:该指针对操作系统的每个进程是唯一的,因此必须和磁盘文件属性分开保存
文件打开计数
文件的磁盘位置
访问权限:该信息保存在进程的打开文件表中
有的操作系统提供文件锁,用于一个继承锁定文件,防止其他进程访问它。
文件锁一般有联众类型:
共享锁:类似读者锁,便于多个进程可以并发获取它
独占锁:类似写者锁,一次只有一个进程可以获得这样的锁
有的操作系统还提供强制和建议文件锁定机制。如果锁定方案是强制性的,那么操作系统确保锁定完整性;如果锁是建议的,软件开发人员应该确保适当的获取和释放锁,比如Windows采用强制锁定,而UNIX采用建议锁定。
文件类型
设计文件系统时,需要考虑系统是否应该识别和支持文件类型。如果系统识别文件的类型,则它就能按合理的方式来操作文件。一般文件名分为两部分,即名称和扩展。
UNIX系统采用位于某些文件开始部分的幻数,大致表明文件类型,不是所有问阿金都有幻数,所以系统特征不能仅仅基于这种信息。UNIX也不记录创建程序的名称。UNIX允许文件名扩展提示,但是操作系统不强制也不依赖这些扩展名;这些扩展名主要帮助用户确定吧文件内容的类型。
文件结构
文件类型也可用于指示文件的内部结构。但是操作系统支持多个文件结构会带来一个缺点:操作系统会变得太复杂。有写操作系统强加(并支持)最小数量的文件结构。UNIX认为每个文件为8位字节序列,而操作系统不必对这些位做出解释。
内部文件结构
磁盘系统通常具有明确定义的块大小,这是由扇区大小决定的。所有的磁盘I/O按块(物理记录)为单位执行,所有的块的大小相同。物理记录大小不太可能刚好匹配期望的逻辑记录的长度,逻辑记录的长度甚至可能不同。解决方法是,将多个逻辑记录包装到一个物理块中。
访问方法
顺序访问
文件的信息按顺序(即一个记录接着一个记录的)加以处理,这种访问模式是目前最常见的,比如编辑器和编译器通常以这种方式进行访问文件。
顺序访问基于文件的磁带模型,不但适用于顺序访问设备,也适用于随机访问设备。
直接访问
直接访问也称为相对访问,文件是由固定长度的逻辑记录组成的,以允许程序按任意顺序进行快速读取和写入记录。直接访问方法基于文件的磁盘模型,因为磁盘允许对任何文件块的随机访问。
对于直接访问方法,必须修改文件操作以便包括块号作为参数,read(n),其中的n就是块号。
用户提供给操作系统的块号,通常为相对块号,相对块号是相对于文件开头的索引。
目录和磁盘的结构
一个存储设备可以按整体来用于文件系统,也可以进行细分来提供更细粒度的控制。比如,一个磁盘可以划分为四个分区,每个分区可以有单独的文件系统。存储设备还可以组成RAID集,一起提供保护以免受到单个磁盘故障。包含文件系统的分区通常称为卷。卷可以是设备的一部分,或整个设备,或由多个设备组成的RAID集。包含文件西荣的每个卷也应包含有关系统内的文件信息,这些信息保存在设备目录或卷目录表中
存储结构
通用计算机系统有多个存储设备,这些存储设备可以分成保存文件系统的卷,计算机系统可能没有文件系统,也可能有多个文件系统,而且文件系统的类型可以不同。
在这里插入图片描述
一些常见的文件系统类型:
tmpfs:“临时”文件系统,是在易失性内存中创建的,当系统重启或崩溃的时候,它的内容会被擦除
objfs:“虚拟”文件系统。本质上这是一个内核接口,但是看起来像一个文件系统;它让调试器访问内核符号
ctfs:维护“合同”信息的虚拟文件系统,以管理哪些进程在系统引导时启动并且运行时必须继续运行。
lofs:“环回”文件系统,允许一个文件系统代替另一个来被访问
procfs:虚拟文件系统,将所有进程信息作为文件系统来呈现
ufs, zfs:通用文件系统
目录概述
目录可视为符号表,可将文件名称转成目录条目。常见考虑特定的目录结构的时候,需要对目录执行的操作如下:
搜索文件
创建文件
删除文件
遍历目录
重命名文件
遍历文件系统
单级目录
最容易实现的就是单级目录,所有文件都包含在同一目录中。但是当文件数量增加或系统有多个用户的时候,单级目录有重要的限制。
两级目录
为每个用户创建一个单独的目录(UFD)。同时系统有一个主文件目录(MFD),通过用户名或账户可以索引MFD,每个条目指向该用户的UFD。当用户引用特定文件时,只搜索自己的UFD。这种数据结构将一个用户和其他用户相隔离,但是当用户需要在某个任务上进行合作并且访问彼此文件时,隔离确是个缺点。
树形目录
树形目录是最常见的目录结构,有一个根目录,系统内每个文件都有唯一的路径名。目录包括一组文件和子目录,目录只不过是一个文件,但是他是按照特殊方式处理的,每个目录条目都有一位来将条目定义为文件或子目录。
无环图目录
树结构截止共享文件或目录。无环图(就是没有循环的图)允许目录共享子目录和文件。同一文件或子目录可出现在两个不同的目录中。无环图是树形目录方案的自然扩展。
在这里插入图片描述
实现共享文件和目录的方法有多个:
使用链接技术
在两个共享目录中复制有关他们的所有信息
两个条目因为复制其实是相同且相等,但是有一个问题即使在修改文件呢时要维护一致性。
实现共享目录和文件时会涉及到删除,即共享文件的分配空间何时可以被释放和重用:
当用户删除时就删除,但是这种操作可能留下悬挂指针,以指向不存在的文件
另一种删除方法是保留文件,直到它的所有引用都被删除,这时需要一种机制来确定文件的最后一个引用被删除。
在UNIX和Linux中的硬链接采用的就是第二种方法,而软链接采用的是第一种方法。
通用图目录
无环图目录保证了结构中不存在环,如果允许目录中有环,则无论从正确性和性能角度来说,同样需要避免多次搜索同一部分。如果存在环时,即使不再坑你引用一个目录或文件时,引用计数也可能不为0,这种情况下通常需要垃圾收集方案,确定何时最后引用已被删除并重新分配磁盘空间
操作系统(英语:Operating System,缩写:OS)是管理计算机硬件与软件资源的系统软件,同时也是计算机系统的内核与基石。操作系统需要处理如管理与配置内存、决定系统资源供需的优先次序、控制输入与输出设备、操作网络与管理文件系统等基本事务。操作系统也提供一个让用户与系统交互的操作界面。
操作系统的类型非常多样:Windows、Linux、Android、iOS、鸿蒙。有些操作系统集成了图形用户界面,而有些仅使用命令行界面。
操作系统理论研究者有时把操作系统分成四大部分:
驱动程序 - 最底层的、直接控制和监视各类硬件的部分,它们的职责是隐藏硬件的具体细节,并向其他部分提供一个抽象的、通用的接口。
内核 - 操作系统之最内核部分,通常运行在最高特权级,负责提供基础性、结构性的功能。
支承库 - (亦作“接口库”)是一系列特殊的程序库,它们职责在于把系统所提供的基本服务包装成应用程序所能够使用的编程接口(API),是最靠近应用程序的部分。例如,GNU C运行期库就属于此类,它把各种操作系统的内部编程接口包装成ANSI C和POSIX编程接口的形式。
外围 - 所谓外围,是指操作系统中除以上三类以外的所有其他部分,通常是用于提供特定高级服务的部件。例如,在微内核结构中,大部分系统服务,以及UNIX/Linux中各种守护进程都通常被划归此列。操作系统的分类没有一个单一的标准,可以根据工作方式分为批处理操作系统、分时操作系统、实时操作系统、网络操作系统和分布式操作系统等;根据架构可以分为单内核操作系统等;根据运行的环境,可以分为桌面操作系统,嵌入式操作系统等;根据指令的长度分为8bit, 16bit, 32bit, 64bit的操作系统。
操作系统中四大部分的不同布局,也就形成了几种整体结构的分野。常见的结构包括:简单结构、层结构、微内核结构、垂直结构、和虚拟机结构。
操作系统的分类没有一个单一的标准,可以根据工作方式分为批处理操作系统、分时操作系统、实时操作系统、网络操作系统和分布式操作系统等;根据架构可以分为单内核操作系统等;根据运行的环境,可以分为桌面操作系统,嵌入式操作系统等;根据指令的长度分为8bit, 16bit, 32bit, 64bit的操作系统。
内核结构
内核是操作系统最内核最基础的构件,其结构往往对操作系统的外部特性以及应用领域有着一定程度的影响。尽管随着理论和实践的不断演进,操作系统高层特性与内核结构之间的耦合有日趋缩小之势,但习惯上,内核结构仍然是操作系统分类之常用标准。
内核的结构可以分为单内核、微内核、超微内核、以及外核等。
单内核结构是操作系统中各内核部件杂然混居的形态,该结构产生于1960年代(亦有1950年代初之说,尚存争议),历史最长,是操作系统内核与外围分离时的最初形态。
微内核结构是1980年代产生出来的较新的内核结构,强调结构性部件与功能性部件的分离。20世纪末,基于微内核结构,理论界中又发展出了超微内核与外内核等多种结构。尽管自1980年代起,大部分理论研究都集中在以微内核为首的“新兴”结构之上,然而,在应用领域之中,以单内核结构为基础的操作系统却一直占据着主导地位。
在众多常用操作系统之中,除了QNX和基于Mach的UNIX等个别系统外,几乎全部采用单内核结构,例如大部分的Unix、Linux,以及Windows(微软声称Windows NT是基于改良的微内核架构的,尽管理论界对此存有异议)。 微内核和超微内核结构主要用于研究性操作系统,还有一些嵌入式系统使用外核。
基于单内核的操作系统通常有着较长的历史渊源。例如,绝大部分UNIX的家族史都可上溯至1960年代。该类操作系统多数有着相对古老的设计和实现(例如某些UNIX中存在着大量1970年代、1980年代的代码)。另外,往往在性能方面略优于同一应用领域中采用其他内核结构的操作系统(但通常认为此种性能优势不能完全归功于单内核结构)。
通用与专用、嵌入式
通用操作系统是面向一般没有特定应用需求的操作系统。由于没有特定的应用需求,通用操作系统为了适应更广泛的应用,需要支持更多的硬件与软件,需要针对所有的用户体验,对系统进行更新。通用操作系统是一个工程量繁重的操作系统。
实时与非实时
“实时操作系统”(Real Time OS)泛指所有据有一定实时资源调度以及通讯能力的操作系统。而所谓“实时”,不同语境中往往有着非常不同的意义。某些时候仅仅用作“高性能”的同义词。但在操作系统理论中“实时性”所指的通常是特定操作所消耗的时间(以及空间)的上限是可预知的。比如,如果说某个操作系统提供实时内存分配操作,那也就是说一个内存分配操作所用时间(及空间)无论如何也不会超出操作系统所承诺的上限。实时性在某些领域非常重要,比如在工业控制、医疗器材、影音频合成、以及军事领域,实时性都是无可或缺的特性。
常用实时操作系统有QNX、VxWorks、RTLinux等等,而Linux、多数UNIX、以及多数Windows家族成员等都属于非实时操作系统。操作系统整体的实时性通常依仗内核的实时能力,但有时也可在非实时内核上创建实时操作系统,很多在Windows上创建的实时操作系统就属于此类。
在POSIX标准中专有一系用于规范实时操作系统的API,其中包括POSIX.4、POSIX.4a、POSIX.4b(合称POSIX.4)以及POSIX.13等等。符合POSIX.4的操作系统通常被认可为实时操作系统(但实时操作系统并不需要符合POSIX.4标准)。
8位、16位、32位、64位、128位
所谓8位、16位、32位、64位、128位等术语有时指总线宽度,有时指指令宽度(在定长指令集中),而在操作系统理论中主要是指存储器定址的宽度。如果存储器的定址宽度是16位,那么每一个存储器地址可以用16个二进制位来表示,也就是说可以在64KB的范围内定址。同样道理32位的宽度对应4GB的定址范围,64位的宽度对应16 Exabyte的定址范围。存储器定址范围并非仅仅是对操作系统而言的,其他类型的软件的设计有时也会被定址范围而影响。但是在操作系统的设计与实现中,定址范围却有着更为重要的意义。
在早期的16位操作系统中,由于64KB的定址范围太小,大都都采用“段”加“线性地址”的二维平面地址空间的设计。分配存储器时通常需要考虑“段置换”的问题,同时,应用程序所能够使用的地址空间也往往有比较小的上限。
在32位操作系统中,4GB的定址范围对于一般应用程序来说是绰绰有余的,因而,通常使用一维的线性地址空间,而不使用“段”。
12月30日,腾讯QQ面向Linux用户发布QQ Linux版3.0,正式上架QQ官网。据了解,本次QQ Linux端是一次大型的版本重构及更新,基于QQNT技术架构驱动实现了全新架构,并可支持x64系统以及arm64系统。同时,基于Linux用户对QQ的使用需求,新增支持帐密登录、夜间模式、截图、表情包、群应用等特色功能,以及支持使用小世界、QQ空间、QQ邮箱等端内应用,进一步完善QQ Linux端功能及提升用户操作体验。
外观上线黑夜模式
该版本更新后支持外观跟随系统设置,默认app外观和系统外观保持一致,无需进行额外操作;同时,支持用户主动操作选择,自由切换白天或黑夜模式。
支持全局搜索
新版本下,QQ Linux可支持用户进行全局搜索,帮助用户解决了信息过多、难以立即获取所需文件或聊天记录的问题。
支持截图
截图功能也首次加入更新,支持Linux用户随心截图,保存和分享图片或文字信息,沟通更高效。
群相册及群文件
群应用方面,新增群相册及群文件,用户可轻松上传/下载图片及文件等内容,进一步提升了群聊沟通的体验。
此外,QQ Linux端还新增了表情、小世界、QQ空间等功能,丰富Linux用户的社交娱乐体验。
为了满足Linux用户工作、生活等多场景使用需求,本次QQ Linux 3.0版本针对系统外观、效率提升、生活娱乐等方面进行功能的更新和拓展,Linux用户可前往官网下载更新。
PROCESS* p_proc=proc_table;
p_proc--->ldt_sel=SELECTOR_LDT_FIRST;
//设置进程表中进程的ldt_sel,ldt_sel被赋值SELECTOR_LDT_FIRST,这个宏的定义在代码6-1-中
memcpy(&p_proc->ldts[0], &gdt[SELECTOR_KERNEL_CS >> 3], sizeof(DESCRIPTOR)); //将SELECTOR_KERNEL_CS所指的描述符拷贝到进程PCB的ldts[0]处
p_proc->ldts[0].attr1 = DA_C | PRIVILEGE_TASK << 5; // change the DPL
memcpy(&p_proc->ldts[1], &gdt[SELECTOR_KERNEL_DS >> 3], sizeof(DESCRIPTOR)); //将SELECTOR_KERNEL_DS所指的描述符拷贝到进程PCB的ldts[1]处
p_proc->ldts[1].attr1 = DA_DRW | PRIVILEGE_TASK << 5; // change the DPL
//LDT中共有两个描述符,分别被初始化为内核代码段和内核数据段,只是改变了一下DPL,以让其运行在低特权级下(2)
p_proc->regs.cs = ((8 * 0) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK; //8*0和8*1是选择子,而且是进程PCB中的LDT描述符的选择子。
//cs指向LDT中的第一个描述符 (3) 通过cs中的这个描述符跳转到内核代码段
//LDT选择子是从0开始的。一个描述符相隔8个字节,所以要乘以8
p_proc->regs.ds = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK; //根据选择子的属性确定是全局选择子还是LDT选择子。
p_proc->regs.es = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK; //本例会根据cs中的选择子自动到进程PCB中读取LDT描述符
p_proc->regs.fs = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK; //本例比较特殊的地方是进程LDT描述符在进程PCB中,没有固定的LDT段
p_proc->regs.ss = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK;
//ds,es,fs,ss指向LDT中的第二个描述符
p_proc->regs.gs = (SELECTOR_KERNEL_GS & SA_RPL_MASK) | RPL_TASK;
//gs指向显存,只是其RPL发生改变
p_proc->regs.eip = (u32)TestA;
//eip指向TestA,这表明进程将从TestA的入口地址开始运行
p_proc->regs.esp = (u32) task_stack + STACK_SIZE_TOTAL;
//esp指向单独的堆栈,堆栈大小为STACK_SIZE_TOTAL
p_proc->regs.eflags = 0x1202; // IF=1, IOPL=1, bit 2 is always 1.
//eflags=0x1202,恰巧设置了IF位,并把IOPL设为1,这样,进程就可以使用I/O指令,并且中断会在iretd执行时,被打开。
//代码中使用到的宏,基本在protect.h中
p_proc_ready = proc_table;
这里要记得把LDT跟GDT是联系在一起的,别忘了填充GDT中进程的LDT的描述符。protect.c
init_descriptor(
&gdt[INDEX_LDT_FIRST], //设置填充地址位置(GDT中的LDT描述符 )
vir2phys(seg2phys(SELECTOR_KERNEL_DS), proc_table[0].ldts), //LDT基址,这个GDT中的LDT基址指向proc_table[0].ldts (1)
LDT_SIZE * sizeof(DESCRIPTOR) - 1, //LDT大小
DA_LDT); //LDT属性
seg2phys(SELECTOR_KERNEL_DS)把段地址转换为物理地址,把DS右移几位。
vir2phys为宏定义,在protect.h中
#define vir2phys(seg_base, vir) (u32)(((u32)seg_base) + (u32)(vir))