创建硬链接的函数:
相关函数:symlink, unlink
头文件:#include <unistd.h>
定义函数:int link (const char * oldpath, const char * newpath);
函数说明:link函数中oldpath指定已经存在文件,newpath指定的名称建立一个新的连接(硬链接),若是newpath指定的文件已存在则不会建立连接;
头文件:#include <unistd.h>
定义函数:int unlink(const char * pathname);
unlink()会删除参数pathname 指定的文件. 如果该文件名为最后连接点, 但有其他进程打开了此文件, 则在所有关于此文件的文件描述词皆关闭后才会删除. 如果参数pathname 为一符号连接, 则此连接会被删除。
硬链接创建条件,创建的除非是root用户,否则创建硬链接只能是针对文件名字;
创建硬链接必须在同一个分区;
只有超级用户才能够对目录创建硬链接;
硬链接文件删除的过程是删除文件计数,文件硬链接计数为0的时候会删除文件,但是前提条件是没有其他进程打开该文件。
创建硬链接使用的命令: ln oldfilename newfilename
andrew@andrew-Thurley:~/work/filedir$ ls -l name
-rw-rw-r-- 2 andrew andrew 43 8月 22 21:33 name
andrew@andrew-Thurley:~/work/filedir$ ls date.txt
date.txt
andrew@andrew-Thurley:~/work/filedir$ ls -l date.txt
-rw-rw-r-- 2 andrew andrew 43 8月 22 21:33 date.txt
andrew@andrew-Thurley:~/work/filedir$ ls -l a.out
-rwxrwxr-x 1 andrew andrew 8840 8月 24 23:10 a.out
andrew@andrew-Thurley:~/work/filedir$
创建硬链接之后显示硬链接文件是一个普通的文件,其中在权限说明之后显示的 的数字2说明的是文件的链接数。
-rwxrwxr-x 第一个 ‘-’指的是普通文件,然后徐后面的是,r可读,w可写,x可执行,分别u+g+o
若是删除源文件,硬链接还是能够看到文件的内容
硬链接创建共享同一个 i节点但是软连接创建的时候会生成自己的 i 节点。
创建硬链接只是创建了文件的连接数,有硬链接的文件当删除源文件的时候删除的只是文件的连接计数,并没有删除磁盘上的文件,创建硬链接也会造成连接数加1。删除文件的实质就是将文件的硬链接数减少到0,所以硬链接虽然没有在磁盘上创建文件,但是硬链接出来的文件名是跟源文件名同等的。
#include<unistd.h>
int symlink(const char*actualpath,const char *sympath);
#include <fcntl.h> /* Definition of AT_* constants */
#include <unistd.h>
int symlinkat(const char *actualpath,int fd,const char *sympath);
两个函数返回值:若成功,返回0;若出错,返回-1
两个函数返回值:若成功,返回0;若出错,返回-1
ssize_t readlink(const char* restrict pathname,char *restrict buf,size_t bufsize);
ssize_t readlinkat(int fd,const char* restrict pathname,char *restrict buf,size_t bufsize);
两个函数返回值:若成功,返回读取的字节数;若出错,返回-1
symlink函数创建了一个指向actualpath的新目录项sympath。在创建此符号链接时,并不要求actualpath已经存在。并且actualpath和sympath并不需要位于同一文件系统中。
symlinkat函数与symlink函数类似,但sympath参数根据相对于打开文件描述符引用的目录(由fd指定)进行计算。如果sympath参数指定的是绝对路径或者fd参数设置了AT_FDCWD值,那么symlinkat就等同于symlink函数。
readlink和readlinkat函数组合了open、read和close的所有操作。如果函数成功执行,则返回读入buf的字节数。在buf中返回的符号链接的内容不以null字符终止。
当pathname参数指定的是绝对路径名或者fd参数的值为AT_FDCWD,readlinkat函数的行为与readlink相同。但是,如果fd参数是一个打开目录的有效文件描述符并且pathname参数是相对路径名,则readlinkat计算相对于由fd代表的打开目录的路径。
创建软连接:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <dirent.h>
#define BUFFSIZE 1024
int main(int argc,char *argv[])
{
if(argc != 4){
printf("param too few\n");
exit(EXIT_FAILURE);
}
char buf[BUFFSIZE];
ssize_t sz;
DIR *dp;
int fd;
//获取相对路径名返回的文件描述符fd
if((dp = opendir(argv[2])) == NULL){
perror("opendir");
exit(EXIT_FAILURE);
}
if((fd = dirfd(dp)) < 0){
perror("dirfd");
exit(EXIT_FAILURE);
}
//创建符号链接
if(symlinkat(argv[1],fd,argv[3]) < 0){
perror("symlinkat");
exit(EXIT_FAILURE);
}
//读取符号链接
bzero(buf,sizeof(buf));
if((sz = readlinkat(fd,argv[3],buf,sizeof(buf))) < 0){
perror("readlinkat");
exit(EXIT_FAILURE);
}
printf("buf:%s,length:%u\n",buf,(unsigned int)sz);
close(fd);
return 0;
}
创建软连接:使用 ln -s oldfilename newfilename
andrew@andrew-Thurley:~/work/filedir$ ln -s date1.txt s1_l
andrew@andrew-Thurley:~/work/filedir$ ls -l date1.txt s1_l
-rw-rw-r-- 1 andrew andrew 43 8月 25 00:03 date1.txt
lrwxrwxrwx 1 andrew andrew 9 8月 25 00:04 s1_l -> date1.txt
andrew@andrew-Thurley:~/work/filedir$
删除源文件软连接,就不能查看文件的内容,会提示是没有那个文件或目录;
创建软连接之后文件显示的文件连接数还是1
软连接就像windows上创建一个快捷方式一样;并且软连接会显示文件的类型是 l 也就是说明 文件是连接型的文件
软连接我文件创建可以跨分区创建符号连接,创建符号链接并不要求actualpath即原文件一定存在。
如图,左边是硬链接,右边是软连接;
硬链接只创建了目录项然后使i节点的硬链接计数加1,删除的时候也只是对i节点的连接计数减1, 软连接创建了目录项,i节点,数据块,但是数据块中存放的不是
源文件内容的复制,存放的是源文件路径,因此当源文件删除的时候,再去使用软连接软连接文件将提示文件不存在或已删除。
相关函数:
#include <stdio.h>
#include <unistd.h>
int remove(const char *pathname);
对于文件remove的左右和unlink的作用是一样的,但是对于目录来说使用remove相当于使用rmdir 即删除目录。
#include <stdio.h>
int rename(char * oldname, char * newname);
函数rename()用于重命名文件、改变文件路径或更改目录名称。
oldname为旧文件名,newname为新文件名。
修改文件名成功则返回0,否则返回-1。
重命名文件:
如果newname指定的文件存在,则会被删除。
如果newname与oldname不在一个目录下,则相当于移动文件。
重命名目录:
如果oldname和oldname都为目录,则重命名目录。
如果newname指定的目录存在且为空目录,则先将newname删除。
对于newname和oldname两个目录,调用进程必须有写权限。
重命名目录时,newname不能包含oldname作为其路径前缀。例如,不能将/usr更名为/usr/foo/testdir,因为老名字( /usr/foo)是新名字的路径前缀,因而不能将其删除。