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