linux 系统编程学习笔记四

文件系统
ext2文件系统


分区的格式化工具mkfs


文件系统的总体存储布局
boot block(1kb)
block group 0
              super block (超级块):描述整个分区的文件系统信息
     GDT(块组描述表group descriptor table):由块组描述符组成
     block bitmap(块位图) 用来描述整个块组中哪些块已用哪些块空闲
              inode bitmap(inode 位图):本身占一个块,每个bit表示一个inode可用
              inode table(inode 表):文件的描述信息存放在inode中,每个文件都有一个
   node,一个块组的所有inode组成inode表
                                    一个块组有多少个8kb就分配多少个inode
              data blocks(数据块):存放文件的数据
block group 1 
block group n 


文件系统中存储的最小单位是块(block)
块的大小在格式化时确定,如mke2fs 的-b参数设定的块的大小
yuezhenhua@ubuntu:/home$ ls -l
总用量 12
drwxrwxrwx  4 root       root       4096 2012-03-06 17:04 online
drwxrwxrwx  2 root       root       4096 2012-02-02 16:06 share
drwxr-xr-x 33 yuezhenhua yuezhenhua 4096 2012-12-10 20:29 yuezheULL


目录的大小都是4096的整倍,因为分区的块大小是4096,


ls -l /dev/
/*xconsole 文件的类型是p 是一个FIFO文件,不在磁盘上保存数据,*/
crw-------  1 root root           0 2012-12-12 20:05 console
/*zero的文件类型是c,表示字符设备文件,代表内核中的一个设备驱动程序,没有数据块
  1 主设备号
  5 次设备号
 */
crw-rw-rw-  1 root root      1,   5 2012-12-12 20:04 zero


创建符号链接文件
yuezhenhua@ubuntu:/opt/sdk/tc/mmap$ touch hello
yuezhenhua@ubuntu:/opt/sdk/tc/mmap$ ln -s ./hello halo
yuezhenhua@ubuntu:/opt/sdk/tc/mmap$ ls -l


/*符号链接文件halo指向hello,字节数是7,是"./hello"这7个字符*/
wxrwxrwx 1 yuezhenhua yuezhenhua    7 2012-12-12 20:22 halo -> ./hello
-rw-rw-r-- 1 yuezhenhua yuezhenhua    6 2012-12-12 20:21 hello


创建硬链接
yuezhenhua@ubuntu:/opt/sdk/tc/mmap$ ln ./hello hello2
yuezhenhua@ubuntu:/opt/sdk/tc/mmap$ ls -l


/*第二栏的数字原本是1,现在变2,ls -l第二栏的数字是硬链接数,
  表示一个文件在文件系统中有几个名字,可以保存在不同目录的数据块中,
  也保存在inode中
 */
-rw-rw-r-- 2 yuezhenhua yuezhenhua    6 2012-12-12 20:21 hello
-rw-rw-r-- 2 yuezhenhua yuezhenhua    6 2012-12-12 20:21 hello2


目录的硬链接数
/*创建目录a*/
yuezhenhua@ubuntu:/opt/sdk/tc/mmap$ mkdir a
/*创建子目录b*/
yuezhenhua@ubuntu:/opt/sdk/tc/mmap$ mkdir a/b
yuezhenhua@ubuntu:/opt/sdk/tc/mmap$ ls -ld a
/*显示结果 */
drwxrwxr-x 3 yuezhenhua yuezhenhua 4096 2012-12-12 20:33 a


yuezhenhua@ubuntu:/opt/sdk/tc/mmap$ ls -la a
/*显示结果 目录a的硬链接数是3*/
总用量 12
drwxrwxr-x 3 yuezhenhua yuezhenhua 4096 2012-12-12 20:33 .
drwxrwxr-x 3 yuezhenhua yuezhenhua 4096 2012-12-12 20:33 ..
drwxrwxr-x 2 yuezhenhua yuezhenhua 4096 2012-12-12 20: b




yuezhenhua@ubuntu:/opt/sdk/tc/mmap$ ls -la a/b
/*显示结果 b目录的硬链接数是2*/
总用量 8
drwxrwxr-x 2 yuezhenhua yuezhenhua 4096 2012-12-12 20:33 .
drwxrwxr-x 3 yuezhenhua yuezhenhua 4096 2012-12-12 20:3 ..




示例代码:
1 创建一个1MB的文件并清零
/*dd命令把一个文件的一部分拷贝成另一个文件
  if 表示输入文件
  of 表示输出文件
  count 表示拷贝多少次
  bs 表示每次拷贝多少字节
 */
yuezhenhua@ubuntu:/opt/sdk/tc/mmap$ dd if=/dev/zero of=fs count=256 bs=4k
记录了256+0 的读入
记录了256+0 的写出
1048576字节(1.0 MB)已复制,0.00396396 秒,265 M 秒


2 对fs进行格式化(把这个文件的数据块合起来看成一个1MB在磁盘分区,在这个分区上再划


分块组)


yuezhenhua@ubuntu:/opt/sdk/tc/mmap$ mke2fs fs
mke2fs 1.41.14 (22-Dec-2010)
fs is not a block special device.
无论如何也要继续? (y,n) y
文件系统标签=
操作系统:Linux
块大小=1024 (log=0)
分块大小=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
128 inodes, 1024 blocks
51 blocks (4.98%) reserved for the super user
第一个数据块=1
Maximum filesystem blocks=1048576
1 block group
8192 blocks per group, 8192 fragments per group
128 inodes per group


正在写入inode表: 完成                            
Writing superblocks and filesystem accounting information: 完成


This filesystem will be automatically checked every 34 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.


查看个块的块组和描述信息


yuezhenhua@ubuntu:/opt/sdk/tc/mmap$ dumpe2fs fs
dumpe2fs 1.41.14 (22-Dec-2010)
Filesystem volume name:   <none>
Last mounted on:          <not available>
Filesystem UUID:          08c37487-bd06-4258-bd25-d8a323914575
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      ext_attr resize_inode dir_index filetype sparse_super
Filesystem flags:         signed_directory_hash 
Default mount options:    (none)
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              128
Block count:              1024
Reserved block count:     51
Free blocks:              986
Free inodes:              117
First block:              1
Block size:               1024  # 块大小
Fragment size:            1024
Reserved GDT blocks:      3
Blocks per group:         8192
Fragments per group:      8192
Inodes per group:         128
Inode blocks per group:   16
Filesystem created:       Wed Dec 12 21:03:32 2012
Last mount time:          n/a
Last write time:          Wed Dec 12 21:03:32 2012
Mount count:              0
Maximum mount count:      34
Last checked:             Wed Dec 12 21:03:32 2012
Check interval:           15552000 (6 months)
Next check after:         Mon Jun 10 21:03:32 2013
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:         128
Default directory hash:   half_md4
Directory Hash Seed:      7fdbe0d3-0192-4f0f-b269-d7c083b305c8


#第0个块是启动块,所以group 0只占1023个块
Group 0: (Blocks 1-1023)
  主 superblock at 1, Group descriptors at 2-2
  保留的GDT块位于 3-5
  #块位图占一个块 
  Block bitmap at 6 (+5), Inode bitmap at 7 (+6)
  Inode表位于 8-23 (+7)
  986 free blocks, 117 free inodes, 2 directories
  可用块数: 38-1023
  #每8kb分配一个inode
  可用inode数: 12-128


常规文件制作而成的文件系统也可以mount到某个目录
yuezhenhua@ubuntu:/opt/sdk/tc/mmap$ sudo mount -o loop fs /mnt
[sudo] password for yuezhenhua: 
yuezhenhua@ubuntu:/opt/sdk/tc/mmap$ cd /mnt/
yuezhenhua@ubuntu:/mnt$ ls
lost+found
yuezhenhua@ubuntu:/mnt$ ls -la
总用量 17
drwxr-xr-x  3 yuezhenhua yuezhenhua  1024 2012-12-12 21:03 .
drwxr-xr-x 25 root       root        4096 2012-04-06 12:29 ..
drwx------  2 root       root       12288 2012-12-12 21:03 lost+found


文件系统在格式化之后在根目录下自动生成三个目录

..
lost+found 由e2fsck工具使用
.和..表示根目录本身


yuezhenhua@ubuntu:/$ sudo umount /mnt/


查看这个文件系统的所有字节
/*启动块*/
000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
/*超级块*/
000400   80 00 00 00      00 04 00 00      33 00 00 00          da 03 00 00
       inode count=128   block count=1024  reserved block=51   free blocks=986
000410 75 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00
000420 00 20 00 00 00 20 00 00 80 00 00 00 00 00 00 00
000430 2c 85 c8 50 01 00 22 00 53 ef 01 00 01 00 00 00
000440 a4 80 c8 50 00 4e ed 00 00 00 00 00 01 00 00 00
000450 00 00 00 00 0b 00 00 00 80 00 00 00 38 00 00 00
000460 02 00 00 00 01 00 00 00 08 c3 74 87 bd 06 42 58
000470 bd 25 d8 a3 23 91 45 75 00 00 00 00 00 00 00 00
000480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 00
0004d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0004e0 00 00 00 00 00 00 00 00 00 00 00 00 7f db e0 d3
0004f0 01 92 4f 0f b2 69 d7 c0 83 b3 05 c8 01 00 00 00
000500 00 00 00 00 00 00 00 00 a4 80 c8 50 00 00 00 00
000510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
000560 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000570 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
000800 06 00 00 00 07 00 00 00 08 00 00 00 da 03 75 00
000810 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000820 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
001800 ff ff ff ff 1f 00 00 00 00 00 00 00 00 00 00 00
001810 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
001870 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80
001880 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
*
001c00 ff 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00
001c10 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
*
002000 00 00 00 00 00 00 00 00 a4 80 c8 50 a4 80 c8 50
002010 a4 80 c8 50 00 00 00 00 00 00 00 00 00 00 00 00
002020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
/*根目录的inode 
  st_mode是以八进制表示,包含文件类型、文件权限
  
 */
002080  ed 41           e8 03 00 04 00 00 ed 83 c8 50 a4 80 c8 50
       st_mode=040755
002090 a4 80 c8 50 00 00 00 00 e8 03 03 00 02 00 00 00
0020a0 00 00 00 00 00 00 00 00 18 00 00 00 00 00 00 00
0020b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
002300 80 81 00 00 00 30 04 04 a4 80 c8 50 a4 80 c8 50
002310 a4 80 c8 50 00 00 00 00 00 00 01 00 08 00 00 00
002320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
002350 00 00 00 00 00 00 00 00 00 00 00 00 25 00 00 00
002360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
002500 c0 41 00 00 00 30 00 00 a4 80 c8 50 a4 80 c8 50
002510 a4 80 c8 50 00 00 00 00 00 00 02 00 18 00 00 00
002520 00 00 00 00 00 00 00 00 19 00 00 00 1a 00 00 00
002530 1b 00 00 00 1c 00 00 00 1d 00 00 00 1e 00 00 00
002540 1f 00 00 00 20 00 00 00 21 00 00 00 22 00 00 00
002550 23 00 00 00 24 00 00 00 00 00 00 00 00 00 00 00
002560 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
/*根目录的数据块*/
006000 02 00 00 00 0c 00 01 02 2e 00 00 00 02 00 00 00
006010 0c 00 02 02 2e 2e 00 00 0b 00 00 00 e8 03 0a 02
006020 6c 6f 73 74 2b 66 6f 75 6e 64 00 00 00 00 00 00
006030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
006400 0b 00 00 00 0c 00 01 02 2e 00 00 00 02 00 00 00
006410 f4 03 02 02 2e 2e 00 00 00 00 00 00 00 00 00 00
006420 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
006800 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00
006810 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
006c00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00
006c10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
007000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00
007010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
007400 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00
007410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
007800 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00
007810 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
007c00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00
007c10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
008000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00
008010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
008400 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00
008410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
008800 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00
008810 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
008c00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00
008c10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
009000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00
009010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
009400 00 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00
009410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
100000




debugfs 可以对文件系统作各种操作,如查看信息、恢复数据、修正文件系统中的错误
yuezhenhua@ubuntu:/opt/sdk/tc/mmap$ debugfs fs
debugfs 1.41.14 (22-Dec-2010)
debugfs:  help


显示目录的inode信息
yuezhenhua@ubuntu:/opt/sdk/tc/mmap$stat /


Inode: 2   Type: directory    Mode:  0755   Flags: 0x0
Generation: 0    Version: 0x00000000
User:  1000   Group:  1000   Size: 1024
File ACL: 0    Directory ACL: 0
Links: 3   Blockcount: 2
Fragment:  Address: 0    Number: 0    Size: 0
ctime: 0x50c880a4 -- Wed Dec 12 21:03:32 2012
atime: 0x50c883ed -- Wed Dec 12 21:17:33 2012
mtime: 0x50c880a4 -- Wed Dec 12 21:03:32 2012
BLOCKS:
(0):24
TOTAL: 1


quit退出debugfs




数据块寻址
如果一个文件有多个数据块,这些数据块可能不是边续存放,需通过其inode中的
索引项blockss查找


文件和目录操作的系统函数


stat(2)读取文件的inode,把inode中和文件属性填入一个struct_stat结构体中返回
示例代码:
stat /opt/file
查找的顺序是
读出inode中的第二项(根目录的inode),找出根目录数据块的位置
从根目录数据块中找出文件名为opt的记录,从记录中读出它的inode号
读出opt目录的inode,找出它数据块的位置
从opt目录的数据块中找出文件名为file的记录,从记录中读出它的inode号
读出file文件的inode


fstat(2)
传入一个文件描述符,传出inode信息
lstat(2)
传入路径,传出inode信息(如果文件是个符号链接文件时,返回的是文件本身的inode)


access(2) 检查执行当前进程的用户是否有权限访问某个文件
传入文件路径和要执行的访问操作(读、写、执行),取出inode中的st_mode字段,
比较访问权限,0表示允许,-1表示不允许


chmod(2)\fchmod(2) 改变文件的访问权限,修改inode中的st_mode
两函数的区别类似于stat/fstat
chmod(1)命令


chown(2)\fchown(2)\lchown(2) 改变文件的所有者和组,修改inode中的user和group字段
chwn(1)命令




utime改变文件的访问时间和修改时间,修改inode中的atime和mtime字段
touch(1)命令


truncate(2)\ftruncate(2)把文件截断成某个长度,如果新的长度比原长度长,则补0
修改inode中的block索引项和块位图中相应的bit


link(2)创建硬链接,在目录的数据块中添加一条新记录
syslink(2)创建一个符号链接,创建一个新的inode,st_mode的文件类型是符号链接
ln(1) 命令


unlink(2)删除一个链接
符号链接 释放inode和数据块,清除inode位图和块位图中相应的位
硬链接于 清除一条文件名记录
unlink(1)\rm(1)命令


rename(2)改变文件名,修改目录数据块中的文件名记录
mv(1)命令




readlink(2) 读取一个符号链接所指向的目标路径,从符号链接的inode或数据块中读出
目标路径


mkdir(2) 创建一个目录
在父目录的数据块中添加一条记录,分配新的inode和数据块.
mkdir(1)命令




rmdir(2) 删除一个目录(目录必需为空)
释放inode和数据块,清除inode位图和块位图中相应的位,
清除父目录数据块中的记录,父目录的硬链接数减1
rmdir(1)命令




opendir(3)\readdir(3)\close(3)遍历目录数据块中的记录
opendir打开一个目录,返回一个DIR *,类似于file *的名柄
closedir 关闭这个句柄,把dir *指针传给readdir读取目录数据块中的记录
每次返回一个指向struts_dirent的指针
structs_dirent结构体的定义如下
struct dirent{
ino_t d_ino; /*incode number*/
off_t d_off; /*offset to the next dirent*/
unsigned short d_reclen; /*length of this record*/
unsigned char  d_type; /*type of file*/
char           d_name; /*filename*/
};




用递归打印目录下的所有子目录和文件
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>


#define MAX_PATH 1024


/*打印目录下的所有子目录和文件*/
void dirwalk(char *dir,void (*fcn)(char *)){
char name[MAX_PATH];
struct dirent *dp;
DIR *dfd;

if((dfd=opendir(dir))==NULL){
fprintf(stderr,"dirwalk: can't open %s\n",dir);
return;
}
while((dp=readdir(dfd))!=NULL){
if(strcmp(dp->d_name,".")==0||strcmp(dp->d_name,"..")==0){
continue;
}
if(strlen(dir)+strlen(dp->d_name)+2>sizeof(name)){
fprintf(stderr,"dirwalk:name %s %s too long\n",dir,dp-


>d_name);
}else{
sprintf(name,"%s%s",dir,dp->d_name);
(*fcn)(name);
}
}
closedir(dfd);
}


void fsize(char *name){
struct stat stbuf;
if(stat(name,&stbuf)==-1){
fprintf(stderr,"fsize: can't access %s\n",name);
return;
}
if((stbuf.st_mode & S_IFMT)==S_IFDIR){
dirwalk(name,fsize);
}
printf("%8ld %s\n",stbuf.st_size,name);
}


int main(int argc,char **argv){
if(argc==1){
fsize(".");
}else{
while(--argc>0){
fsize(*++argv);
}
}
return 0;
}

posted @ 2012-12-13 21:41  retacn_yue  阅读(262)  评论(0编辑  收藏  举报