问题
通常,在不考虑任何特定平台的情况下,Perl中的Cwd::cwd
和Cwd::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的MacOS
和darwin
。谢谢,@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/