Perl Cwd :: cwd和Cwd :: getcwd函数有何不同?

Pal*_*lec 11 perl working-directory getcwd perl5

这个问题

Cwd::cwdCwd::getcwdPerl有什么区别,一般来说,不考虑任何特定的平台?为什么Perl都有?什么是预期用途,我应该在哪些场景中使用?(示例用例将受到赞赏.)这有关系吗?(假设我不混合它们.)任何一个的选择是否会以任何方式影响可移植性?哪一个更常用于模块?

即使我解释手册说,除了极端情况cwd`pwd`,并getcwd只是调用getcwdunistd.h,有什么实际的区别?无论如何,这仅适用于POSIX系统.

我总是可以阅读实现,但这并没有告诉我这些函数的含义.实施细节可能会发生变化,而非定义的含义.(否则会发生重大变化,这是一项严肃的事情.)

手册说了什么

引用Perl的Cwd模块手册页:

这些函数中的每一个都不带参数调用,并返回当前工作目录的绝对路径.

  • GETCWD

    my $cwd = getcwd();

    返回当前工作目录.

    暴露POSIX函数getcwd(3)或重新实现它(如果它不可用).

  • CWD

    my $cwd = cwd();

    cwd()是当前架构最自然的形式.对于大多数系统,它与`pwd`相同(但没有尾随行终止符).

在Notes部分:

  • 事实上,在Mac OS上的getcwd(),fastgetcwd()fastcwd()功能都为所有别名cwd()功能,其中,在Mac OS,调用`pwd`.同样,该abs_path()函数是别名fast_abs_path()

好的,我知道在Mac OS 1上没有区别getcwd(),cwd()因为两者实际上归结为`pwd`.但是在其他平台上呢?(我对Debian Linux特别感兴趣.)


1经典的Mac OS,而不是OS X. $^OMacOSdarwin分别为Mac OS和OS X,.谢谢,@ tobyink@ikegami.

还有一个小问题:如何避免为具有非常相似功能的其他模块提出类似的问题?除了深入实施之外,是否存在发现差异的通用方法?(目前,我认为如果文档不清楚预期的用途和差异,我必须要求更有经验的人或自己阅读实施.)

afe*_*ter 9

一般来说

我认为这个想法cwd()总是解析为获取当前工作目录的外部特定于操作系统的方式.也就是说,pwd在Linux上,command /c cd在DOS上,/usr/bin/fullpath -t在QNX中运行,等等 - 所有示例都来自实际Cwd.pm.在getcwd()应该使用POSIX系统调用(如果可用),并回落到cwd()如果不.

为什么我们两个都有?在当前的实现中,我相信getcwd()对于大多数系统来说,导出就足够了,但谁知道为什么"if syscall可用,使用它,否则运行cwd()" 的逻辑可能在某些系统失败(例如在Perl 5.6.1中的MorphOS上) .

在Linux上

在Linux上,cwd()将运行`/bin/pwd`(实际上将执行二进制并获取其输出),同时getcwd()将发出getcwd(2)系统调用.

实际效果通过检查 strace

人们可以strace(1)用来看到实际行动:

使用cwd():

$ strace -f perl -MCwd -e 'cwd(); ' 2>&1 | grep execve
execve("/usr/bin/perl", ["perl", "-MCwd", "-e", "cwd(); "], [/* 27 vars */]) = 0
[pid 31276] execve("/bin/pwd", ["/bin/pwd"], [/* 27 vars */] <unfinished ...>
[pid 31276] <... execve resumed> )      = 0
Run Code Online (Sandbox Code Playgroud)

使用getcwd():

$ strace -f perl -MCwd -e 'getcwd(); ' 2>&1 | grep execve
execve("/usr/bin/perl", ["perl", "-MCwd", "-e", "getcwd(); "], [/* 27 vars */]) = 0
Run Code Online (Sandbox Code Playgroud)

阅读Cwd.pm来源

您可以查看源代码(Cwd.pm例如,在CPAN中),并查看Linux cwd()调用是否映射到_backtick_pwd,如顾名思义,调用pwd反向引号.

以下是Cwd.pm我的评论片段:

unless ($METHOD_MAP{$^O}{cwd} or defined &cwd) {
    ...
    # some logic to find the pwd binary here, $found_pwd_cmd is set to 1 on Linux
    ...
    if( $os eq 'MacOS' || $found_pwd_cmd )
    {
        *cwd = \&_backtick_pwd;  # on Linux we actually go here
    }
    else {
        *cwd = \&getcwd;
    }
}
Run Code Online (Sandbox Code Playgroud)

绩效基准

最后,两者之间的区别在于cwd(),调用另一个二进制文件,必须更慢.我们可以做一些性能测试:

$ time perl -MCwd -e 'for (1..10000) { cwd(); }'

real    0m7.177s
user    0m0.380s
sys     0m1.440s
Run Code Online (Sandbox Code Playgroud)

现在将它与系统调用进行比较:

$ time perl -MCwd -e 'for (1..10000) { getcwd(); }'

real    0m0.018s
user    0m0.009s
sys     0m0.008s
Run Code Online (Sandbox Code Playgroud)

讨论,选择

但由于您通常不经常查询当前工作目录,因此两个选项都可以正常工作 - 除非由于某些原因ulimit(内存不足等)导致无法生成任何其他进程.

最后,至于选择使用哪一个:对于Linux,我会一直使用getcwd().我想你需要进行测试并选择使用哪个函数,如果你要编写一个可以在一些非常奇怪的平台上运行的可移植代码(当然,在这里,Linux,OS X和Windows不在奇怪的平台列表).