gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 19:13:37 28 4
gpt4 key购买 nike

问题

一般来说,在不考虑任何特定平台的情况下,Perl 中的 Cwd::cwdCwd::getcwd 之间有什么区别?为什么 Perl 两者兼而有之?预期用途是什么,在什么场景下应该使用哪一种? (我们将不胜感激示例用例。)这重要吗? (假设我不混合它们。)选择其中任何一个会以任何方式影响可移植性吗?模块中哪一种更常用?

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

我总是可以阅读实现,但这并没有告诉我这些函数的含义。实现细节可能会改变,但定义的含义并非如此。 (否则会发生重大变化,这是一件很严重的事情。)

手册说了什么

引用 Perl 的 Cwd module manpage :

Each of these functions are called without arguments and return the absolute path of the current working directory.

  • getcwd

    my $cwd = getcwd();

    Returns the current working directory.

    Exposes the POSIX function getcwd(3) or re-implements it if it's not available.

  • cwd

    my $cwd = cwd();

    The cwd() is the most natural form for the current architecture. For most systems it is identical to `pwd` (but without the trailing line terminator).

在注释部分:

  • Actually, on Mac OS, the getcwd(), fastgetcwd() and fastcwd() functions are all aliases for the cwd() function, which, on Mac OS, calls `pwd`. Likewise, the abs_path() function is an alias for fast_abs_path()

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

<小时/>

1 经典 Mac OS,而非 OS X。对于 Mac,$^O 值为 MacOSdarwin分别是操作系统和 OS X。 谢谢,@tobyink@ikegami .

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

最佳答案

一般来说

我认为这个想法是 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 上

在 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/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com