博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
水煮coreutils之 rm
阅读量:4212 次
发布时间:2019-05-26

本文共 2195 字,大约阅读时间需要 7 分钟。

 前言:
    这是水煮coreutils 系列的第一篇,写下在读linux coreutils 代码的心得体会,随着难度的渐渐加大,不知道能把这个系列坚持到什么
时候,也许这是第一篇也就是最后一篇.
    coreutils 是linux系统中最接近我们日常使用的部分,rm cp ls cat 等命令皆发于此,最常用意味着最稳定,最高效,偶自认为
 目前不是看内核代码的那块料,那就从最基本的地方看起.
 rm [ -f ] [ -r ] [ -R ] [ -i ] [ -e ]  File
 其中 i 是问不问要删除,r和R 表达一个意思要递归删除,e是显示删除的内容,f 不是我们想像的强制删除只是有错误信息不做提示
 罢了.
 通过 getopt_long 获取参数,参数放在struct rm_options中,不包括文件名.
 那文件名是怎么获取的呢? 一个小技巧,以后在很多的应用程序中都会用到.
 size_t n_files = argc - optind;
    char const *const *file = (char const *const *) argv + optind;
 获取到文件名以后,要做的事情就是删除了
 enum RM_status status = rm (n_files, file, &x);
 现在我们来看rm函数的实现:
 在分析函数之前我们思考一下如果我们来实现这个函数,应当怎么做?
 删除文件用remove 或者 unlink 函数,删除目录用rmdir函数,那么我们要做的事情就是遇到文件删除文件,遇到目录进入目录删除
 文件,文件删除光光再出来删除目录,遇到删除不掉的就跳到上一级目录连着文件一起不删除.
 rm的实现其实也很简单,拿
   
for
 (i 
=
 
0
; i 
<
 n_files; i
++
)
    
{
      
enum RM_status s;
      cycle_check_init (
&ds->cycle_check_state);
      
/* In the event that rm_1->remove_dir->remove_cwd_entries detects
  a directory cycle, arrange to fail, give up on this FILE, but
  continue on with any other arguments.  
*/
      
if (setjmp (ds->current_arg_jumpbuf))
 s 
= RM_ERROR;
      
else
 s 
= rm_1 (ds, file[i], x, &cwd_state);
      assert (VALID_STATUS (s));
      UPDATE_STATUS (status, s);
    }
 注意一下这一句:setjmp (ds->current_arg_jumpbuf)
 在以后的过程中会有意想不到的效果.
 自顶向下 抽丝剥茧 偶们来到了 rm_1函数:
 它做的事情很简单 跳过 . .. 文件,remove_entry  删除文件,如果返回值为非空目录,那就删除目录remove_dir.
 判断文件是个有用的宏,记录一下
 #define DOT_OR_DOTDOT(Basename) /
  (Basename[0] == '.' && (Basename[1] == '/0' /
     || (Basename[1] == '.' && Basename[2] == '/0')))
 现在来看remove_entry:
 调用prompt,这个函数做多个事情,
 第一 迎合-i选项问你是否要删除
 第二 判断是否为目录,
 第三 目录是否为空
 返回值表达,如果为文件,链接,空目录等标志为可删除,如果为非空目录标志为非空目录,如果其它情况作为err返回.
 接下来对于可删除的的东西就开始删除了.
 来看remove_dir函数.
 这个函数采取的方法是用几个堆栈保持目录,文件状态,然后调用remove_cwd_entries  删除本目录的内容.
 那么来看remove_cwd_entries 函数
 从函数名来说就是把当前目录下的所有文件删除,很多人会认为这个是递归实现的,其实这个才是rm这个程序的精华部分,
 通过两个循环化解递归:
 这个是伪代码表示,表示个流程,还有复杂的堆栈操作,递归是函数的压栈,这里是把目录名压栈,一定程度上保留了系统资源.
 
removedir()
 
{
    
while(1)
 
{
    remove_cwd_entries(dir);
 }
 }
 
 remove_cwd_entries()
 
{
   
while(1)
   
{
      
if(isfile)
      rm(file) ;
    
if(isdir)
    
{
      chdir(dir)
   
break ;
    }
   }
 }
 
 细看代码我们可以学到很多有用的东西,很多很精巧的宏和函数,比如判断一个数是否2的n次方
 
static
 inline 
bool
is_power_of_two (unsigned 
int
 i)
{
  
return (i & (i - 1)) == 0;
}
这种用法也很好
memcpy(mempcpy(str,buf1,strlen(buf1)),buf2,strlen(buf2)
+
1
) ; 
 
   
 

转载地址:http://iskmi.baihongyu.com/

你可能感兴趣的文章
Google Web工具包 GWT
查看>>
材料与工程学科相关软件
查看>>
windows 下AdNDP 安装使用
查看>>
Project 2013项目管理教程(1):项目管理概述及预备
查看>>
ssh客户端后台运行
查看>>
【React Native】把现代web科技带给移动开发者(一)
查看>>
【GoLang】Web工作方式
查看>>
Launch Sublime Text 3 from the command line
查看>>
【数据库之mysql】mysql的安装(一)
查看>>
【数据库之mysql】 mysql 入门教程(二)
查看>>
【HTML5/CSS/JS】A list of Font Awesome icons and their CSS content values(一)
查看>>
【HTML5/CSS/JS】<br>与<p>标签区别(二)
查看>>
【HTML5/CSS/JS】开发跨平台应用工具的选择(三)
查看>>
【心灵鸡汤】Give it five minutes不要让一个好主意随风而去
查看>>
【React Native】Invariant Violation: Application AwesomeProject has not been registered
查看>>
【ReactNative】真机上无法调试 could not connect to development server
查看>>
【XCode 4.6】常用快捷键 特别是格式化代码ctrl+i
查看>>
【iOS游戏开发】icon那点事 之 实际应用(二)
查看>>
【iOS游戏开发】icon那点事 之 图标设计(三)
查看>>
【IOS游戏开发】之测试发布(Distribution)
查看>>