Linuxunlink函数和删除⽂件的操作⽅法
1. unlink函数
  对于硬链接来说,unlink ⽤来删除⽬录项,并把 inode 引⽤计数减 1,这两步也是⼀个原⼦过程。直到 inode 引⽤计数为0,才会真正删除⽂件。
  对于软链接来说,unlink 直接删除软链接,⽽不影响软链接指向的⽂件。
函数原型:
int unlink(const char *pathname);
参数说明:
  pathname:指定要移除的链接⽂件
返回值说明:
  成功返回0;失败则返回-1,同时设置errno为相应值
2. 实验代码—myunlink
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[]){
//为⼀个已经存在的⽂件创建⽬录项(硬链接)
if(link(argv[1], argv[2]) == -1){
perror("link error");
exit(1);
}
//删除之前的⽂件⽬录项
if(unlink(argv[1]) == -1){
perror("unlink error");
exit(1);
}
return 0;
}
  当我们执⾏./myunlink hellotest命令完后,会删除 hellotest,同时 inode 引⽤计数减 1。
3. 删除⽂件
  不⽤说,相信⼤家都⽤过rm -rf命令吧。
  现在我们再来思考⼀下,以前我们通过rm命令删除⽂件时你有没有质疑过,⽂件真的被删除掉了吗?
  如果真的删除的了话,那么操作系统⼜是怎么把⽂件删除掉的?
  操作系统在设计的时候是通过把⽂件的inode索引号与磁盘中的block块建⽴了关联,这样我们通过⽂件到block块的位置,也就看到了⽂件的数据了。
  在删除⽂件时,是由系统的2个变量来控制的⼀个是i_link,表⽰⽂件的硬链接数量,另⼀个是i_count,表⽰⽂件的引⽤计数,⽂件删除的必需条件就是i_link = 0和i_count = 0。
  在磁盘中的⽂件只要把i_link = 0(硬链接数⼲掉)就可以把⽂件删除了,如果这个⽂件在程序中被打开,我们还需要把运⾏的程序⼲掉 i_count = 0,这样才能达到删除⽂件的⽬的。
4. linux下删除⽂件的⼤概过程
  linux下⽂件删除过程⼤概如图:
图1-linux下⽂件删除的⼤概过程
  当前磁盘中的/test/file⽬录下有⼀个test⽂件(i_link = 1),还有⼀个硬链接⽂件hard_link指向test⽂件(i_link = 1),且./test进程⼜打开了test⽂件(i_count = 1),如果要删除⽂件,必须把./test进程⼲掉(i_count = 0),然后删除hard_link硬链接⽂件和/test/file⽬录下的⽂件(也就是让i_link = 0)。
  也就是说linux下是通过link的数量来控制⽂件删除的,当⼀个⽂件的link = 0时,这个⽂件才会被删除。⼀般⼀个⽂件有2个link计数器,⼀个是i_link和i_count。
  i_count是当前进程打开⽂件的引⽤计数,i_link是⽂件链接的数量,可以把i_count理解为内存中⽂件的
计数器,⽽i_link 是磁盘中的计数器。对于rm命令来说实际就是设置磁盘中⽂件的i_link计数为0。如果⼀个⽂件被进程所使⽤,⽽⽤户⼜执⾏了rm命令把⽂件删除掉了,此时程序还能正常执⾏,依旧能从⽂件中读取正确的数据,这是因为rm命令只是把i_link设置为
0(是将⽂件到inode的关联断开,并没有删除掉inode与磁盘中的block数据块,此时停⽌进程,被删除的数据可以回来,如果进程正在写⼊数据,那么磁盘的block块的数据会被进程写⼊的数据覆盖掉,原先的数据就恢复不了了)。
  ⽽进程仍然在引⽤该⽂件i_count = 1,执⾏rm命令系统并不会真正的删除该⽂件,如果要删除该⽂件必须让进程解除对该⽂件的引⽤计数,也就是把进程⼲掉,这样⽂件才会被真正的删除掉。
  即便如此,⽂件真的被删除了吗?前⾯我们说过⽂件的数据是存储在磁盘上block块中,当我们要查⽂件当中的数据时并不是直接到磁盘上的block块,因为磁盘上的block块实在是太多了,你怎么就知道你的数据存储在哪个block块中?
  假设你⼀不⼩⼼把⾮常重要的数据删除掉了,这将意味着你的数据就永远也不回来了,从⽽造成⽆法挽回的损失了,由此可见数据的重要性,因此操作系统不会轻易把数据从磁盘中真正的删除掉。
  看到这⾥,相信你已经明⽩了,实际上你所谓的右键删除操作只是把⽂件的inode索引号与磁盘中的blo
ck的关联断开了⽽已,但⽂件的数据并没有真正的被删除掉。如果你想真的删除数据的话,要么把磁盘格式化,要么把原先的数据删除掉,然后写⼊新的数据覆盖掉,当然,你也可以选择格式化和数据覆盖双重保险,这个时候你的数据想要恢复基本上是⾮常困难的,即便可以顶多只能恢复⼀部分数据了吧。
  如果你真的⼀不⼩⼼删除了很重要的数据的话,这个时候赶紧恢复数据,其他的任何多余的操作尽量不要做,这样在数据恢复过程中才能尽量减少数据丢失。
5. myunlink2.c程序
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
/*
unlink函数是删除⼀个dentry
*/
int main(void){
int fd;
char *p = "test of unlink\n";
char *p2 = "after write something.\n";
//当进程打开⽂件时,引⽤计数会+1
fd = open("", O_RDWR|O_CREAT|O_TRUNC, 0644);
if(fd < 0){
perror("open temp error");
exit(1);
}
//具备了被释放的条件
int ret = unlink("");
if(ret < 0){
perror("unlink error");
exit(1);
}
//向⽂件写⼊第⼀个字符串,通过返回值判断写操作是否成功
ret = write(fd, p, strlen(p));
if (ret == -1) {
perror("-----write error");
}
printf("hi! I'm printf\n");
//向⽂件写⼊第⼆个字符串,通过返回值判断写操作是否成功
ret = write(fd, p2, strlen(p2));
if (ret == -1) {
perror("-----write error");
}
printf("Enter anykey continue\n");
getchar();
trunc函数是什么
//当close关闭fd的时候,进程对⽂件的引⽤计数就会-1,断开进程与⽂件的关联关系
close(fd);
return 0;
}
程序运⾏结果:
  程序的运⾏结果和我们所预料的⼀样,当程序运⾏的时候,调⽤open函数创建并打开了⽂件,此时进程对temp⽂件的引⽤计数i_count会加1,同时temp⽂件本⾝也会有⼀个i_link链接计数也会加1。
  当调⽤了unlink函数删除temp⽂件时,只是把i_link链接计数减1,⽽进程的i_count计数还是1,并没有断开与temp⽂件的关联关系,因此进程可以调⽤write函数往temp⽂件⾥⾯写数据,⾃然也就能成功了。当程序运⾏结束后,调⽤close关闭对temp⽂件的引⽤,此时temp⽂件就会被操作系统删除掉。
6. 总结
  在不了解⽂件系统原理的情况下,通常我们会认为数据已经删除掉,其实不然,磁盘上的⽂件数据还在,只是把dentry⽬录和磁盘上的数据的联系断开,我们不到数据肯定会认为删掉了,但是只要我们想办法让数据和dentry⽬录之间重新建⽴连接,就可以让删除的数据恢复。
  因此我们删除⽂件,从某种意义上说,只是让⽂件具备了被释放的条件,⾄于什么时候释放这取决于操作系统。
  对于unlink函数来说,清除⽂件时,如果⽂件的硬链接数到0了,没有dentry对应,但该⽂件仍不会马上被释放。要等到所有打开该⽂件的进程关闭该⽂件,系统才会挑时间将该⽂件释放掉。
7. 不要随便使⽤rm命令
  相信看到这⾥,你应该知道了,数据对于计算机的重要性了,因为⼀旦某些⾄关重要的数据删除了,那就真的永远没了,这也是操作系统为什么不直接将数据从磁盘中删除的原因。但也不要因为这样,你就可以肆⽆忌惮的使⽤rm命令了,因为有时候数据删除了,并不能百分百的恢复回来。
总结
以上所述是⼩编给⼤家介绍的Linux unlink函数和删除⽂件的操作⽅法,希望对⼤家有所帮助,也⾮常感谢⼤家对⽹站的⽀持!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。