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 消失了。