精华内容
下载资源
问答
  • 符号链接和硬链接

    2014-10-03 11:34:37
    2. ln -s file1 linkfile建立符号链接  ll file1会发现链接数为1,大小为8,因为linkfile字符数为8  ll linkfile会发现其链接数仍然为1,因为仍然只有一个指针指向数据对应的inode节点,即linkfile指向  数据...
    1. vi linkfile 输入this is linkfile 保存退出;

       
    2. ln -s file1 linkfile建立符号链接
       ll file1会发现链接数为1,大小为8,因为linkfile字符数为8
       ll linkfile会发现其链接数仍然为1,因为仍然只有一个指针指向数据对应的inode节点,即linkfile指向
       数据的inode节点;
     
       
    3. ln -L linkfile hard建立硬链接
       ll hard会发现其链接数为2,因为hard也指向数据的inode节点,linkfile也指向inode节点,所以为2
       ll linkfile同样其链接数2,hard和linkfile都指向inode节点
    注:这里ll hard和ll linkfile显示的各种属性为inode中的内容


    4. rm -rf linkfile删除linkfile,删除的只是linkfile指向inode节点的连线,此时
       ll hard会发现其链接数为1了,因为linkfile的这条指向inode节点的线被删除了,但是此时数据并没有被
       删除,cat hard仍然可以看到数据内容:this is linkfile,但是cat file1将会出现”找不到想应的文件“  
       的错误;



    注:符号链接文件中保存只是其目标文件名,而硬链接文件会有一个指针指向数据的inode节点;


    展开全文
  • HDFS符号链接和硬链接

    千次阅读 2016-10-15 15:31:07
    前言初看这个标题,可能很多人会心生疑问:符号链接和硬链接是什么意思?...熟悉Linux系统的同学应该都知道在Linux文件系统下有硬链接和软链接的概念,而HDFS同样作为一套文件系统,它也能支持文件

    前言


    初看这个标题,可能很多人会心生疑问:符号链接和硬链接是什么意思?这些概念不是在Linux操作系统下才有的嘛,HDFS目前也有?当然大家可能还会有其他疑问,没关系,在后面的内容讲述中答案会一一揭晓。归纳起来一句话:不管是符号链接还是硬链接,它们本质上都是一种快捷的链接方式。熟悉Linux系统的同学应该都知道在Linux文件系统下有硬链接和软链接的概念,而HDFS同样作为一套文件系统,它也能支持文件链接的形式。本文所讲述的主题正是HDFS下的文件链接操作。

    相关背景:Linux软链接和硬链接


    在讲述HDFS下的文件链接内容之前,有必要了解一下相关内容:Linux软链接和硬链接。因为HDFS文件链接的原理设计基本与此相似。Linux软链接和硬链接分别代表着2种截然不同的连接形式,它们在作用上也存在部分微妙的差异。

    软链接


    软链接又被称为符号链接,英文名称soft link或symbolic link(HDFS内采用的软链接名称就是symbolic link,简称symlink)。就个人感觉而言,软链接在实际工作中用得频率会略高于硬链接。一句话简单地概括软链接的作用:

    软链接其实就是文件的一个快捷方式,软链接删除了,其指向的真实文件并不会受到影响。

    所以在实际的工作中,我们一般会把依赖资源包的路径用软链接的方式引用,这样的话资源包的路径可以一直保持不变,而其所指向的真实资源包可以根据使用场景进行任意变化

    硬链接


    硬链接,英文名称为hard link。它的一个主要目的在于文件的共享。文件的硬链接创建出来之后,它具有如下的特点:

    硬链接相当于文件的一个别名。它指向的是一个文件inode的引用地址,而非软链接中的文件路径指向。所以对于硬链接中的文件做修改会影响到其所指向的真实文件,当对硬链接做删除动作后,如果其所指向的文件inode当前没有被外部引用的话,则原文件会被删除,否则原文件不会被删除。

    上面的意思通俗地解释就是说,当真实文件或此文件的硬链接有一个存在的情况下,对文件执行删除操作,文件不会被真正删除。当只剩下一个文件inode引用的情况下,删除操作才能生效。

    HDFS符号链接(软链接)与硬链接概述


    了解完Linux下的软链接与硬链接的概念后,我们将进入本文的主题:HDFS下的符号链接与硬链接。

    Hadoop社区在HDFS-245(Create symbolic links in HDFS)中优先对符号链接功能进行了实现。符号链接另外一部分的工作在HADOOP-6421(Symbolic links)中,此部分是HADOOP-COMMON模块相关的底层代码改动。在硬链接方面,社区目前有相关的JIRA:HDFS-3370(HDFS hardlink),但是社区目前并没有在跟进,只有初始的设计文档。所以本文准备讲述的HDFS硬链接将会是一个设计模型,并未真正实现,这点需要注意

    鉴于目前HDFS的硬链接功能并未真正实现,所以本文的主讲内容还是符号链接的功能,硬链接功能将给出大致设计模型。

    HDFS符号链接(软链接)


    HDFS符号链接,在HDFS中称之为symbolic link,在下文的讲述中此名称都将会简称为symlink。与Linux文件系统中的软链接概念一样,HDFS符号链接也是相当于给目标文件新建一个自定义路径,这个自定义路径实质指向目标文件。所以在这里HDFS符号链接中做的最重要的事情就是路径的解析。而且这个解析还有可能是嵌套的,符号链接中指向的是另外一个符号链接。下面来学习HDFS符号链接的主要原理实现。

    HDFS符号链接原理


    HDFS符号链接功能的实现主要分为2个部分:一个是对现有文件符号链接的添加,另外一个则是符号链接的解析过程。

    对现有文件符号链接的添加在HDFS中的实现就是添加一个新的INode对象在NameNode中,只是这个INode对象是Symlink类型的,叫做INodeSymlink。此对象内部会包含一个实际指向的target地址。

    而符号链接的解析过程则会略微复杂一些,HDFS并不是直接在NameNode最终处理方法的地方做解析的,而是在前面一层FileContext类上做解析的,然后将解析好后的路径再传到HDFS中做处理。换句话说,客户端需要通过FileContext上下文对象来操作符号链接相关的操作,如果直接用FileSystem的API来操作的话,会抛出解析异常的错误

    HDFS符号链接核心代码实现


    此部分我们将通过部分代码的跟踪来学习HDFS符号链接的实现过程。

    同样首先是创建符号链接的过程,我们直接进入到最终的服务端处理方法,FSNamesystem的createSymlink方法。

       *// 为目标文件创建一个符号链接
      void createSymlink(String target, String link,
          PermissionStatus dirPerms, boolean createParent, boolean logRetryCache)
          throws IOException {
        if (!FileSystem.areSymlinksEnabled()) {
          throw new UnsupportedOperationException("Symlinks not supported");
        }
        HdfsFileStatus auditStat = null;
        writeLock();
        try {
          checkOperation(OperationCategory.WRITE);
          checkNameNodeSafeMode("Cannot create symlink " + link);
          // 此处进入创建软链接实际操作
          auditStat = FSDirSymlinkOp.createSymlinkInt(this, target, link, dirPerms,
                                                      createParent, logRetryCache);
          ...

    我们继续进入FSDirSymlinkOp的createSymlinkInt方法,

      static HdfsFileStatus createSymlinkInt(
          FSNamesystem fsn, String target, final String linkArg,
          PermissionStatus dirPerms, boolean createParent, boolean logRetryCache)
          throws IOException {
        FSDirectory fsd = fsn.getFSDirectory();
        String link = linkArg;
        // 检验符号链接的名称
        if (!DFSUtil.isValidName(link)) {
          throw new InvalidPathException("Invalid link name: " + link);
        }
        if (FSDirectory.isReservedName(target) || target.isEmpty()
            || FSDirectory.isExactReservedName(target)) {
          throw new InvalidPathException("Invalid target name: " + target);
        }
    
        if (NameNode.stateChangeLog.isDebugEnabled()) {
          NameNode.stateChangeLog.debug("DIR* NameSystem.createSymlink: target="
              + target + " link=" + link);
        }
    
        FSPermissionChecker pc = fsn.getPermissionChecker();
        INodesInPath iip;
        fsd.writeLock();
        try {
          // 解析得到符号链接的路径对象
          iip = fsd.resolvePathForWrite(pc, link, false);
          link = iip.getPath();
          ...
    
          // 将此符号链接对象加入到NameNode元数据中
          addSymlink(fsd, link, iip, target, dirPerms, createParent, logRetryCache);
          ...

    我们继续进入addSymlink方法,

      private static INodeSymlink addSymlink(FSDirectory fsd, String path,
          INodesInPath iip, String target, PermissionStatus dirPerms,
          boolean createParent, boolean logRetryCache) throws IOException {
        final long mtime = now();
        final INodesInPath parent;
        // 获取目标符号链接的父亲对象
        if (createParent) {
          // 如果需要创建父亲对象,则进行创建父目录操作方法
          parent = FSDirMkdirOp.createAncestorDirectories(fsd, iip, dirPerms);
          if (parent == null) {
            return null;
          }
        } else {
          parent = iip.getParentINodesInPath();
        }
        final String userName = dirPerms.getUserName();
        long id = fsd.allocateNewInodeId();
        PermissionStatus perm = new PermissionStatus(
            userName, null, FsPermission.getDefault());
        // 加入符号链接类型的INode对象到父对象中
        INodeSymlink newNode = unprotectedAddSymlink(fsd, parent,
            iip.getLastLocalName(), id, target, mtime, mtime, perm);
        ...

    最后调用到加入NameNode命名空间方法,

      static INodeSymlink unprotectedAddSymlink(FSDirectory fsd, INodesInPath iip,
          byte[] localName, long id, String target, long mtime, long atime,
          PermissionStatus perm)
          throws UnresolvedLinkException, QuotaExceededException {
        assert fsd.hasWriteLock();
        // 新建符号链接类型的INode对象
        final INodeSymlink symlink = new INodeSymlink(id, null, perm, mtime, atime,
            target);
        symlink.setLocalName(localName);
        // 将符号链接对象加入到最终路径对应的上一级父目录下
        return fsd.addINode(iip, symlink, perm.getPermission()) != null ?
            symlink : null;
      }

    至此,添加软链接操作正式完毕,与普通HDFS文件INode对象的添加过程类似。

    接下来我们来看另外一个部分的内容:HDFS符号链接的路径解析过程。这个过程是本文的一个重点。在没有学习HDFS符号链接源代码之前,本人一直以为HDFS把符号链接的解析过程放在了NameNode的处理方法中,但最终结果表明,事实并不是这样的

    假设我们直接以HDFS文件的符号链接进行读写操作,究竟会发生什么事情呢?这里我们以setReplication设置副本数操作为例。

    首先通过DFSClient端执行setReplication方法,

       *// 为指定的文件进行副本数的设置,假设我们这里传入的src路径是一个符号链接,而非真实文件地址
      public boolean setReplication(String src, short replication)
          throws IOException {
        checkOpen();
        try (TraceScope ignored = newPathTraceScope("setReplication", src)) {
          // 向服务端发起设置副本数操作请求
          return namenode.setReplication(src, replication);
        } catch (RemoteException re) {
          ...
        }
      }

    我们直接进入FSNamesystem的相应处理方法,

      boolean setReplication(final String src, final short replication)
          throws IOException {
        boolean success = false;
        checkOperation(OperationCategory.WRITE);
        writeLock();
        try {
          checkOperation(OperationCategory.WRITE);
          checkNameNodeSafeMode("Cannot set replication for " + src);
          // 调用真正设置副本数方法
          success = FSDirAttrOp.setReplication(dir, blockManager, src, replication);
        } catch (AccessControlException e) {
          logAuditEvent(false, "setReplication", src);
          throw e;
        } finally {
          writeUnlock();
        }
        ...
        return success;
      }

    这里进入FSDirAttrOp的setReplication方法,

      static boolean setReplication(
          FSDirectory fsd, BlockManager bm, String src, final short replication)
          throws IOException {
        bm.verifyReplication(src, replication, null);
        final boolean isFile;
        FSPermissionChecker pc = fsd.getPermissionChecker();
        fsd.writeLock();
        try {
          // 解析此路径得到INode路径对象
          final INodesInPath iip = fsd.resolvePathForWrite(pc, src);
          if (fsd.isPermissionEnabled()) {
            fsd.checkPathAccess(pc, iip, FsAction.WRITE);
          }
          // 对此路径进行副本的设置
          final BlockInfo[] blocks = unprotectedSetReplication(fsd, iip,
                                                               replication);
          ...

    至少从目前来看,我们还没看到解析符号链接的操作,我们继续进入设置副本的进一步操作:unprotectedSetReplication方法。

      static BlockInfo[] unprotectedSetReplication(
          FSDirectory fsd, INodesInPath iip, short replication)
          throws QuotaExceededException, UnresolvedLinkException,
          SnapshotAccessControlException, UnsupportedActionException {
        assert fsd.hasWriteLock();
    
        final BlockManager bm = fsd.getBlockManager();
        // 获取路径对象的最后一个节点,也就是最终需要设置副本的文件INode对象
        final INode inode = iip.getLastINode();
        if (inode == null || !inode.isFile() || inode.asFile().isStriped()) {
          // TODO we do not support replication on stripe layout files yet
          return null;
        }
        // 得到此INodeFile对象
        INodeFile file = inode.asFile();
        // Make sure the directory has sufficient quotas
        short oldBR = file.getPreferredBlockReplication();
    
        long size = file.computeFileSize(true, true);
        // Ensure the quota does not exceed
        if (oldBR < replication) {
          fsd.updateCount(iip, 0L, size, oldBR, replication, true);
        }
        // 对象文件对象进行副本数的设置
        file.setFileReplication(replication, iip.getLatestSnapshotId());
        short targetReplication = (short) Math.max(
            replication, file.getPreferredBlockReplication());
    
        ...
        return file.getBlocks();
      }

    在此方法中,HDFS直接从路径对象中取出文件INode对象,然后对其进行副本数的设置,从中并没有对符号链接进行解析的操作。我们重新把目光回到之前FSDirAttrOp的setReplication方法,在此方法中的fsd.resolvePathForWrite操作是否会有这样的解析动作呢,从方法名上看也确实包含了解析的单词。这里进入FSDirectory的resolvePathForWrite方法,

      INodesInPath resolvePathForWrite(FSPermissionChecker pc, String src)
          throws UnresolvedLinkException, FileNotFoundException,
          AccessControlException {
        // 此处调用同名方法,这里的第三个布尔参数代表解析到符号链接的INode对象时是否抛出异常
        return resolvePathForWrite(pc, src, true);
      }

    此方法中间会调用层层方法,最终调用INodesInPath类内部的resolve方法。此方法执行过程如下,

      static INodesInPath resolve(final INodeDirectory startingDir,
          final byte[][] components, final boolean isRaw,
          final boolean resolveLink) throws UnresolvedLinkException {
        Preconditions.checkArgument(startingDir.compareTo(components[0]) == 0);
    
        INode curNode = startingDir;
        int count = 0;
        int inodeNum = 0;
        INode[] inodes = new INode[components.length];
        boolean isSnapshot = false;
        int snapshotId = CURRENT_STATE_ID;
    
        while (count < components.length && curNode != null) {
          final boolean lastComp = (count == components.length - 1);
          inodes[inodeNum++] = curNode;
          final boolean isRef = curNode.isReference();
          final boolean isDir = curNode.isDirectory();
          final INodeDirectory dir = isDir? curNode.asDirectory(): null;
          if (!isRef && isDir && dir.isWithSnapshot()) {
            ...
          } else if (isRef && isDir && !lastComp) {
            ...
          }
          // 如果当前INode是符号链接类型并且当前需要抛出符号链接异常或当前不是最后一个INode对象时,
          // 都抛出异常
          if (curNode.isSymlink() && (!lastComp || resolveLink)) {
            final String path = constructPath(components, 0, components.length);
            final String preceding = constructPath(components, 0, count);
            final String remainder =
              constructPath(components, count + 1, components.length);
            // 获取符号链接地址
            final String link = DFSUtil.bytes2String(components[count]);
            // 获取符号链接真实指向地址
            final String target = curNode.asSymlink().getSymlinkString();
            if (LOG.isDebugEnabled()) {
              LOG.debug("UnresolvedPathException " +
                " path: " + path + " preceding: " + preceding +
                " count: " + count + " link: " + link + " target: " + target +
                " remainder: " + remainder);
            }
            // 抛出无法解析异常
            throw new UnresolvedPathException(path, preceding, remainder, target);
          }
          ...
        return new INodesInPath(inodes, components, isRaw, isSnapshot, snapshotId);
      }

    从上面的操作方法中,我们可以得出两个结论:

    • 第一点,HDFS符号链接的解析逻辑并不是实现在NameNode服务端的处理代码中。
    • 第二点,NameNode服务端中解析符号链接的目的在于帮助抛出解析异常信息,以此告诉用户当前处理的路径是一个符号链接地址。

    那么这部分的解析逻辑到底发生在了什么地方呢?这个答案我们可以从符号链接的单元测试实例中进行寻找,范例代码如下(同样以设置副本数操作为例):

       @Test
       /** setReplication affects the target not the link */  
       public void testSetReplication() throws IOException {
         Path file = new Path(testBaseDir1(), "file");
         Path link = new Path(testBaseDir1(), "linkToFile");
         createAndWriteFile(file);
         fc.createSymlink(file, link, false);
         // 此处通过fc对象进行设置,fc指的是文件上下文对象
         fc.setReplication(link, (short)2);
         assertEquals(0, fc.getFileLinkStatus(link).getReplication());
         assertEquals(2, fc.getFileStatus(link).getReplication());      
         assertEquals(2, fc.getFileStatus(file).getReplication());
      }

    上面符号链接的设置副本操作是通过fc对象进行的,fc对象的意思是文件上下文,此对象的初始化操作如下:

       @BeforeClass
       public static void testSetUp() throws Exception {
         Configuration conf = new HdfsConfiguration();
         conf.setBoolean(DFSConfigKeys.DFS_PERMISSIONS_ENABLED_KEY, true);
         conf.set(FsPermission.UMASK_LABEL, "000");
         cluster = new MiniDFSCluster(conf, 1, true, null);
         // 测试实例初始化操作中,得到文件上下文对象
         fc = FileContext.getFileContext(cluster.getURI());
       }

    至此,这也就是为什么我们不能直接用FileSystem对象进行符号链接相关操作执行的原因。

    下面我们来聊聊FileContext到底是如何帮助用户完成符号链接的解析过程的。比如说,现在我已经初始化好了一个FileContext对象,然后调用了setReplication操作,接着会触发到下面的方法,

      public boolean setReplication(final Path f, final short replication)
          throws AccessControlException, FileNotFoundException,
          IOException {
        final Path absF = fixRelativePart(f);
        // 调用解析器对象进行解析
        return new FSLinkResolver<Boolean>() {
          @Override
          public Boolean next(final AbstractFileSystem fs, final Path p) 
            throws IOException, UnresolvedLinkException {
            // next方法执行时,p已经代表了目标真实文件地址
            return fs.setReplication(p, replication);
          }
        }.resolve(this, absF);
      }

    所以以上的实现关键点在于FSLinkResolver的解析过程。我们进入此类,解析过程如下:

      public T resolve(final FileContext fc, final Path path) throws IOException {
        int count = 0;
        T in = null;
        Path p = path;
        // 获取初始文件系统
        AbstractFileSystem fs = fc.getFSofPath(p);
    
        // 进行循环解析,直到所有的符号链接地址都被解析成功
        for (boolean isLink = true; isLink;) {
          try {
            // 如果当前的路径解析成功,则更新标记为false,跳出循环,代表当前路径已解析成功
            in = next(fs, p);
            isLink = false;
          } catch (UnresolvedLinkException e) {
            ...
            // 否则出现符号链接时,解析当前第一层符号链接地址,fs.getLinkTarget(p)会获取当前符号链接地址所指向的真实地址
            p = qualifySymlinkTarget(fs.getUri(), p, fs.getLinkTarget(p));
            fs = fc.getFSofPath(p);
            // 然后用新的路径和文件系统对象进行下一次的操作执行
          }
        }
        return in;
      }

    fs.getLinkTarget(p)操作方法的实现,大家可以从DistributedFileSystem中查看其具体实现。

    所以,HDFS符号链接的总过程调用如下图所示:


    20161014221322931
    图 1-1 HDFS符号链接解析过程

    HDFS硬链接的原型设计


    鉴于前面花了大量的篇幅介绍了HDFS符号链接(软链接)的内容,最后简单介绍介绍HDFS硬链接的内容。因为此功能目前在HDFS中并未实现,只有原型设计,所以这里也将只会介绍社区上对于此功能的一个设计。

    HDFS硬链接的一个核心使用点在于它可以在无需拷贝真实数据的情况下,实现数据的共享。为了实现这样的功能,在HDFS-3370中的设计文档中,设计者引入了INodeHardLinkFile对象来代表当前的一个硬链接。这些对象共享HardLinkFileInfo对象。在HardLinkFileInfo对象中,会保持有当前的引用计数值,表示当前引用此文件的硬链接数,与Linux操作系统中的硬链接类似。

    下面通过图形展示的方式大致介绍一下HDFS硬链接的原型设计:

    首先,假设当前存在一个已存在的文件File1,如图1-2。


    20161015151401844
    图 1-2 HDFS初始文件

    此时对文件File1创建一个硬链接,同时名称也为File1不变,File1的INodeFile对象将会转化为INodeHardLinkFile对象,同时引用计数为1,此过程见图1-3。


    20161015151713754
    图 1-3 HDFS硬链接的创建

    在此基础上,如果还要对此文件进行硬链接的创建,即为INodeHardLinkFile的再次创建,但是引用的HarLinkFileInfo还是同一个对象,HarLinkFileInfo引用计数此时递增 2,此过程见图1-4。


    20161015151935506
    图 1-4 HDFS硬链接的再创建

    这个于Linux硬链接中的文件inode引用原理是完全一致的。当个别文件硬链接对象的删除将不会删除其真实的数据,除非硬链接文件当前没有其他的引用对象了。

    此设计文档的作者是来自于Facebook的某位工程师,本人估测此功能在Facebook内部已经早已实现,HDFS硬链接更多设计细节,可以阅读参考资料中的链接地址。

    参考资料


    [1].https://issues.apache.org/jira/browse/HDFS-245
    [2].https://issues.apache.org/jira/browse/HDFS-3370
    [3].https://issues.apache.org/jira/browse/HADOOP-6421
    [4].https://issues.apache.org/jira/secure/attachment/12526189/HDFS-HardLink.pdf

    展开全文
  • 符号链接和硬链接有什么区别?

    千次阅读 2019-12-22 15:32:05
    最近我在求职面试时被问到这个问题。 我是诚实的,并说我知道符号链接的行为以及如何创建一个,但不理解硬链接的使用以及它与符号链接的区别。

    最近我在求职面试时被问到这个问题。 我是诚实的,并说我知道符号链接的行为以及如何创建一个,但不理解硬链接的使用以及它与符号链接的区别。


    #1楼

    使用任何Linux(ish)控制台可能有所帮助的一些很好的直觉。

    创建两个文件:

    $ touch foo; touch bar
    

    在其中输入一些数据:

    $ echo "Cat" > foo
    $ echo "Dog" > bar
    

    (实际上,我可以首先使用echo,因为它创建了文件,如果它们不存在......但不要介意。)

    正如所料:

    $cat foo; cat bar
    Cat
    Dog
    

    让我们创建硬链接和软链接:

    $ ln foo foo-hard
    $ ln -s bar bar-soft
    

    让我们看看刚刚发生了什么:

    $ ls -l
    
    foo
    foo-hard
    bar
    bar-soft -> bar
    

    更改foo的名称无关紧要:

    $ mv foo foo-new
    $ cat foo-hard
    Cat
    

    foo-hard指向文件的inode,内容 - 没有改变。

    $ mv bar bar-new
    $ ls bar-soft
    bar-soft
    $ cat bar-soft  
    cat: bar-soft: No such file or directory
    

    无法找到文件的内容,因为软链接指向已更改的名称,而不是内容。

    同样,如果foo被删除, foo-hard仍然保留内容; 如果bar被删除, bar-soft只是指向不存在的文件的链接。


    #2楼

    也:

    1. 读取硬链接的性能优于符号链接(微观性能)
    2. 符号链接可以复制,版本控制,..等。 换句话说,它们是一个实际的文件。 另一方面,硬链接稍微低一些,你会发现与符号链接相比,有更少的工具可以提供硬链接作为硬链接而不是普通文件的工具

    #3楼

    简单来说,硬链接:只是为文件添加新名称,这意味着,一个文件可以同时拥有多个名称,所有名称彼此相等,没有人首选,硬链接并不意味着复制所有内容文件和制作新文件不是那样,它只是创建一个可供选择的替代名称..

    符号链接(符号链接):是指向另一个文件的文件指针,如果符号链接指向稍后删除的现有文件,则符号链接将继续指向相同的文件名,即使该名称不再指定任何文件。


    #4楼

    在文件系统下面的文件由inode表示(或者它是多个inode不确定)

    文件系统中的文件基本上是指向inode的链接。
    然后,硬链接只创建另一个文件,其中包含指向同一底层inode的链接。

    删除文件时,它会删除一个指向底层inode的链接。 只有在删除了所有指向inode的链接后,才会删除(或删除/可写入)inode。

    符号链接是指向文件系统中另一个名称的链接。

    一旦建立了硬链接,链接就是inode。 删除重命名或移动原始文件不会影响硬链接,因为它链接到底层的inode。 对inode数据的任何更改都会反映在引用该inode的所有文件中。

    注意:硬链接仅在同一文件系统中有效。 符号链接可以跨越文件系统,因为它们只是另一个文件的名称。


    #5楼

    符号链接链接到路径名称。 这可以是系统文件树中的任何位置,甚至在创建链接时也不必存在。 目标路径可以是相对路径或绝对路径。

    硬链接是指向inode的附加指针,这意味着它们只能存在于与目标相同的卷上。 文件的其他硬链接与用于引用文件的“原始”名称无法区分。


    #6楼

    我会指向维基百科:

    几点:

    • 与硬链接不同,符号链接可以跨文件系统(大多数情况下)。
    • 符号链接可以指向目录。
    • 硬链接指向文件,使您能够引用具有多个名称的同一文件。
    • 只要至少有一个链接,数据仍然可用。

    #7楼

    我补充说尼克的问题:什么时候硬链接有用还是必要? 我想到的唯一一个符号链接无法完成工作的应用程序是在chrooted环境中提供系统文件的副本。


    #8楼

    当原始文件被移动时,硬链接很有用。 例如,将文件从/ bin移动到/ usr / bin或移动到/ usr / local / bin。 这个文件在/ bin中的任何符号链接都会被破坏,但是硬链接(直接指向文件的inode的链接)并不关心。

    硬链接可能占用较少的磁盘空间,因为它们只占用目录条目,而符号链接需要它自己的inode来存储它指向的名称。

    硬链接也需要较少的时间来解决 - 符号链接可以指向符号链接目录中的其他符号链接。 其中一些可能在NFS或其他高延迟文件系统上,因此可能导致网络流量得到解决。 始终在同一文件系统上的硬链接总是在一次查找中解决,并且从不涉及网络延迟(如果它是NFS文件系统上的硬链接,NFS服务器将执行解析,并且它将不可见客户系统)。 有时这很重要。 不适合我,但我可以想象这可能很重要的高性能系统。

    我还认为像mmap(2)甚至open(2)这样的东西使用与硬链接相同的功能来保持文件的inode活动,这样即使文件被取消链接(2),inode仍然允许进程继续访问,只有在进程关闭后,文件才会真正消失。 这允许更安全的临时文件(如果你可以原子地进行打开和取消链接,可能有一个我不记得的POSIX API,那么你真的有一个安全的临时文件)你可以读/写没有任何人能够访问您的数据。 好吧,在/ proc让每个人都能够查看你的文件描述符之前,这是真的,但这是另一个故事。

    说到这一点,恢复在进程A中打开但在文件系统上取消链接的文件围绕使用硬链接重新创建inode链接,这样当打开它的进程关闭或消失时,文件不会消失。


    #9楼

    执行增量备份时,硬链接非常有用。 例如,请参阅rsnapshot 。 我的想法是使用硬链接进行复制:

    • 将备份号码n复制到n + 1
    • 将备份n - 1复制到n
    • ...
    • 将备份0复制到备份1
    • 使用任何更改的文件更新备份0。

    除了您所做的任何更改之外,新备份不会占用任何额外空间,因为所有增量备份都将指向未更改的文件的同一组inode。


    #10楼

    软链接

    软或符号更像是对原始文件的快捷方式....如果删除原始文件,则快捷方式会失败,如果只删除快捷方式,则原始文件不会发生任何变化。

    软链接语法ln -s Pathof_Target_file link

    输出: link -> ./Target_file

    证明: readlink link在同样ls -l link输出,您将看到的第一个字母lrwxrwxrwxL这表明该文件是软链接。

    删除链接: unlink link

    注意:如果您愿意,即使将软链接从当前目录移动到其他位置,您的软链接也可以正常工作。 确保在创建软链接时给出绝对路径而不是相对路径。 ie(从/ root / user / Target_file开始而不是./Target_file)

    硬链接:

    硬链接更多是镜像副本或同一文件的多个路径。 对file1执行某些操作并将其显示在文件2中。删除一个仍然保持另一个正常。

    仅当删除了所有(硬)链接或(同一文件)inode的所有路径时,才会删除inode(或文件)。

    一旦建立了硬链接,该链接就具有原始文件的inode。 删除重命名或移动原始文件不会影响硬链接,因为它链接到底层的inode。 对inode数据的任何更改都会反映在引用该inode的所有文件中。

    硬链接语法ln Target_file link

    输出:将使用与Targetfile相同的inode编号创建具有名称链接的文件。

    证明: ls -i link Target_file (检查它们的inode)

    删除链接: rm -f link (删除链接就像普通文件一样)

    注意 :符号链接可以跨越文件系统,因为它们只是另一个文件的名称。 而硬链接仅在同一文件系统中有效。

    符号链接有一些功能缺少硬链接:

    • 硬链接指向文件内容。 而软链接指向文件名。
    • 而硬链接的大小是内容的大小,而软链接具有文件名大小。
    • 硬链接共享相同的inode。 软链接没有。
    • 硬链接无法跨文件系统。 软链接。
    • 你知道符号链接指向硬链接的位置,你需要浏览整个文件系统来查找共享相同inode的文件。

      # find / -inum 517333

       /home/bobbin/sync.sh /root/synchro 
    • 硬链接不能指向目录。

    硬链接有两个限制:

    • 目录不能硬链接。 Linux不允许这样做来维护目录的非循环树结构。
    • 无法跨文件系统创建硬链接。 这两个文件必须位于相同的文件系统上,因为不同的文件系统具有不同的独立inode表(不同文件系统上的两个文件,但具有相同的inode编号将不同)。

    #11楼

    符号链接以类似于硬链接的方式为文件指定另一个名称。 但即使存在剩余的符号链接,也可以删除文件。


    #12楼

    你认为普通的“文件”实际上是两个独立的东西:文件的数据和目录条目。 为文件创建硬链接时,实际上会创建第二个目录条目,该条目引用相同的数据。 两个目录条目具有完全相同的功能; 每个都可以用来打开文件来读取它。 所以你没有“文件和硬链接”,你有“两个目录条目的文件数据”。 您认为删除文件实际上会删除目录条目,并且当删除数据的最后一个目录条目时,也会删除数据本身。 对于只有一个目录条目的普通文件,删除目录条目将一如既往地删除数据。 (当文件打开时,操作系统会创建一个指向该文件的临时链接,因此即使删除所有目录条目,数据也会在关闭文件后保持但消失)。

    例如,创建文件A.txt,硬链接B.txt,并删除A.txt。 创建A.txt时,会创建一些数据,并创建目录条目A.txt。 创建硬链接时,会创建另一个目录条目B.txt,指向完全相同的数据。 当您删除A.txt时,您仍然拥有所有数据和单个目录条目B.txt,就像您首先创建文件B.txt一样。

    软链接只是一个(几乎)普通文件,除了它不包含数据,而是包含另一个目录条目的路径。 如果删除软链接引用的文件,则软链接将包含不再指向目录条目的路径; 它被打破。 如果删除软链接,就像删除任何其他文件一样,它指向的文件不受影响。


    #13楼

    查看硬链接和符号链接之间差异的简单方法是通过一个简单的示例。 指向文件的硬链接将指向存储文件的位置或该文件的inode。 符号链接将指向实际文件本身。

    因此,如果我们有一个名为“a”的文件并创建一个硬链接“b”和一个符号链接“c”,它们都引用文件“a”:

    echo "111" > a
    ln a b
    ln -s a c
    

    “a”,“b”和“c”的输出将是:

    cat a --> 111
    cat b --> 111
    cat c --> 111
    

    现在让我们删除文件“a”,看看“a”,“b”和“c”的输出会发生什么:

    rm a
    cat a --> No such file or directory
    cat b --> 111
    cat c --> No such file or directory
    

    所以发生了什么事?

    因为文件“c”指向文件“a”本身,如果删除文件“a”,则文件“c”将没有任何指向,实际上它也被删除。

    但是,文件“b”指向文件“a”的存储位置或inode。 因此,如果文件“a”被删除,那么它将不再指向inode,但由于文件“b”,因此inode将继续存储属于“a”的任何内容,直到不再有硬链接指向它为止。


    #14楼

    俗话说,一张图片胜过千言万语。 这是我如何想象它:

    在此输入图像描述

    以下是我们如何获得该图片:

    1. 在文件系统中创建一个名称myfile.txt ,指向新的inode(包含文件的元数据并指向包含其内容的数据块,即文本“Hello,World!”:

       $ echo 'Hello, World!' > myfile.txt 
    2. 创建一个到myfile.txt文件的硬链接my-hard-link ,这意味着“创建一个应该指向myfile.txt指向的同一个inode的文件”:

       $ ln myfile.txt my-hard-link 
    3. 创建一个软链接my-soft-link到文件myfile.txt ,这意味着“创建一个应该指向文件myfile.txt的文件”:

       $ ln -s myfile.txt my-soft-link 

    如果myfile.txt被删除(或移动),看看现在会发生什么: my-hard-link仍然指向相同的内容,因此不受影响,而my-soft-link现在指向什么。 其他答案讨论每个人的利弊。


    #15楼

    来自MSDN

    符号链接

    符号链接是指向另一个文件系统对象的文件系统对象。 被指向的对象称为目标。

    符号链接对用户是透明的; 链接显示为普通文件或目录,并且可以由用户或应用程序以完全相同的方式对其进行操作。

    符号链接旨在帮助迁移和应用程序与UNIX操作系统的兼容性。 Microsoft已实现其符号链接,以便像UNIX链接一样运行。

    符号链接可以是绝对链接或相对链接。 绝对链接是指定路径名称的每个部分的链接; 相对链接是相对于相对链接说明符在指定路径中的位置确定的

    绝对符号链接的一个例子

    X: "C:\alpha\beta\absLink\gamma\file"
    Link: "absLink" maps to "\\machineB\share"
    Modified Path: "\\machineB\share\gamma\file"
    

    相对符号链接的一个例子

    X: C:\alpha\beta\link\gamma\file
    Link: "link" maps to "..\..\theta"
    Modified Path: "C:\alpha\beta\..\..\theta\gamma\file"
    Final Path: "C:\theta\gamma\file"
    

    硬链接

    硬链接是文件的文件系统表示,通过该文件,多个路径引用同一卷中的单个文件。

    要在Windows中创建硬链接,请导航到要创建链接的位置并输入以下命令:

    mklink /H Link_name target_path
    

    请注意,您可以删除任何订单的硬链接,无论它们的创建顺序如何。 此外,无法创建硬链接

    • 引用位于不同的本地驱动器中
    • 参考包括网络驱动器。 换句话说,其中一个参考是网络驱动器
    • 要创建的硬链接与目标位于同一路径中

    连接点

    NTFS支持另一种称为联结的链接类型。 MSDN将其定义如下:

    联结(也称为软链接)与硬链接的不同之处在于,它引用的存储对象是单独的目录,并且联结可以链接位于同一计算机不同本地卷上的目录。 否则,交叉点的运行方式与硬链路相同。

    硬链接部分和连接部分中的粗体部分显示了两者之间的基本差异。

    在Windows中创建联结的命令,导航到要创建链接的位置,然后输入:

    mklink /J link_name target_path
    

    #16楼

    目录条目是链接结构:

    struct dentry{
        ino_t ino;
        char  name[256];
    }
    

    ino是inode的数量,名称是文件名,inode结构可能如下:

    struct inode{
          link_t nlink; 
          ...
    }
    

    例如,你创建一个文件/ 1,目录条目可能像:

    struct dentry{
         ino_t ino; /* such as 15 */
         char  name[256]; /* "1" */
    } 
    

    inode结构可能像:

       struct inode{ /* inode number 15 */
             link_t nlink; /* nlink = 1 */
             ...
        }
    

    然后你创建一个硬链接(可能是/ 100),目录条目可能像:

      struct dentry{
         ino_t ino; /* 15 */
         char  name[256]; /* 100 */
      }
    

    inode结构可能像:

       struct inode{ /* inode numebr 15 */
             link_t nlink; /* nlink = 2 */
             ...
        }
    

    然后你创建一个符号链接(可能是/ 200)到文件1,目录条目可能像:

      struct dentry{
            ino_t ino; /* such as 16 */
            char  name[256]; /* "200" */
      }
    

    inode结构可能像:

       struct inode{ /* inode number 15 */ 
             link_t nlink; /* nlink = 2 */
             ...
        }
    
       struct inode{ /* inode number 16 */
             link_t nlink; /* nlink = 1 */
             ...
        } /* the data of inode 16 maybe /1 or 1 */
    

    #17楼

    我刚刚找到了一种简单的方法来理解常见场景中的硬链接,即软件安装。

    有一天,我将软件Downloads到文件夹Downloads以进行安装。 我做了后sudo make install ,一些可执行文件是cp版到本地bin文件夹。 在这里, cp创建了硬链接 。 我对软件很满意,但很快意识到从长远来看, Downloads不是一个好地方。 所以,我mv编软件的文件夹source目录。 好吧,我仍然可以像以前一样运行软件而不必担心任何目标链接的东西,比如在Windows中。 这意味着硬链接直接找到inode和其他文件。


    #18楼

    硬链接与软链接

    硬链接Vs软链接可以通过此图像轻松解释。


    #19楼

    在这个答案当我说一个文件,我的意思是在内存中的位置

    保存的所有数据都使用称为inode的数据结构存储在内存中。每个inode都有一个inodeumber .inode号用于访问inode。所有到文件的硬链接可能有不同的名称但共享相同的inode编号。由于所有硬链接具有相同的inodenumber(其中访问相同的inode),所以它们都指向相同的物理内存。

    符号链接是一种特殊的文件。因为它也是一个文件,它将有一个文件名和一个inode号。如上所述,inode号接受一个指向data的inode。现在使符号链接特殊的是符号链接中的inodenumbers访问指向另一个文件的“路径”的那些inode。更具体地说,符号链接中的inode号接收指向另一个硬链接的那些inode。

    当我们在GUI中移动,复制,删除文件时,我们正在使用文件的硬链接而不是物理内存。当我们删除文件时,我们正在删除文件的硬链接。 我们没有消灭物理内存。如果文件的所有硬链接都被删除,那么虽然它可能仍然存在于内存中,但是无法访问存储的数据


    #20楼

    我使用的两分钱:

    链接可用于缩短长路径名称,即:

    ln -s /long/folder/name/on/long/path/file.txt /short/file.txt
    

    /short/file.txt所做的更改将应用​​于原始文件。

    链接可用于移动大文件:

    $ ls -lh /myapp/dev/
    total 10G
    -rw-r--r-- 2 root root 10G May 22 12:09 application.bin
    

    ln /myapp/dev/application.bin /myapp/prd/application.bin

    即时复制到不同的文件夹,可以移动或删除原始文件(在/myapp/dev ),而不触及/myapp/prd上的文件


    #21楼

    除了以上所有答案之外,查找硬链接和软链接文件的区别可以理解如下:

    我当前目录中有一个文件f6 ,以及一个名为t2的目录。

    名为f1./t2/f2文件是f6符号链接。

    名为f7./t2/f8文件是f6硬链接。

    要查找软链接和硬链接,我们可以使用:

    $ find -L . -samefile f6 
    
    > ./f1
    > ./f6
    > ./f7
    > ./t2/f2
    > ./t2/f8
    

    要仅查找硬链接,我们可以使用:

    $ find . -xdev -samefile f6
    
    > ./f6
    > ./f7
    > ./t2/f8
    

    由于可以在同一文件系统上创建硬链接,因此我们可以在同一文件系统/挂载点中搜索所有未使用-L选项(带-xdev选项)的-xdev 。 它将不必要的搜索保存到不同的挂载点。

    因此,搜索硬链接比搜索软链接要快一些(如果我错了或不清楚,请纠正)。

    展开全文
  • 符号链接和硬链接,静态库和动态库

    千次阅读 2018-05-15 16:05:45
    而且目录不允许创建硬链接,但可以创建软连接,我们用vim 打开一个目录,发现里面的内容是该目录里面的文件名,其实目录也是一个文件,目录文件在磁盘上的数据区中保存的是它里面的文件名文件的inode的映射关系。...

    这里只是要求简单理解
    操作系统是如何管理文件的,我们用stat命令查看一个文件的相关信息

    解释上面文件信息中的三个时间(acm):
    Access:最后访问时间
    Change:属性最后改变时间(inode)
    Modify:文件内容最后修改时间

    inode  存放文件元信息
    文件是如何在磁盘上存放的呢,
    i节点表中存放文件的inode,其实我们创建一个文件就会为这个文件分配一个inode标号
    我们访问一个文件其实就是找到这个文件的inode编号,

    创建一个文件的基本步骤:
    1.存储属性
    内核先找到一个空闲的i节点,把文件记录到其中

    2.存储数据
    该文件需要三个数据块来存放数据,就在数据块中找到三个空闲的空闲块,内核将数据依次复制到这几个空闲块中

    3.记录分配情况
    在磁盘上记录上面三个数据块列表
    4.添加文件名到目录
    内核将入口(inode 编号,文件名)添加到目录文件,文件名和inode之间的对应关系将文件名和文件内容及属性连接起来。

    硬链接
    我们知道找文件其实就是找到文件的inode ,那么如果两个文件的inode相同,所对应的文件也是相同的,
    硬链接就是这样实现的,创建一个文件的硬链接其实就是将硬链接数加1,在删除的时候,只是将硬链接数减1,只有当硬链接数为0的时候,才会将这个inode 删除。

    硬链接是通过inode 引用另外一个文件

    软链接(符号链接)

    软连接是通过文件名引用另外一个文件
    软链接其实是将这个文件的全路径保存下来,如果将原文件删除,软连接文件就不能访问了


    目录创建下来,它的硬链接数默认为2,而且目录不允许创建硬链接,但可以创建软连接,我们用vim 打开一个目录,发现里面的内容是该目录里面的文件名,其实目录也是一个文件,目录文件在磁盘上的数据区中保存的是它里面的文件名和文件的inode的映射关系。
    Windos 下的快捷方式即为Linux下的软连接。

    二、静态库和动态库

    静态库:程序在编译时把库中的代码链接到可执行文件中,程序运行时不再需要静态库(后缀为.a)

    动态库:在程序运行的过程中才去链接动态库到可执行文件中,多个程序共享使用库的代码 (后缀为.so)
    假设现在有两个进程都依赖于某个动态库,当程序2要将动态库加载到内存时,会先检查内存中有没有这个动态库,如果已经存在,就将自己页表与该块内存建立映射关系。

    使用ldd命令查看可执行程序所依赖的动态库


    这里有一个libc.so 就是我们C标准库,操作系统的多数程序都是依赖C库,但我们为将libc.so进行删除后,会发现,很多命令都不能正常执行了,但是内建指令还是可以的,因为内建指令是父进程调用在系统函数执行了,并没有进行创建子进程进行程序替换,没有依赖于C库。

    现在来自己实现一个静态库:


    这里用到的生成静态库的的指令
    ar -rc lib***.a test1.o  test2.o//静态库的名称为以lib开始,以.a结束

    使用静态库的方法除了上面的使用静态库的完整名字方法外。还有一种

    gcc -o test test.c libadd.a//使用完整名字gcc -o test test.c -L. -ladd使用路径
    //-L后面接路径, -l后面接库到名字(去掉lib和.a)

    如何生成动态库.
    因为链接动态库是在进程运行期间才加载的。所以这里有一个环境变量指定了到哪个目录下去找动态库

    LD_LIBRARY_PATH
    所以我们先将这个路径该为当前路径

    我们看到这里的 
     gcc add.c -o libadd.so -fPIC -shared   //这里有两个选项是用来创建动态库的

    展开全文
  • 符号链接和硬链接的区别

    千次阅读 2015-09-20 12:10:58
    (1)创建一个硬链接 可以使用命令ln或者函数link()为文件创建一个链接。 #include  int link( const char *path1, const char *path2 ); 硬链接本身就是一个目录项,(比如文件名+索引节点...
  • 存在2众不同类型的链接,软链接和硬链接,修改其中一个,硬链接指向的是节点(inode),软链接指向的是路径(path) 软连接文件 软连接文件也叫符号连接,这个文件包含了另一个文件的路径名,类似于win下的快捷方式...
  • <br />存在两种不同类型的链接,软链接和硬链接。修改其中一个,硬连接指向的是节点(inode),而软连接指向的是路径(path) 软链接文件  软链接又叫符号链接,这个文件包含了另一个文件的路径名。可以...
  • 这些内容是文件中的实际内容分开放的。 文件的属性是放在叫做 i节点的结构中 ,而文件内容则放在数据块中。 这个 inode(i节点) block(数据块)是文件系统一开始就规划好的,并且不会改变(除非你格式化)。 ...
  • Linux的符号链接(软连接)和硬链接 Linux 链接概念 Linux 链接分两种,一种被称为硬链接( Hard Link ),另一种被称为符号链接( Symbolic Link )。 默认情况下, ln 命令产生硬链接。 ...
  • inode谁谁一样,谁谁不一样 ? 为什么? 4.  问: 执行unlink b命令会怎样?剩下的a,c情况如何? 为什么? 执行unlink c命令会怎样?剩下的a情况如何? 为什么? 执行unlink a命令会怎样? 为什么? 奖品: ...
  • 硬链接和符号链接详解

    千次阅读 多人点赞 2018-08-10 08:38:53
    建立硬链接时,链接文件被链接文件必须位于同一个文件系统中,并且不能建立指向目录的硬链接。而对符号链接,则不存在这个问题。默认情况下,ln产生硬链接。 在硬链接的情况下,参数中的“目标”被链接至[链接名]...
  • 硬链接和符号链接

    2014-04-30 10:03:54
    UNIX目录中有2中类型的链接——硬链接和符号链接。   硬链接本身就是一个目录项,(比如文件名+索引节点号),可以将文件名与文件的位置关联起来; 符号链接也称软链接,是指存储了一个字符串的文件。这个字符串...
  • 一 符号链接和硬链接的区别: (一)符号链接(软链接): 1.符号链接是指向一个文件的间接指针;符号链接文件本身保存的是源文件的存放路径。 2.删除源文件后,符号链接将失去意义。 3.可以创建对文件和目录的符号链接...
  • 符号链接硬链接

    2013-03-29 19:49:21
    符号链接(Symbolic link) windows下执行命令 mklink link_name target_name, linux下执行 ln -s创建链接后的图标快捷方式很像在系统中不占用空间在文件系统中不是一个单独的文件...硬链接(Hard link) wind
  • linux 硬链接和符号链接

    千次阅读 2018-07-25 15:44:42
     硬链接和符号链接比起来,硬链接是最初 Unix 创建链接的方式,而符号链接更加现代。在默认情况下,每个文件都有一个硬链接,这个硬链接给文件起名字。当我们创建一个硬链接以后,就为文件创建了一个额外的目录条目。硬...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 46,744
精华内容 18,697
关键字:

符号链接和硬链接