目录操作
In the glibc implementation, the dirent structure is defined as follows:
struct dirent {
ino_t d_ino; /* Inode number */
off_t d_off; /* Not an offset; see below */
unsigned short d_reclen; /* Length of this record */
unsigned char d_type; /* Type of file; not supported
by all filesystem types */
char d_name[256]; /* Null-terminated filename */
};
一些常见的系统调用:
DIR opendir(char dirname),打开目录,返回的DIR类似于文件指针FILE
struct dirent readdir(DIR ptr),接受目录指针,返回一个dirent指针。注意调用该函数的过程会自动遍历目录!当遍历完成后返回NULL.
int closedir(DIR *ptr),关闭目录
文件信息
stat(char file, struct stat buf),失败返回-1
stat结构体中常用变量如下
struct stat {
mode_t st_mode; //文件对应的模式,文件,目录等
ino_t st_ino; //inode节点号
dev_t st_dev; //设备号码
dev_t st_rdev; //特殊设备号码
nlink_t st_nlink; //文件的连接数
uid_t st_uid; //文件所有者
gid_t st_gid; //文件所有者对应的组
off_t st_size; //普通文件,对应的文件字节数
time_t st_atime; //文件最后被访问的时间
time_t st_mtime; //文件内容最后被修改的时间
time_t st_ctime; //文件状态改变时间
blksize_t st_blksize; //文件内容对应的块大小
blkcnt_t st_blocks; //伟建内容对应的块数量
};
使用样例:
#include<stdio.h>
#include<dirent.h>
#include<stdlib.h>
#include<string.h>
#include<sys/stat.h>
int main(int argc,char*argv[]){
char dirname[256];
strncpy(dirname,argv[1],255);
DIR* direct=opendir(dirname);
struct dirent* item;
struct stat filestat;
while((item=readdir(direct)) != NULL){
char permstr[10];
int stat_ret=stat(item->d_name,&filestat);
if(stat_ret==-1){
printf("Stat read error!\n");
exit(-1);
}
mode_t filemode=filestat.st_mode;
sprintf(permstr,"%c%c%c%c%c%c%c%c%c",(filemode & S_IRUSR)?'r':'-',
(filemode & S_IWUSR)?'w':'-',(filemode & S_IXUSR)?'x':'-',
(filemode & S_IRGRP)?'r':'-',(filemode & S_IWGRP)?'w':'-',
(filemode & S_IXGRP)?'x':'-',(filemode & S_IROTH)?'r':'-',
(filemode & S_IWOTH)?'w':'-',(filemode & S_IXOTH)?'x':'-');
printf("%s %s %hu\n",item->d_name,permstr,filestat.st_size);
}
return 0;
}
调用结果:
root@evillage:/home/woc/study/LinuxProgram# ./myls .
. rwxr-xr-x 137
.. rwxr-xr-x 170
myls rwxr-xr-x 16288
a.out rwxr-xr-x 16288
myls.c rw-r--r-- 875
testfile rw-r--r-- 760
Adir rwxr-xr-x 31
a rwxr-xr-x 6
b rwxr-xr-x 18
rename.c rw-r--r-- 174
myls.c~ rw-r--r-- 873
mypwd.c rw-r--r-- 877
链接
linux系统调用:
mkdir(char *path, mode_t mode),新建文件夹
rmdir(char *path)删除文件夹
unlink(const char *path)删除链接
link(const char src, const char dst)新建链接
rename(const char src, const char dst)重命名,可以用来移动文件
上述系统调用在成功时返回0,失败返回1.
linux使用“挂载”的方法将多个文件系统树整合到一个树上,具体过程是将一个新的文件系统嵌入到一个已经有的文件树中,
(LinuxProgram P117)
但是两个文件系统可能存在inode编号碰撞,因此link,rename这些系统调用会拒绝跨越文件系统的链接,编写以下测试代码:
#include<unistd.h>
#include<stdio.h>
#include<string.h>
int main(int argc, char *argv[]){
char srcfile[256];
char dstfile[256];
strcpy(srcfile, argv[1]);
strcpy(dstfile, argv[2]);
int result = rename(srcfile,dstfile);
if(result != -1){
printf("Rename Sucessfully.\n");
}
else{
printf("Failed! \n");
}
}
结果如下:
root@evillage:/home# ls
a.out file test.c woc
root@evillage:/home# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
nvme0n1 259:0 0 1.8T 0 disk
├─nvme0n1p1 259:1 0 100M 0 part /boot/efi
├─nvme0n1p2 259:2 0 16M 0 part
├─nvme0n1p3 259:3 0 512G 0 part
├─nvme0n1p4 259:4 0 1000G 0 part
├─nvme0n1p5 259:5 0 100G 0 part
├─nvme0n1p6 259:6 0 736M 0 part
├─nvme0n1p7 259:7 0 74.5G 0 part /
├─nvme0n1p8 259:8 0 37.3G 0 part /home
└─nvme0n1p9 259:9 0 3.7G 0 part [SWAP]
root@evillage:/home# ./a.out file file1
Rename Sucessfully.
root@evillage:/home# ./a.out file1 /file2
Failed!
root@evillage:/home#
通过lsblk我们可以看出,/home文件夹和根目录/处于两个不同的文件系统中,所以我们将/home下的file更名为file1能成功,但建立在/file2会失败
linux命令ln可以建立链接
root@evillage:~# touch file
root@evillage:~# ln file hard_file
root@evillage:~# ln -s file soft_file
root@evillage:~# ll -i *file
1086871 -rw-r--r-- 2 root root 0 Jul 1 19:49 file
1086871 -rw-r--r-- 2 root root 0 Jul 1 19:49 hard_file
1086872 lrwxrwxrwx 1 root root 4 Jul 1 19:49 soft_file -> file
root@evillage:~# ln -s /root/file testfile
root@evillage:~# ll -i testfile
1086873 lrwxrwxrwx 1 root root 10 Jul 1 19:53 testfile -> /root/file
我们可以看到,硬链接建立的文件与源文件inode相同,其本质是在指定目录下的block中新建了一个指向目标文件inode的部分,当file被删除后,hard_file仍能指向正确的位置。但是硬链接无法链接目录,也不能跨文件系统
而软链接则仅仅是“链接了文件名”,我们可以看到因为指向的文件file大小为4,而指向的/root/file则大小为10.
上面的file软链接soft_file文件大小仅仅为4,并没有使用绝对路径/root/file,我们可以猜测:如果将其移到其它目录,是不是就不能正常工作了呢?下面来验证:
root@evillage:~# mv testfile soft_file ..
root@evillage:~# ll -i *file
1086871 -rw-r--r-- 2 root root 0 Jul 1 19:49 file
1086871 -rw-r--r-- 2 root root 0 Jul 1 19:49 hard_file
root@evillage:~# cd ..
root@evillage:/# ll -i *file
1086872 lrwxrwxrwx 1 root root 4 Jul 1 19:49 soft_file -> file //失效
1086873 lrwxrwxrwx 1 root root 10 Jul 1 19:53 testfile -> /root/file
因为链接testfile的时候使用的是绝对路径,因此将其移动后仍然能正常指向file,但是soft_file则会失效,我们的猜想是正确的
文件系统
linux下文件系统有下面几个重要组成部分:
1.数据块,记录真实数据
2.inode,记录文件的权限、数据块编号、最近修改的时间等等文件信息(inode并不记录文件名称,真正将inode和文件名关联的是目录),inode也可以使用间接、双间接甚至三间接方法指向数据块,以扩大能够覆盖的数据范围。
3.超级区块,记录已经使用和未使用的inode,以及文件系统的一些整体信息
mount命令基本用法:
鸟哥P248
mount [-t filesystem] LABEL=''|UUID=''|设备文件名 挂载点
-o可以加上一些参数,//待补充
如果不加-t参数,系统会自动分析相关区块内容来决定挂载什么文件系统
/etc/fstab文件所写的文件系统会在系统启动时自动挂载,使用mount -a可以重新读取该文件并挂载。
卸载文件系统时,应该先移动到其外面
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。