问题

通常,在不考虑任何特定平台的情况下,Perl中的Cwd::cwdCwd::getcwd有什么区别?为什么Perl两者都有?预期用途是什么?在哪种情况下应该使用哪种用途? (示例用例将不胜感激。)这有关系吗? (假设我没有混合使用。)选择其中一种会以任何方式影响便携性吗?模块中最常用的是哪一种?

即使我理解该手册是说除了特殊情况,cwd`pwd`,而getcwd只是从getcwd调用unistd.h,实际区别是什么?无论如何,这仅适用于POSIX系统。

我总是可以阅读实现,但是这些功能的含义并没有告诉我。实现细节可能会更改,而不是定义的含义。 (否则会发生重大变化,这是很严肃的事情。)

手册说什么

引用Perl的Cwd module manpage:



并在“注释”部分中:



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

1经典Mac OS,不是OSX。$^O的值分别是Mac OS和OS X的MacOSdarwin。谢谢,@tobyink@ikegami

还有一个元问题:如何避免对功能非常相似的其他模块提出相似的问题?除了深入研究实现之外,还有发现差异的通用方法吗? (当前,我认为如果文档尚不清楚预期的用途和区别,我必须请经验丰富的人或亲自阅读实现。)

最佳答案

一般来说

我认为想法是cwd()始终解析为获取当前工作目录的外部特定于操作系统的方式。也就是说,在Linux上运行pwd,在DOS上运行command /c cd,在QNX中运行/usr/bin/fullpath -t,依此类推-所有示例均来自实际的Cwd.pm。如果getcwd()可用,则应使用POSIX系统调用,否则不使用cwd()

为什么我们两者都有?在当前的实现中,我相信仅导出getcwd()就可以满足大多数系统的需要,但是谁知道为什么“如果有syscall可用,请使用它,否则运行cwd()”的逻辑在某些系统上可能会失败(例如on MorphOS in Perl 5.6.1)。

在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

使用getcwd():

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

阅读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;
    }
}

绩效基准

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

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

real    0m7.177s
user    0m0.380s
sys     0m1.440s

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

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

real    0m0.018s
user    0m0.009s
sys     0m0.008s

讨论,选择

但是,由于您通常不经常查询当前工作目录,因此这两个选项都将起作用-除非由于某种原因(由于与ulimit相关的其他原因,内存不足的情况而无法产生更多的进程),否则这两个选项都将起作用。

最后,关于选择使用哪个:对于Linux,我将始终使用getcwd()。我想如果您要编写将在某些真正奇怪的平台上运行的可移植代码段(当然,此处不包含Linux,OS X和Windows,则需要进行测试并选择要使用的功能)奇怪的平台列表)。

关于working-directory - Perl Cwd::cwd和Cwd::getcwd函数有何不同?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25219996/

10-09 01:53