一般来说
我认为这个想法是cwd()
始终解析为获取当前工作目录的外部、特定于操作系统的方式。也就是说,运行pwd
在Linux上,command /c cd
在DOS下,/usr/bin/fullpath -t
在 QNX 等中 - 所有示例均来自实际Cwd.pm
. The getcwd()
应该使用 POSIX 系统调用(如果可用),然后回退到cwd()
if not.
为什么我们两者都有?在当前的实施中,我相信导出只是getcwd()
对于大多数系统来说就足够了,但是谁知道为什么“如果系统调用可用,则使用它,否则运行”的逻辑cwd()
” 在某些系统上可能会失败(例如Perl 5.6.1 中的 MorphOS http://www.nntp.perl.org/group/perl.perl5.porters/2004/08/msg94261.html).
On Linux
在 Linux 上,cwd()
会跑`/bin/pwd`
(将实际执行二进制文件并获取其输出),而getcwd()
将发行getcwd(2)
系统调用。
实际效果通过查看strace
一个可以用strace(1)
看看它的实际效果:
Using 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
Using getcwd()
:
$ strace -f perl -MCwd -e 'getcwd(); ' 2>&1 | grep execve
execve("/usr/bin/perl", ["perl", "-MCwd", "-e", "getcwd(); "], [/* 27 vars */]) = 0
Reading Cwd.pm
source
您可以查看来源(Cwd.pm https://metacpan.org/source/SMUELLER/PathTools-3.47/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),你将需要进行测试并选择要使用的函数。奇怪的平台列表)。