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