第三章_文件和目录 : 函数link、linkat、unlink、unlinkat和remove

硬链接&软连接

函数link、linkat、unlink、unlinkat和remove

任何一个文件可以有多个目录项指向其i节点。创建一个指向现有文件的链接的方法是使用link函数或linkat函数。

#include <unistd.h>
int link(const char *existingpath, const char * newpath);
int linkat(int efd, const char *existingpath, int nfd, const char * newpath, int flag); 
两个函数的返回值:若成功,返回0;若出错,返回-1

这两个函数创建一个新目录项newpath,它引用现有文件existingpath。如果newpath已经存在,则返回出错。只创建newpath中的最后一个分量,路径中的其他部分应当已经存在。

对于linkat函数,现有文件时通过efd和existingpath参数指定的,新的路径名是同过nfd和newpath参数指定的。默认情况下,如果两个路径名中的任何一个是相对路径,那么它需要通过相对应于对应的文件描述符进行计算。如果两个文件描述符中任一个设置为AT_FDCWD,那么相应的路径名(如果它是相对路径)就通过相对于当前目录进行计算。如果任一路径名是绝对路径,相应的文件描述符参数就会被忽略。

当现有文件时符号链接时,由flag参数来控制linkat函数是创建指向现有符号链接的链接还是创建指向现有符号链接所指向的文件的链接。如果在flag参数中设置了AT_SYMLINK_FOLLOW标志,就创建指向符号链接目标的链接。如果这个标志被清除了,则创建一个指向符号链接本身的链接。

创建新目录项和增加链接计数应当是一个原子操作。

虽然POSIX.1允许实现支持跨越文件系统的链接,但是大多数实现要求现有的和新建的两个路径名在同一个文件系统中。如果实现支持创建指向一个目录的硬链接,那么也仅限于超级用户才可以这样做。其理由是这样做可能在文件系统中形成循环,大多数处理文件系统的实用程序都不能处理这种情况。因此,很多系统实现不允许对于目录的硬链接。

测试程序

#include<stdio.h>
#include<unistd.h>
int main(int argc, char *argv[])
{
    if(3 != argc)
    {
        printf("reference error!\n");
        exit(0);
    }
    int res;
    res = link(argv[1], argv[2]);
    if(res)
    {
        printf("link error!\n");
    }
    return 0;
}

在这里插入图片描述

为了删除一个现有的目录项,可以调用unlink函数。

#include <unistd.h>
int unlink(const char *pathname);
int unlinkat(int fd, const char *pathname, int flag);
                  两个函数的返回值:若成功,返回0;若出错,返回-1

这两个函数删除目录项,并将由pathname所引用文件的链接计数减1.如果对该文件还有其他链接,则仍通过其他链接访问该文件的数据。如果出错,则不对该文件做任何更改。

我们前面已经提及,为了解除对文件的链接,必须对包含该目录项的目录具有写和执行权限。正如4.10节所述,如果对该目录设置了粘着位,则对该目录必须具有写权限,并且具备下面三个条件之一:

拥有该文件;
拥有该目录;
具有超级用户权限。

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

如果pathname参数是相对路径名,那么unlinkat函数计算相对于由fd文件描述符参数代表的目录的路径名。如果fd参数设置为AT_FDCWD,那么通过相对于调用进程的当前工作目录来计算路径名。如果pathname参数是绝对路径名,那么fd参数被忽略。

flag参数给出了一个方法,使函数进程可以改变unlinkat函数的默认行为。当AT_REMOVEDIR标志被设置时,unlinkat函数可以类似于rmdir一样删除目录。如果这个标志被清除,unlinkat和unlink执行同样的操作。

测试程序

#include<stdio.h>
#include<unistd.h>
int main(int argc, char *argv[])
{
    if(2 != argc)
    {
        printf("reference error!\n");
        exit(0);
    }
    int res;
    res = unlink(argv[1]);
    if(res)
    {
        printf("unlink error!\n");
    }
    return 0;
}

我们也可以用remove函数解除一个文件或目录的链接。对于文件,remove功能与unlink相同。对于目录,remove功能与rmdir相同

#include<stdio.h>
int remove(const char *pathname);

unlink是系统调用,而remove是库函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值