参考书籍:Unix环境高级编程,深入理解计算机系统
文件系统:
一. 目录和文件
- 获取文件属性
类ls的实现 如myls
ls -i:列出文件inode
ls -n:和ls -l差不多 区别在ls-l显示username,ls -n显示userID
Linux命令问运维人员比较多,问开发人员较松
int stat(const char *pathname,struct stat *statbuf)
stat结构体中的内容:(其他参见man手册)
st_dev 包含这个文件的设备ID号
st_rdev 设备ID号
st_size 文件大小(以字节为单位)
stat命令是用stat函数封装出来的
fstat lstat
例子:计算文件长度
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
static off_t flen(const char *fname)
{
struct stat statres;
if (stat(fname, &statres) < 0)
{
perror("stat()");
exit(1);
}
return statres.st_size;
}
int main(int argc, const char *argv[])
{
if (argc < 2)
{
fprintf(stderr, "Usage...\n");
exit(1);
}
printf("%ld\n", flen(argv[1]));
return 0;
}
空洞文件:
以下程序创建一个大小为5G的空洞文件
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if (argc < 2)
{
fprintf(stderr, "Usage...\n");
exit(1);
}
int fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0)
{
perror("open");
exit(1);
}
lseek(fd, 5LL * 1024LL * 1024LL * 1024LL - 1LL, SEEK_SET);
//lseek(fd,(5*1024*1024*1024)LL,SEEK_SET); //错误方式:在C语言中像10,20这样的常数默认大小为int,而5*1024*1024*1024-1显然溢出了,这样做是先溢出丢失,然后转为long long类型,而且这样也有语法错误,编译时就会报错.
write(fd, "", 1);
close(fd);
return 0;
}
编译方式:
cc -D FILE_OFFEST_BITS=64 bigfile.c -o bigfile
使用stat命令查看的文件占用磁盘空间信息:
文件:bigfile
大小:16984 块:40 IO 块:4096 普通文件
设备:810h/2064d Inode:88396 硬链接:1
实际占用40*4K = 160K字节空间.
不同文件系统文件的存储方式不同
当将此文件移动到Windows系统下时,这个文件占用的磁盘空间大小就是5G,但这个空洞文件在Linux系统下的处理和Windows不同.Linux先记录空字节的个数,不停地读取判断是否为空,linux系统下size只是一个属性值,在磁盘中占用不一定就是size的大小.
- 文件访问权限
dcp-lsp 七种文件类型
测试文件类型:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
int filetype(const char *filename) //char型有没有符号未定义,用int
{
struct stat statres;
if (stat(filename, &statres) < 0)
{
perror("stat()");
exit(1);
}
if (S_ISREG(statres.st_mode))
return '-';
else if (S_ISDIR(statres.st_mode))
return 'd';
else if (S_ISSOCK(statres.st_mode))
return 's';
else if (S_ISLNK(statres.st_mode))
return 'l';
else if (S_ISBLK(statres.st_mode))
return 'b';
else if (S_ISCHR(statres.st_mode))
return 'c';
else if (S_ISFIFO(statres.st_mode))
return 'p';
else
return '?'; //出异常
}
int main(int argc, const char *argv[])
{
if (argc < 2)
{
fprintf(stderr, "Usage...\n");
exit(1);
}
printf("%c\n",filetype(argv[1]));
return 0;
}
st_mode是一个16位的位图,用于表示文件类型,文件访问权限,及特殊权限位。
-
umask
作用:防止产生权限过松的文件
mode_t umask(mode_t mask); -
文件权限的更改/管理
int chmod(const char *pathname, mode_t mode);
int fchmod(int fd, mode_t mode); //针对某一个成功打开的文件修改权限 -
粘住位
t位:原来是用于在内存中保存一个可执行命令/二进程程序执行的痕迹,但由于现在有cache,所有现在不常用了这个性质了,现在多用于给某一个目录进行t位的设置:
如根目录下的tmp目录
drwxrwxrwt 16 root root 94208 7月 20 16:24 tmp/
- 文件系统:FAT,UFS —涉及到深入理解计算机系统
文件系统:文件或数据的存储和管理
UFS:Unix早期文件系统 FAT:和UFS同一时期的文件系统
二者一个开源一个不开源
缺点:UFS不善于管理小文件
i位图和块位图里面的小格子都存放的0/1,
面试:巧用位图
8. 硬链接, 符号链接(不要说成软链接)
硬链接:创建的文件inode与原文件相同,Links变为2. 两个指针指向同一个数据块
硬链接与目录项是同义词,且建立硬链接有限制;不能给分区建立,不能给目录建立。符号链接优点:可跨分区,可以给目录建立。
符号链接 :类似于快捷方式
int link(const char *oldpath, const char *newpath);
int unlink(const char *pathname); //从磁盘上删除一个文件,并不代表这个文件就一定不存在了,只有硬链接数为零且没有其他进程打开才能完全删除
int remove(const char *pathname); //库函数,rm命令就是由这个函数封装而来
int rename(const char *oldpath, const char *newpath); //mv命令由这个函数封装而来
-
更改时间的操作utime
int utime(const char *filename, const struct utimbuf *times); //更改文件的最后读和写的时间
Linux没有文件的创建时间。 -
目录的创建和销毁
int mkdir(const char *pathname, mode_t mode);
int rmdir(const char *pathname); -
切换/更改当前工作路径
int chdir(const char *path); //cd命令由这个函数封装
int fchdir(int fd);
如果一个进程本身工作路径在一个U盘中,但此时要拔掉U盘,则就要修改工作路径。
假根技术:
能利用fchdir和bug突破安全机制
char *getcwd(char *buf, size_t size); //pwd命令由此函数封装 -
分析目录/读取目录内容