[操作系统]fy姥爷的考试 (第三周) 补 linux文件系统中的i节点

我们可以把一个磁盘分成一个或多个分区。每个分区可以包含一个文件系统。i节点是固定长度的记录项m它包含有关文件的信息。

这里写图片描述

如果我们忽视自举块和超级块的情况,那么可以得到下面这张更清晰的图。
这里写图片描述

在图中有两个目录项指向同一个i节点,每个i节点都有一个连接计数,他的值是指向这个i节点的目录项数。只有当连接计数为0的时候,才可以删除该文件(也就是可以释放该文件占用的数据块)。这就是为什么”解除一个文件的连接”的操作并不总是意味这”释放该文件占用的磁盘块”的原因。这也是为什么删除一个目录项的函数被称之为unlink而不是delete的原因。

另一种连接类型称之为符号连接(symbolic link)。对于这种连接,该文件的实际内容(在数据块中)包含了该符号连接所指向的文件的名字。该i节点中的文件类型是S_INLNK,于是系统知道这是一个符号连接。

i节点包含了所有与文件有关的信息:文件类型,文件存取许可权位,文件长度和指向该文件所占用的数据块的指针等等。stat结构中大多数信息都取自i节点。只有两项数据存放在目录项中:文件名和i节点编号数。i节点编号数的数据类型是ino_t。

因为目录项中的i节点编号数指向同一文件系统中的i节点,所以不能使一个目录项指向另一个文件系统的i节点。

当不更改文件系统的情况下为一个文件更名时,该文件的实际内容并未移动,只需构造一个指向现存i节点的新目录项,并删除老的目录项。例如:将文件 /usr/lib/foo 更名为 /usr/foo ,如果目录/usr/lib和/usr处于同一文件系统上,则文件foo的内容无需移动。这就是mv命令的通常操作。

现在来说明这个连接计数是怎么算的。

这里写图片描述

创建一个向现存文件连接的方法是使用link函数
link函数原型

    int link(const char *existingpath,const char* newpath);

此函数创建一个新目录newpath,他引用现存文件existingpath 
创建新目录项以及增加连接计数应当是一个原子操作
只有超级用户进程可以创建指向一个目录的新连接。其理由是这样做可能在文件系统形成循环,大多数处理文件系统的公用程序都不能处理这种情况。

为了删除一个现存的目录项,可以调用unlinkhanshu1
unlink函数原型

    int unlink(const char *pathname);

此函数删除目录项,并将有pathname所引用的文件连接计数减1.如果该文件还有其他连接,则仍可通过其他链接存取该文件的数据。

只有当连接计数达到0时,该文件的内容才可被删除。另一个条件也阻止删除文件的内容——只要有进程打开该文件,其内容也不能删除。关闭一个文件时,内核首先检查使该文件打开的进程计数。如果该计数到达0,然后内核检查其连接计数,如果这也是0,那么就删除该文件的内容。

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
int main()
{
    int fd;
    char buf[32];
    struct stat buff;
    if((fd=open("temp.txt",O_RDWR|O_CREAT|O_TRUNC,S_IRWXU))<0){
        printf("create file error!\n");
    }
    stat("temp.txt",&buff);
    printf("temp.link=%d\n",buff.st_nlink);
    link("temp.txt","test.txt");
    stat("test.txt",&buff);
    printf("after link the temp.link=%d\n",buff.st_nlink);
    if(unlink("temp.txt")<0){
        printf("write error!\n");
    }
    if((lseek(fd,0,SEEK_SET))==-1){
        printf("lseek error!\n");
    }
    if((read(fd,buf,5))<0){
            printf("read error!\n");
            }

    return 0;
}
//temp.link=1
//after link the temp.link=1

符号连接
符号连接是对一个文件的间接指针,他与硬连接不同。硬连接直接指向文件的i节点。引进符号连接的原因是为了避免硬连接的一些限制:
1. 硬连接通常要求连接文件位于同一文件系统中
2. 只有超级用户才能创建到目录的硬连接,对符号连接以及他指向什么没有文件系统限制,任何用户都可创建指向目录的符号连接

符号连接一般用于将一个文件或整个目录结构移到其他某一个地址。

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<dirent.h>

int main(int argc,char *argv[])
{
    if(argc!=4){
        printf("param too few\n");
        exit(0);
    }
    char buf[1000];
    ssize_t sz;
    DIR *dp;
    int fd;
    if((dp=opendir(argv[2]))==NULL) {
        perror("opendir\n");
        exit(0);
    }
    if((fd=dirfd(dp))<0){
        perror("dirfd\n");
        exit(0);
    }

    if(symlinkat(argv[1],fd,argv[3])<0){
        perror("symlinkat\n");
        exit(0);
    }

    memset(buf,0,sizeof(buf));
    if((sz=readlinkat(fd,argv[3],buf,sizeof(buf)))<0){
        perror("readlinkat\n");
        exit(0);
    }
    printf("buf:%s,length:%u\n",buf,(unsigned int)sz);
    close(fd);
    return 0;
    // ./a.out ./p1_symlink.c ./foo ./mysymlinl
    //输出 ./p1_symlink.c,length 14
}

进入当前目录下的foo目录就能看到刚创建的符号连接mysymlink

(symlink程序 参考自飞鹰51 老哥http://blog.csdn.net/eagle51/article/details/52704156)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值