系统相关
首页 > 系统相关> > 《Linux/Unix系统编程》第七、八章学习笔记

《Linux/Unix系统编程》第七、八章学习笔记

作者:互联网

第七、八章学习笔记

文件操作

文件操作级别

文件操作分为五个级别,按照从高到低的顺序如下:

(1)硬件级别:硬件级别的文件操作包括:

(2)操作系统内核中的文件系统函数:每个操作系统内核均可为基本文件操作提供支持。

每个操作系统均可为基本文件操作提供支持。

•kumount(),kumount()•                  (mount/umount file systems)
kmkdir(),krmdir()•                   (make/remove directory)
kchair(),kgetCwd()•                   (change directory,get CWD pathname)
•klink(),kunlink()•                   (hard link/unlink files)
•kchmod(),kchown(),kutime()           (change r|w|x permissions,owner,time)
kcreat(),kopen()•                     (create/open file for R,W,RW,APPEND)
kread(),kwrite()                     (read/write opened files)
klseek(),kclose()                   •(Lseek/close file descriptors)
keymlink(),kreadlink ()•             (create/read symbolic 1ink files)•
kstat(),kfstat(),klatat()           (get file status/information)
kopendir(),kreaddir()•               (open/read directories)•

(3)系统调用:用户模式程序使用系统调用来访问内核函数。

以下程序可读取文件的第二个1024字节

#include <fcnt1.h>
int main(int argc,char *argv[]){//run as a.out filename
int fd,n;
char buf[1024];
if((fd=open(argv[1],O_RDONLY))<0)//if open() fails
exit(1);
lseek(fd,1024,SEEK_SET);//lseek to byte 1024
n = read(fd,buf,1024);//try to read 1024 bytes.
close(fd);
}

每个C语言库函数都会发出一个系统调用,使进程进程进入内核模式来执行相应的内核函数,例如open可以进入kopen()。进程结束执行内核函数的时候,会返回到用户模式,并得到所需结果。在用户模式和内核模式之间切换需要大量的操作(和时间)。内核与用户空间之间的数据传输成本昂贵。

(4)I/O库函数:系统调用何以让用户读/写多个数据块,这些数据块只是一系列字节。

为方便用户使用,C语言提供了一些列标准的I/O函数,同时提高了运行效率。除了读/写内存位置的sscanf()/sprintf()函数之外,所有其他I/O库函数都建立在系统调用之上,也就是说,他们最终会通过系统内核发出实际数据传输的系统调用。

(5)用户命令:用户可以使用Linux/Unix命令来执行文件操作。

可参考链接: Linux命令大全----常用文件操作命令_Evankaka的专栏-CSDN博客

 

 

(6)sh脚本:虽然比系统调用方便得多,但是必须要手动输入命令,如果使用的是GUI,必须拖放文件图标和点击指向设备来输入,操作烦琐且耗时。

文件I/O操作

 

 

在图7.1中,双线上半部分表示内核空间,下半部分为进程的用户空间。

低级别文件操作

分区

一个块存储设备,如硬盘、U盘、SD卡等,可以分为几个逻辑单元,称为分区。各分区均可以格式化为特定的文件系统,也可以安装在不同的操作系统上。分区表位于第一个扇区的字节偏移446(0x1BE)处,该扇区称为设备的主引导记录(MBR)

扩展类型分区(类型编号=5),每个扩展类型分区的第一个扇区是一个本地MBR。每个本地MBR在字节偏移量0x1BE处也有一个分区表,只包含两个条目。

fdisk mydisk

DOS (MBR) a 开关 可启动 标志 b 编辑嵌套的 BSD 磁盘标签 c 开关 dos 兼容性标志

常规 d 删除分区 F 列出未分区的空闲区 l 列出已知分区类型 n 添加新分区 p 打印分区表 t 更改分区类型 v 检查分区表 i 打印某个分区的相关信息

杂项 m 打印此菜单 u 更改 显示/记录 单位 x 更多功能(仅限专业人员)

脚本 I 从 sfdisk 脚本文件加载磁盘布局 O 将磁盘布局转储为 sfdisk 脚本文件

保存并退出 w 将分区表写入磁盘并退出 q 退出而不保存更改

新建空磁盘标签 g 新建一份 GPT 分区表 G 新建一份空 GPT (IRIX) 分区表 o 新建一份的空 DOS 分区表 s 新建一份空 Sun 分区表

 

格式化分区

fdisk只是将一个存储设备划分为多个分区。每个分区都有特定的文件系统类型,但是分区还不能使用。存储文件必须先为特定的文件系统准备好分区。称为格式化磁盘或磁盘分区。

 

EXT2文件系统

多年来,Linux一直使用EXT2作为默认文件系统。EXT3中增加的主要内容是一个日志文件,记录系统更改记录。日志可在文件系统崩溃时更快从错误中恢复。

struct et2_super block {
u32 s_inodes_count;       /* Inodes count */
u32 s_blocks_count;       /* Blocks count */
u32 s_r_blocks_count;     /* Reserved blocks count */
u32 s_free blocks_count;   /* Free blocks count */
u32 s_free_inodes_count;   /* Free inodes count */
u32 s_first_data_block;   /* First Data Block */
u32 s_log block_size;     /* Block size */
u32 s_log_cluster_size;   /* Al1ocation cluster size */
u32 s_blocks per_group;   /* # Blocks per group * /
u32 s_clusters per_group; /* # Fragments per group */
u32 s_inodes_per_group;   /* # Inodes per group * /
u32s_mtime;               /* Mount time * /
u32s_wtime;               /* write time */
u16s_mnt_count;           /* Mount coune* /
s16 s_max_ntcount;         /* Maximal mount count */
u16 B_magic;               /* Magic signature */
//more non-essential fields
u16 s_inode_size;         /* size of inode structure*/
}

s_first_data_block:0表示4KB块大小,1表示1KB块大小。它用于确定块组描述符的起始块,即s_first_data_block +1。 s_log_block_size确定文件块大小,为1KB*(2**s_log_block_size),例如0表示 1KB块大小,1表示2KB块大小,2表示4KB块大小,等等。最常用的块大小是用于小文件系统的1KB和用于大文件系统的4KB。 s_mnt_count:已挂载文件系统的次数。当挂载计数达到max_mount_count时,fsck会话将被迫检查文件系统的一致性。 s_magic是标识文件系统类型的幻数。EXT2/3/4文件系统的幻数是OxEF53。

struct ext2_group_dese {
u32 bg_b1ock_bitmap; //Bmap bloak number
u32 bg_inode_bitmap; //Imap block number
u32 bg_inode_table; //Inodes begin block number
u16 bg_free_blocks_count; //THESE are OBVIOUS
u16 bg_free_inodes_count;
u16 bg_used_dirs_count;
u16 bg_pad; // ignore these
u32 bg_reserved[3];
};

由于一个软盘只有1440个块,B2只包含一个块组描述符。其余的都是0。在有大量块组的硬盘上,块组描述符可以跨越多个块。块组描述符中最重要的字段是bg_block_bitmap.bg_inode_bitmap和 bg_inode_table,它们分别指向块组的块位图、索引节点位图和索引节点起始块。对于Linux格式的EXT2文件系统,保留了块3到块7。所以,bmap=8,imap=9,inode_table= 10。

 

将文件路径名转换为索引节点

各文件系统的根本问题是将文件名转换为文件系统中的文件数据结构表示形式。在EXT2/3/4文件系统中,相当于将路径名转换为文件的INODE。

 

使用系统调用进行文件操作

操作系统中,进程以两种不同模式运行:

系统调用(syscall)一种允许进程进入Kmode执行Umode不允许操作的机制。

man2子目录列出了所有系统调用手册页。手册页的SYNOPSIS(摘要)部分列出了系统调用所需的头文件。

 

系统调用必须由程序发出。

简单的系统调用:

access:检查对某个文件的权限 int access(char *pathname, int mode);chdir:更改目录 int chdir(const char *path);chmod:更改某个文件的权限 int chmod(char *path, mode_t mode) ;chown:更改文件所有人 int chown (char *name, int uid, int gid);chroot:将(逻辑)根目录更改为路径名int chroot (char *pathname) ; getcwd:获取CWD的绝对路径名char *getcwd(char *buf, int size); mkdir:创建目录 int mkdir (char *pathname, mode_t mode); rmdir:移除目录(必须为空) int rmdir(char *pathname ); link:将新文件名硬链接到旧文件名 int link (char *oldpath, char *newpath) ; unlink:减少文件的链接数;如果链接数达到0,则删除文件int unlink (char *pathname); symlink:为文件创建一个符号链接 int symlink(char *oldpath,char *newpath);rename:更改文件名称 int rename(char *oldpath, char *newpath);utime:更改文件的访问和修改时间 int utime(char *pathname, struct utimebuf *time)以下系统调用需要超级用户权限。 mount:将文件系统添加到挂载点目录上 intmount(char *specialfile, char *mountDir); umount:分离挂载的文件系统 int umount (char *dir) ; mknod:创建特殊文件

常用系统调用

stat与文件索引节点

stat与文件索引节点:

stat的工作原理:每个文件都有一个独有的索引节点数据结构,包含文件的所有信息。每对设备由主、次设备号标识,stat系统调用只是查找文件的索引节点并将信息从索引节点复制到stat结构体中。(st_dev和st_ino除外,他们分别是设备号和索引节点编号)

 

 

标签:count,文件,八章,int,文件系统,char,Unix,u32,Linux
来源: https://www.cnblogs.com/Aegon-Targaryen/p/15384221.html