Linux之链接
一、链接以及基础知识
本章导读中给大家稍微提了一下的是硬链接,在介绍前面 stat 函数提到过符号链接,不过这硬链接,符号链接和链接完全不是一回事。
在 linux 中,文件目录包含文件名列表,每一个文件名对应一个 inode 编号。每个文件名叫目录项,每个名字到 inode 的映射叫链接。
类似 windows 下的快捷方式叫做符号链接(软连接)和硬链接。虽然有点绕口,但是在 linux 编程的书籍在最开始就是这么翻译过来的,能够理解就行了。
前面强调过在 linux 系统中每一个 inode 都是唯一的,但是发现,如下图所示,在最小系统下使用命令“ls -i”,会发现两个相同的 inode。
其实这就是硬链接,硬链接的个数可以是多个。
和硬链接对应的是软链接,也可以叫符号链接或者symlinks,软连接不是文件系统的文件名和 inode 的映射,而是一种指针,在运行的时候解释。
在 linux 命令中,有 ln 命令可以创建链接,如下图所示,使用“man ln”查看一下。
如上图所示,可以看到关于ln的功能描述。它是用来创建一个TARGET到真实的文件的link(链接)。这也算是 linux 中一种特殊的文件,就像 windows 下的快捷方式,也属于 window下的文件。
二、硬链接 link
1、使用 man 学习 link 函数
如下图所示,使用命令“man 2 link”。
最后介绍一下 link 函数。
int link(const char *oldpath, const char *newpath);
//参数*oldpath:已有的文件路径。
//参数*newpath:新建的硬链接文件路径。
//返回值:成功返回 0,错误返回-1。
2、函数例程
编写简单的 link.c 文件测试 link 函数。
#include <stdio.h>
//link函数头文件
#include <unistd.h>
int main(int argc,char *argv[])
{
int ret;
if(argc <3){
printf("\nPlease input file path\n");
return 1;
}
//测试link函数
ret = link(argv[1],argv[2]);
if(ret)
{
printf("link failed");
return 1;
}
printf("link %s to %s success!\n",argv[1],argv[2]);
return 0;
}
3、运行结果
如下图所示,使用 vi 编辑器新建一个 linktest.c 文件。文件中内容为“hello linux link!”
接着运行程序,如下图所示。
然后使用 ls -i命令查看,如下图所示。
如上图所示,可以看到硬链接建立的完全一样的文件,inode 是相同的。
使用 vi 命令打开 linktest,查看其中的内容。如下图所示,一模一样。
三、符号链接 symlink
1、使用 man 学习 symlink 函数
如下图所示,使用命令“man 2 symlink”。函数 symlink 和 link 函数用法差不多。
接着介绍一下 symlink 的用法。
int symlink(const char *oldpath, const char *newpath);
//参数*oldpath:已有的文件路径。
//参数*newpath:新建的符号链接文件路径。
//返回值:成功返回 0,错误返回-1。
2、函数例程
编写简单的 symlink.c 文件测试 symlink 函数。
#include <stdio.h>
//symlink函数头文件
#include <unistd.h>
int main(int argc,char *argv[])
{
int ret;
if(argc <3){
printf("\nPlease input file path\n");
return 1;
}
//测试symlink函数
ret = symlink(argv[1],argv[2]);
if(ret)
{
printf("symlink failed");
return 1;
}
printf("symlink %s to %s success!\n",argv[1],argv[2]);
return 0;
}
3、运行结果
使用程序给前一个实验中 linktest.c 文件建立软连接,如下图所示。运行程序如下。
如下图所示,使用 ls 命令查看新建的软连接文件,可以发现和之前的并不是同一个文件,inode 不一样,说明是不同的文件。
使用命令vi symlink.c打开之后也是显示同样的内容,如下图所示。
四、解除链接 unlink
1、 使用 man 学习 unlink 函数
如下图所示,使用命令“ man 2 unlink”。
接着介绍一下 unlinke 的用法。
int unlink(const char *pathname);参数:
//参数*pathname:链接文件的路径。
//返回值:成功返回 0,错误返回-1。
//当 unlink 指向的是软链接,则会删除软链接,不会删除目标文件。
//当 unlink 指向的是硬链接,如果,如果是最后一个链接,则就相当于删除了文件。
另外还有一个 remove 函数,可以直接用来删除 path。
如果 path 是目录则 remove 调用 rmdir。
如果 path 是文件则 remove 调用 unlink。
2、函数例程
编写简单的 unlink.c 文件测试 unlink 函数。
#include <stdio.h>
//unlink函数头文件
#include <unistd.h>
int main(int argc,char *argv[])
{
int ret;
if(argc <2){
printf("\nPlease input file path\n");
return 1;
}
//测试unlink函数
ret = unlink(argv[1]);
if(ret)
{
printf("unlink failed");
return 1;
}
printf("unlink %s is success!\n",argv[1]);
return 0;
}
3、运行结果
运行程序如下所示,这里取消了前一个实验建立的软连接文件。
五、拷贝文件
文件处理中拷贝和移动文件是最基本的操作。可以通过 cp 命令和 mv 命令实现。mv 可以理解为“重命名”;
cp 拷贝要注意和创建硬链接区分开来,硬链接的 inode 是相同,它们是同一个文件,但是 cp 拷贝之后,inode 索引节点是不同的,它们是不同的文件。
1、拷贝简介
Linux 下并没有专门的拷贝函数和接口,需要通过 open,read,wite 等文件操作函数实现。
如下图所示,是 linux 下拷贝的流程图。
一般步骤是 open 之后将数据读至内存,然后写入新的文件。
2、拷贝例程
编写简单的 cpfile.c 文件完成拷贝功能。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
//argv[1] is oldpath ; argv[2] is newpath
#define LENTH 1024
int main(int argc,char *argv[])
{
int fds,fdt;
char buffer[LENTH];
char *fileold,*filenew;
fileold = argv[1];
filenew = argv[2];
if(argc <3){
printf("\nPlease input file path\n");
return 1;
}
//打开oldpath
fds = open(fileold,O_RDWR);
if(fds<0)
{
printf("Please make sure file path\n");
return 1;
}
//打开newpath,如果没有则创建目标文件
fdt = open(filenew,O_WRONLY|O_CREAT);
if(fdt<0)
{
printf("Please make sure file path\n");
return 1;
}
//读和写操作
while(read(fds,buffer,LENTH)){
write(fdt,buffer,strlen(buffer));
}
//关闭文件
close(fds);
close(fdt);
printf("cp to finished!\n");
printf("cp %s to %s success!\n",fileold,filenew);
return 0;
}
3、运行结果
运行程序如下图所示,用到了前面实验建立的 linktest.c 文件。
接着查看一下 cptest 文件,和原来的 linktest.c 不是同一个文件。
打开复制生成的 cptest 文件,内容没变,如下图所示。
六、移动文件
1、使用 man 学习 rename 函数
Linux 下移动文件可以使用 rename 实现。如下图所示,使用命令“man 2 rename”,查看 rename 文档。
最后介绍一下 rename 函数。
int rename(const char *oldpath, const char *newpath);
//参数*oldpath:旧的文件路径。
//参数*newpath:新的文件路径。
//返回值:成功返回 0,错误返回-1。
2、函数例程
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
//argv[1] is oldpath ; argv[2] is newpath
int main(int argc,char *argv[])
{
int ret;
if(argc < 3){
printf("\nPlease input file path\n");
return 1;
}
if(ret = rename(argv[1],argv[2])){
printf("\nerr\n");
}
printf("rename %s to %s success!\n",argv[1],argv[2]);
return 0;
}
3、运行结果
运行程序如下。
接着使用 ls 命令查看,有新的 renametest 文件,原来的文件 cptes 消失了。