Perl中Cwd::cwd
和Cwd::getcwd
之间的区别是什么,通常不考虑任何特定平台?为什么Perl都有?什么是预期用途,我应该在哪些场景中使用哪一个? (示例用例将受到赞赏。)这有关系吗? (假设我不混合它们。)任何一个的选择是否会以任何方式影响可移植性?哪一个更常用于模块?
即使我解读说明书,除了角落案例cwd
`pwd`
和getcwd
只是从getcwd
拨打unistd.h
之外,是什么实际差异?无论如何,这仅适用于POSIX系统。
我总是可以阅读实现,但这并没有告诉我这些功能的含义。实施细节可能会发生变化,而非定义的含义。 (否则会发生重大变化,这是一项严肃的事情。)
引用Perl的Cwd module manpage:
每个函数都不带参数调用,并返回当前工作目录的绝对路径。
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. $^O
值分别为Mac OS和OS X MacOS
和darwin
。 谢谢,@tobyink和@ikegami。
还有一个小问题:如何避免对功能非常相似的其他模块提出类似的问题?除了深入实施之外,是否存在发现差异的通用方法? (目前,我认为如果文档不清楚预期的用途和差异,我必须要求更有经验的人或自己阅读实施。)
答案 0 :(得分:9)
我认为这个想法是cwd()
总是解析为获取当前工作目录的外部特定于操作系统的方式。也就是说,在Linux上运行pwd
,在DOS上运行command /c cd
,在QNX中运行/usr/bin/fullpath -t
,依此类推 - 所有示例都来自实际的Cwd.pm
。 getcwd()
应该使用POSIX系统调用(如果可用),如果没有则返回cwd()
。
为什么我们两个都有?在当前的实现中,我认为只导出getcwd()
对于大多数系统来说已经足够了,但谁知道为什么“如果系统调用可用,使用它,否则运行cwd()
”的逻辑可能会在某些系统上失败(例如on MorphOS in Perl 5.6.1)。
在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不在奇怪的平台列表。)