Как отличаются функции Perl Cwd::cwd и Cwd::getcwd?

вопрос

в чем разница между Cwd::cwd и Cwd::getcwd в Perl, как правило, без учета какой-либо конкретной платформы? Почему у Perl есть оба? Каково предполагаемое использование, какой из них я должен использовать в каких сценариях? (Примеры использования будут оценены. Это имеет значение? (При условии, что я их не смешиваю.) Влияет ли выбор любого из них на переносимость каким-либо образом? Какой из них чаще используется в модулях?

даже если я интерпретирую руководство говоря, что за исключением угловых случаев cwd и `pwd` и getcwd просто называет getcwd С unistd.h, какова фактическая разница? Во всяком случае, это работает только на системах POSIX.

я всегда могу прочитать реализацию, но это ничего не говорит мне о значении этих функций. Детали реализации могут измениться, не так определенный смысл. (В противном случае происходит резкое изменение, что является серьезным делом.)

что говорится в руководстве

цитировать В Perl модуль Cwd manpage:

каждая из этих функций вызывается без аргументов и возвращает абсолютный путь текущего рабочего каталога.

  • функция getcwd

    my $cwd = getcwd();

    возвращает текущий рабочий каталог.

    предоставляет функцию POSIX getcwd (3) или повторно реализует ее, если она недоступна.

  • cwd

    my $cwd = cwd();

    cwd () является наиболее естественной формой для текущей архитектуры. Для большинства систем он идентичен " pwd " (но без Терминатора конечной линии).

и в разделе "Заметки":

  • на самом деле, на Mac OS,getcwd(), fastgetcwd() и fastcwd() функции все псевдонимы для cwd() функция, которая в Mac OS вызывает "pwd". Аналогично,

1 ответов


в целом

я думаю, идея в том, что cwd() всегда разрешает внешний, специфичный для ОС способ получения текущего рабочего каталога. То есть бегом!--6--> в Linux command /c cd на DOS,/usr/bin/fullpath -t в QNX, и так далее - все примеры от реальных Cwd.pm. The getcwd() предполагается использовать системный вызов POSIX, если он доступен, и возвращается к cwd() если не.

почему у нас есть оба? В текущей реализации я считаю экспорт просто getcwd() было бы достаточно для большинства систем, но кто знает, почему логика "если syscall доступен, используйте его, иначе запустите cwd() " может произойти сбой в некоторой системе (например,на MorphOS в 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 в backticks.

вот фрагмент 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;
    }
}

производительность benchmark

наконец, разница между двумя заключается в том, что 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 не входят в список странных платформ).