HPUNIX Сайт о ОС и не только!

Комментарии - unix (15)

unix прокомментировал 5 сентября 2008 в 18:12

вывод, файлы, каталоги и глобы

С момента публикации моего предшествующего урока программирования на Perl прошло уже более 2-ух месяцев. И вот она — давно ожидаемая последняя часть!

Если вы пропустили прошлые три части, я бы рекомендовал начать чтение с начала. В принципе, эту серию уроков можно читать в случайном порядке и во всем разобраться, но для чего усложнять для себя жизнь?

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

К счастью, с этим для вас поможет фактически неважно какая книга по основам ОС семейства UNIX. Ну и в сети соответственных статей должно быть в обилии.

Ввод и вывод

Как обычно, давайте начнем с примера:

#!/usr/bin/perl
use strict;

while(my $line = <STDIN>) {
chomp($line); # отсекаем знак \n
  last if($line eq "exit");
  print "Вы ввели '$line'. Для выхода из цикла введите exit\n";
}

Разглядим четвертую строчку. STDIN — это файловый дескриптор, связанный со стандартным потоком ввода. Чтение из файла делается при помощи оператора «треугольные скобки».

Да, это не так обычно, как readln, но такая запись тоже имеет право на жизнь, тем паче, что она короче.

Функция chomp инспектирует, находится ли в конце строки-аргумента знак новейшей строчки (\n) и если он находится, отсекает его. Если такового знака нет, строчка остается без конфигураций.

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

print STDOUT "Вывод строчки в стандартный поток вывода\n";
print STDERR "Вывод строчки в стандартный поток ошибок\n";

Направьте внимание, что после файлового дескриптора не ставится запятая. Вопрос «почему это так» — выходит за рамки статьи. Сможете считать, что это просто исключение из правил.

Приведенный выше скрипт можно малость «ужать» за счет использования переменной $_. Припоминаю, что в первый раз мы столкнулись с ней во 2-м уроке.

#!/usr/bin/perl
use strict;

while(<STDIN>) { # итог чтения сохраняется в переменной $_
  chomp; # отсекаем знак \n в переменной $_
  last if($_ eq "exit");
  printf "Вы ввели '%s'. Для выхода из цикла введите exit\n", $_;
}

Заметьте также, что функция print была заменена на printf, которая должна быть отлично знакома программерам на Си. Я полагаю, что вы уже знакомы с форматированным выводом. Если это не так — ничего ужасного, всю нужную информацию можно получить, выполнив команды perldoc -f printf и perldoc -f sprintf.

Файлы — чтение и запись

Чтение и запись в случае с файлами делается точь-в-точь как чтение из STDIN и запись в STDOUT либо STDERR. Единственное, о чем следует позаботится — это сделать дескриптор, связанный с данным файлом.

#!/usr/bin/perl
use strict;
# создаем файловый дескриптор
open FID, "input.txt"
  or die "Failed to open input.txt: $!\n";
my $i = 0;
print "line ".++$i.": $_" while(<FID>);
close FID; # закрываем файловый дескриптор

Фактически создание файлового дескриптора происходит на четвертой строке. Функция open воспринимает два аргумента — дескриптор и название файла. В случае ошибки, к примеру, если файла с именованием input.txt не существует, функция возвратит false, а сообщение об ошибке будет записано в переменную $!.

Но что делает оператор «или» после вызова open? Конструкция вида «функция1 or функция2» встречается в perl-скриптах достаточно нередко, так что давайте разберемся, как она работает.

Будем считать, что функция1 и функция2 возвращают ересь в случае ошибки и правду по другому. Поначалу производится функция1.

Если она заканчивается удачно, будет возвращено настоящее значение и интерпретатору Perl следует вычислить «истина либо (что-то, что возвратит функция2)». Но «истина либо ложь» = «истина либо истина» = «истина». Другими словами, в данном случае итог не находится в зависимости от того, что возвратит функция2, а означает не следует растрачивать время на ее выполнение.

Если же функция1 закончится с ошибкой и возвратит «ложь», то итог «ложь либо функция2» впрямую находится в зависимости от того, что возвратит функция2, означает в данном случае интерпретатор будет должен ее вызвать. Таким макаром конструкция «функция1 or функция2» значит «вызвать функцию1 и если она возвратит ересь (и только в данном случае!) вызвать функцию2».

Означает, если вызов open закончится безуспешно, будет вызвана функция die, которая делает что? Как нетрудно додуматься по ее наименованию — выводит сообщение об ошибке и заканчивает работу скрипта. Остальная часть примера так элементарна, что я не вижу смысла ее обрисовывать.

Только-только мы разглядели открытие файла на чтение. Чтоб открыть файл на запись, необходимо перед его именованием указать > либо >>:

вывод, файлы, каталоги и глобы
#!/usr/bin/perl
use strict;
# пример 1
open FID, ">output1.txt"; # один символ "больше"
  or die "Failed to open output1.txt: $!\n";
print FID "111\n"; # направьте внимание - запятой нет
close FID;

# пример 2
open FID, ">>output2.txt"; # два знака "больше"
  or die "Failed to open output2.txt: $!\n";
print FID "222\n";
вывод, файлы, каталоги и глобы
close FID;

В первом случае, если файл output1.txt уже существует, он будет очищен, по другому — файл output1.txt будет сотворен. Во 2-м случае, если файл output2.txt уже существует, запись будет делается в его конец, по другому также будет сотворен новый файл. Чтоб ощутить разницу, сможете пару раз запустить этот скрипт и поглядеть, что будет записано в каждом из файлов.

Тут мы разглядели только самые всераспространенные методы вызова функции open. Вывод команды perdoc -f open занимает Девятнадцать кб.

Это не случаем, ведь функцию open можно вызывать с 3-мя аргументами, с ее помощью можно сохранять файловые дескрипторы в скалярных переменных и даже перенаправлять данные в уже открытых дескрипторах. Очевидно, в рамках одной заметки я не могу поведать о всех способностях этой функции (более того — вероятнее всего я их всех и не знаю), так что сможете считать чтение соответственной документации домашним заданием.

В заключение к этому разделу хотелось бы поведать об увлекательной особенности оператора <>. Дело в том, что он может употребляться без указания файлового дескриптора:

#!/usr/bin/perl
print while(<>); # аналогично print $_ while($_ = <>);

В данном случае, если скрипт был вызван без аргументов, оператор будет создавать чтение из STDIN. В неприятном случае все аргументы будут рассматриваться, как названия файлов. Чтение будет выполняться по очереди из каждого файла.

Можно сказать, что этот скрипт представляет собой аналог утилиты cat.

Работа с каталогами

Самый обычной метод получить имена всего, что есть в каталоге — это пользоваться функциями opendir и readdir:

#!/usr/bin/perl
use strict;
opendir DIR, "/home/afiskon" or die $!;
while(my $fname = readdir DIR) {
print "$fname\n";
}
closedir DIR;

Здесь все так просто, что даже комментировать не охото. Давайте лучше сходу перейдем к более увлекательному примеру:

#!/usr/bin/perl
use strict;

my @flist = glob "~/*.txt";
print "$_\n" for(@flist);

Функция glob возвращает перечень файлов, как это сделала бы оболочка csh. Тильда значит домашний каталог, звездочка — всякую последовательность знаков. Также можно использовать символ вопроса, фигурные и квадратные скобки.

Существует и поболее маленькая запись:

my @flist = <~/*.txt>; # на сто процентов эквивалентно glob "~/*.txt"

А еще можно так:

print "$_\n" while(<~/*.txt>);

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

Другие операции над файлами и каталогами

Эта заметка была бы не полной, если б я не поведал, как в Perl сделать/удалить каталог либо найти размер файла. Но не волнуйтесь, этот раздел очень обычный. Практически на данный момент моя задачка — привести перечень функций и операторов, чтоб в случае необходимости вы знали, в какой мануал заглянуть (вы ведь уже запомнили команду «perldoc -f имя_функции», правильно?) :

# удаление 1-го либо нескольких файлов
# функция возвращает число удачно удаленных файлов
вывод, файлы, каталоги и глобы
unlink $file1, $file2, $file3;

# а еще можно так:
unlink glob "~/*.core";

# переименовать либо переместить файл
rename $old, $new;

# сделать каталог, 2-ой аргумент представляет
# собой права доступа и является необязательным
mkdir $dir_name, 0755;

вывод, файлы, каталоги и глобы
# удалить пустой каталог
rmdir dir;

# поменять права доступа к файлу либо файлам
chmod 0755, $file1, $file2, $file3;

# поменять хозяев файлов
chown $user, $group, glob "*.txt"

# по моему опыту работать с ссылками приходится редко
# но на всякий случай вот перечень имен функций:
# link, symlink, readlink

Также в Perl есть некоторое количество достаточно нужных операторов:

if(-e $fname) { # если файл либо каталог существует
  if(-f $fname) { # является файлом
    my $fsize = -s $fname; # получить размер файла
    # сделать с ним еще что-то
  } elsif(-d $fname) { # является каталогом
    my $readable = -r $fname; # доступен на чтение?
    # ....
  } else {
    die "EPIC FAIL\n";
  }
}

С непривычки эти операторы могут показаться необычными, но по сути они не много чем отличаются от очевидных «больше» и «меньше». Полный перечень операторов этого типа можно поглядеть, выполнив команду perldoc -f -X.

Заключение

Мои поздравления! Вы только-только окончили читать последнюю часть «Основ Perl». Сейчас вы понимаете, что в этом языке нет ничего магического — он не то, чтоб неописуемо сложен, очень даже читаем, если знаешь матчасть, и отлично документирован.

К огорчению, за кадром остались еще огромное количество вопросов, к примеру взаимодействие процессов, объектно-ориентированное программирование, постоянные выражения и многие другие. Если вы хотят продолжить исследование Perl, то я безотступно рекомендую приобрести книжки «Изучаем Perl» и «Perl: изучаем глубже», создатели — Шварц Р. и Феникс Т., пока их еще просто отыскать.

Я надеюсь, что «основы» посодействуют для вас написать ваши 1-ые скрипты и разобраться в чужом коде. С течением времени у вас будут появляться вопросы «а как мне сделать то-то» и «а что происходит в этом скрипте в строе N».

Не ленитесь заглядывать в документацию и просить помощи у более опытнейших программистов на форумах, в чатах и в направленных на определенную тематику обществах (к примеру, жж-сообществе ru_perl). И в какой-то момент вы станете реальным гуру языка Perl. Фортуны!

Дополнение. Рекомендую также поглядеть презентацию «Мифы Perl» Алексея Капранова, представленную на DEVCONF::Perl() 2010.

Дополнение. Некто Тезка совсем справедливо увидел в комментах:

А про eval, system, etc не написали, как в прошлой главе обозначили сие намерение.

Правильно, но урок и так вышел большой, так что оставляю на самостоятельное исследование. Самое главное, что я поведал про perldoc.

Дополнение. См также заметки, посвященные постоянным выражениям и объектно-ориентированному программированию в Perl. Сможете считать их дополнениями к этой серии уроков.

Похожие статьи

0

unix прокомментировал 5 сентября 2008 в 18:12

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

0

unix прокомментировал 5 сентября 2008 в 18:12

вывод, файлы, каталоги и глобы

С момента публикации моего предшествующего урока программирования на Perl прошло уже более 2-ух месяцев. И вот она — давно ожидаемая последняя часть!

Если вы пропустили прошлые три части, я бы рекомендовал начать чтение с начала. В принципе, эту серию уроков можно читать в случайном порядке и во всем разобраться, но для чего усложнять для себя жизнь?

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

К счастью, с этим для вас поможет фактически неважно какая книга по основам ОС семейства UNIX. Ну и в сети соответственных статей должно быть в обилии.

Ввод и вывод

Как обычно, давайте начнем с примера:

#!/usr/bin/perl
use strict;

while(my $line = <STDIN>) {
chomp($line); # отсекаем знак \n
  last if($line eq "exit");
  print "Вы ввели '$line'. Для выхода из цикла введите exit\n";
}

Разглядим четвертую строчку. STDIN — это файловый дескриптор, связанный со стандартным потоком ввода. Чтение из файла делается при помощи оператора «треугольные скобки».

Да, это не так обычно, как readln, но такая запись тоже имеет право на жизнь, тем паче, что она короче.

Функция chomp инспектирует, находится ли в конце строки-аргумента знак новейшей строчки (\n) и если он находится, отсекает его. Если такового знака нет, строчка остается без конфигураций.

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

print STDOUT "Вывод строчки в стандартный поток вывода\n";
print STDERR "Вывод строчки в стандартный поток ошибок\n";

Направьте внимание, что после файлового дескриптора не ставится запятая. Вопрос «почему это так» — выходит за рамки статьи. Сможете считать, что это просто исключение из правил.

Приведенный выше скрипт можно малость «ужать» за счет использования переменной $_. Припоминаю, что в первый раз мы столкнулись с ней во 2-м уроке.

#!/usr/bin/perl
use strict;

while(<STDIN>) { # итог чтения сохраняется в переменной $_
  chomp; # отсекаем знак \n в переменной $_
  last if($_ eq "exit");
  printf "Вы ввели '%s'. Для выхода из цикла введите exit\n", $_;
}

Заметьте также, что функция print была заменена на printf, которая должна быть отлично знакома программерам на Си. Я полагаю, что вы уже знакомы с форматированным выводом. Если это не так — ничего ужасного, всю нужную информацию можно получить, выполнив команды perldoc -f printf и perldoc -f sprintf.

Файлы — чтение и запись

Чтение и запись в случае с файлами делается точь-в-точь как чтение из STDIN и запись в STDOUT либо STDERR. Единственное, о чем следует позаботится — это сделать дескриптор, связанный с данным файлом.

#!/usr/bin/perl
use strict;
# создаем файловый дескриптор
open FID, "input.txt"
  or die "Failed to open input.txt: $!\n";
my $i = 0;
print "line ".++$i.": $_" while(<FID>);
close FID; # закрываем файловый дескриптор

Фактически создание файлового дескриптора происходит на четвертой строке. Функция open воспринимает два аргумента — дескриптор и название файла. В случае ошибки, к примеру, если файла с именованием input.txt не существует, функция возвратит false, а сообщение об ошибке будет записано в переменную $!.

Но что делает оператор «или» после вызова open? Конструкция вида «функция1 or функция2» встречается в perl-скриптах достаточно нередко, так что давайте разберемся, как она работает.

Будем считать, что функция1 и функция2 возвращают ересь в случае ошибки и правду по другому. Поначалу производится функция1.

Если она заканчивается удачно, будет возвращено настоящее значение и интерпретатору Perl следует вычислить «истина либо (что-то, что возвратит функция2)». Но «истина либо ложь» = «истина либо истина» = «истина». Другими словами, в данном случае итог не находится в зависимости от того, что возвратит функция2, а означает не следует растрачивать время на ее выполнение.

Если же функция1 закончится с ошибкой и возвратит «ложь», то итог «ложь либо функция2» впрямую находится в зависимости от того, что возвратит функция2, означает в данном случае интерпретатор будет должен ее вызвать. Таким макаром конструкция «функция1 or функция2» значит «вызвать функцию1 и если она возвратит ересь (и только в данном случае!) вызвать функцию2».

Означает, если вызов open закончится безуспешно, будет вызвана функция die, которая делает что? Как нетрудно додуматься по ее наименованию — выводит сообщение об ошибке и заканчивает работу скрипта. Остальная часть примера так элементарна, что я не вижу смысла ее обрисовывать.

Только-только мы разглядели открытие файла на чтение. Чтоб открыть файл на запись, необходимо перед его именованием указать > либо >>:

вывод, файлы, каталоги и глобы
#!/usr/bin/perl
use strict;
# пример 1
open FID, ">output1.txt"; # один символ "больше"
  or die "Failed to open output1.txt: $!\n";
print FID "111\n"; # направьте внимание - запятой нет
close FID;

# пример 2
open FID, ">>output2.txt"; # два знака "больше"
  or die "Failed to open output2.txt: $!\n";
print FID "222\n";
вывод, файлы, каталоги и глобы
close FID;

В первом случае, если файл output1.txt уже существует, он будет очищен, по другому — файл output1.txt будет сотворен. Во 2-м случае, если файл output2.txt уже существует, запись будет делается в его конец, по другому также будет сотворен новый файл. Чтоб ощутить разницу, сможете пару раз запустить этот скрипт и поглядеть, что будет записано в каждом из файлов.

Тут мы разглядели только самые всераспространенные методы вызова функции open. Вывод команды perdoc -f open занимает Девятнадцать кб.

Это не случаем, ведь функцию open можно вызывать с 3-мя аргументами, с ее помощью можно сохранять файловые дескрипторы в скалярных переменных и даже перенаправлять данные в уже открытых дескрипторах. Очевидно, в рамках одной заметки я не могу поведать о всех способностях этой функции (более того — вероятнее всего я их всех и не знаю), так что сможете считать чтение соответственной документации домашним заданием.

В заключение к этому разделу хотелось бы поведать об увлекательной особенности оператора <>. Дело в том, что он может употребляться без указания файлового дескриптора:

#!/usr/bin/perl
print while(<>); # аналогично print $_ while($_ = <>);

В данном случае, если скрипт был вызван без аргументов, оператор будет создавать чтение из STDIN. В неприятном случае все аргументы будут рассматриваться, как названия файлов. Чтение будет выполняться по очереди из каждого файла.

Можно сказать, что этот скрипт представляет собой аналог утилиты cat.

Работа с каталогами

Самый обычной метод получить имена всего, что есть в каталоге — это пользоваться функциями opendir и readdir:

#!/usr/bin/perl
use strict;
opendir DIR, "/home/afiskon" or die $!;
while(my $fname = readdir DIR) {
print "$fname\n";
}
closedir DIR;

Здесь все так просто, что даже комментировать не охото. Давайте лучше сходу перейдем к более увлекательному примеру:

#!/usr/bin/perl
use strict;

my @flist = glob "~/*.txt";
print "$_\n" for(@flist);

Функция glob возвращает перечень файлов, как это сделала бы оболочка csh. Тильда значит домашний каталог, звездочка — всякую последовательность знаков. Также можно использовать символ вопроса, фигурные и квадратные скобки.

Существует и поболее маленькая запись:

my @flist = <~/*.txt>; # на сто процентов эквивалентно glob "~/*.txt"

А еще можно так:

print "$_\n" while(<~/*.txt>);

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

Другие операции над файлами и каталогами

Эта заметка была бы не полной, если б я не поведал, как в Perl сделать/удалить каталог либо найти размер файла. Но не волнуйтесь, этот раздел очень обычный. Практически на данный момент моя задачка — привести перечень функций и операторов, чтоб в случае необходимости вы знали, в какой мануал заглянуть (вы ведь уже запомнили команду «perldoc -f имя_функции», правильно?) :

# удаление 1-го либо нескольких файлов
# функция возвращает число удачно удаленных файлов
вывод, файлы, каталоги и глобы
unlink $file1, $file2, $file3;

# а еще можно так:
unlink glob "~/*.core";

# переименовать либо переместить файл
rename $old, $new;

# сделать каталог, 2-ой аргумент представляет
# собой права доступа и является необязательным
mkdir $dir_name, 0755;

вывод, файлы, каталоги и глобы
# удалить пустой каталог
rmdir dir;

# поменять права доступа к файлу либо файлам
chmod 0755, $file1, $file2, $file3;

# поменять хозяев файлов
chown $user, $group, glob "*.txt"

# по моему опыту работать с ссылками приходится редко
# но на всякий случай вот перечень имен функций:
# link, symlink, readlink

Также в Perl есть некоторое количество достаточно нужных операторов:

if(-e $fname) { # если файл либо каталог существует
  if(-f $fname) { # является файлом
    my $fsize = -s $fname; # получить размер файла
    # сделать с ним еще что-то
  } elsif(-d $fname) { # является каталогом
    my $readable = -r $fname; # доступен на чтение?
    # ....
  } else {
    die "EPIC FAIL\n";
  }
}

С непривычки эти операторы могут показаться необычными, но по сути они не много чем отличаются от очевидных «больше» и «меньше». Полный перечень операторов этого типа можно поглядеть, выполнив команду perldoc -f -X.

Заключение

Мои поздравления! Вы только-только окончили читать последнюю часть «Основ Perl». Сейчас вы понимаете, что в этом языке нет ничего магического — он не то, чтоб неописуемо сложен, очень даже читаем, если знаешь матчасть, и отлично документирован.

К огорчению, за кадром остались еще огромное количество вопросов, к примеру взаимодействие процессов, объектно-ориентированное программирование, постоянные выражения и многие другие. Если вы хотят продолжить исследование Perl, то я безотступно рекомендую приобрести книжки «Изучаем Perl» и «Perl: изучаем глубже», создатели — Шварц Р. и Феникс Т., пока их еще просто отыскать.

Я надеюсь, что «основы» посодействуют для вас написать ваши 1-ые скрипты и разобраться в чужом коде. С течением времени у вас будут появляться вопросы «а как мне сделать то-то» и «а что происходит в этом скрипте в строе N».

Не ленитесь заглядывать в документацию и просить помощи у более опытнейших программистов на форумах, в чатах и в направленных на определенную тематику обществах (к примеру, жж-сообществе ru_perl). И в какой-то момент вы станете реальным гуру языка Perl. Фортуны!

Дополнение. Рекомендую также поглядеть презентацию «Мифы Perl» Алексея Капранова, представленную на DEVCONF::Perl() 2010.

Дополнение. Некто Тезка совсем справедливо увидел в комментах:

А про eval, system, etc не написали, как в прошлой главе обозначили сие намерение.

Правильно, но урок и так вышел большой, так что оставляю на самостоятельное исследование. Самое главное, что я поведал про perldoc.

Дополнение. См также заметки, посвященные постоянным выражениям и объектно-ориентированному программированию в Perl. Сможете считать их дополнениями к этой серии уроков.

Похожие статьи

0

unix прокомментировал 5 сентября 2008 в 18:12

вывод, файлы, каталоги и глобы

С момента публикации моего предшествующего урока программирования на Perl прошло уже более 2-ух месяцев. И вот она — давно ожидаемая последняя часть!

Если вы пропустили прошлые три части, я бы рекомендовал начать чтение с начала. В принципе, эту серию уроков можно читать в случайном порядке и во всем разобраться, но для чего усложнять для себя жизнь?

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

К счастью, с этим для вас поможет фактически неважно какая книга по основам ОС семейства UNIX. Ну и в сети соответственных статей должно быть в обилии.

Ввод и вывод

Как обычно, давайте начнем с примера:

#!/usr/bin/perl
use strict;

while(my $line = <STDIN>) {
chomp($line); # отсекаем знак \n
  last if($line eq "exit");
  print "Вы ввели '$line'. Для выхода из цикла введите exit\n";
}

Разглядим четвертую строчку. STDIN — это файловый дескриптор, связанный со стандартным потоком ввода. Чтение из файла делается при помощи оператора «треугольные скобки».

Да, это не так обычно, как readln, но такая запись тоже имеет право на жизнь, тем паче, что она короче.

Функция chomp инспектирует, находится ли в конце строки-аргумента знак новейшей строчки (\n) и если он находится, отсекает его. Если такового знака нет, строчка остается без конфигураций.

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

print STDOUT "Вывод строчки в стандартный поток вывода\n";
print STDERR "Вывод строчки в стандартный поток ошибок\n";

Направьте внимание, что после файлового дескриптора не ставится запятая. Вопрос «почему это так» — выходит за рамки статьи. Сможете считать, что это просто исключение из правил.

Приведенный выше скрипт можно малость «ужать» за счет использования переменной $_. Припоминаю, что в первый раз мы столкнулись с ней во 2-м уроке.

#!/usr/bin/perl
use strict;

while(<STDIN>) { # итог чтения сохраняется в переменной $_
  chomp; # отсекаем знак \n в переменной $_
  last if($_ eq "exit");
  printf "Вы ввели '%s'. Для выхода из цикла введите exit\n", $_;
}

Заметьте также, что функция print была заменена на printf, которая должна быть отлично знакома программерам на Си. Я полагаю, что вы уже знакомы с форматированным выводом. Если это не так — ничего ужасного, всю нужную информацию можно получить, выполнив команды perldoc -f printf и perldoc -f sprintf.

Файлы — чтение и запись

Чтение и запись в случае с файлами делается точь-в-точь как чтение из STDIN и запись в STDOUT либо STDERR. Единственное, о чем следует позаботится — это сделать дескриптор, связанный с данным файлом.

#!/usr/bin/perl
use strict;
# создаем файловый дескриптор
open FID, "input.txt"
  or die "Failed to open input.txt: $!\n";
my $i = 0;
print "line ".++$i.": $_" while(<FID>);
close FID; # закрываем файловый дескриптор

Фактически создание файлового дескриптора происходит на четвертой строке. Функция open воспринимает два аргумента — дескриптор и название файла. В случае ошибки, к примеру, если файла с именованием input.txt не существует, функция возвратит false, а сообщение об ошибке будет записано в переменную $!.

Но что делает оператор «или» после вызова open? Конструкция вида «функция1 or функция2» встречается в perl-скриптах достаточно нередко, так что давайте разберемся, как она работает.

Будем считать, что функция1 и функция2 возвращают ересь в случае ошибки и правду по другому. Поначалу производится функция1.

Если она заканчивается удачно, будет возвращено настоящее значение и интерпретатору Perl следует вычислить «истина либо (что-то, что возвратит функция2)». Но «истина либо ложь» = «истина либо истина» = «истина». Другими словами, в данном случае итог не находится в зависимости от того, что возвратит функция2, а означает не следует растрачивать время на ее выполнение.

Если же функция1 закончится с ошибкой и возвратит «ложь», то итог «ложь либо функция2» впрямую находится в зависимости от того, что возвратит функция2, означает в данном случае интерпретатор будет должен ее вызвать. Таким макаром конструкция «функция1 or функция2» значит «вызвать функцию1 и если она возвратит ересь (и только в данном случае!) вызвать функцию2».

Означает, если вызов open закончится безуспешно, будет вызвана функция die, которая делает что? Как нетрудно додуматься по ее наименованию — выводит сообщение об ошибке и заканчивает работу скрипта. Остальная часть примера так элементарна, что я не вижу смысла ее обрисовывать.

Только-только мы разглядели открытие файла на чтение. Чтоб открыть файл на запись, необходимо перед его именованием указать > либо >>:

вывод, файлы, каталоги и глобы
#!/usr/bin/perl
use strict;
# пример 1
open FID, ">output1.txt"; # один символ "больше"
  or die "Failed to open output1.txt: $!\n";
print FID "111\n"; # направьте внимание - запятой нет
close FID;

# пример 2
open FID, ">>output2.txt"; # два знака "больше"
  or die "Failed to open output2.txt: $!\n";
print FID "222\n";
вывод, файлы, каталоги и глобы
close FID;

В первом случае, если файл output1.txt уже существует, он будет очищен, по другому — файл output1.txt будет сотворен. Во 2-м случае, если файл output2.txt уже существует, запись будет делается в его конец, по другому также будет сотворен новый файл. Чтоб ощутить разницу, сможете пару раз запустить этот скрипт и поглядеть, что будет записано в каждом из файлов.

Тут мы разглядели только самые всераспространенные методы вызова функции open. Вывод команды perdoc -f open занимает Девятнадцать кб.

Это не случаем, ведь функцию open можно вызывать с 3-мя аргументами, с ее помощью можно сохранять файловые дескрипторы в скалярных переменных и даже перенаправлять данные в уже открытых дескрипторах. Очевидно, в рамках одной заметки я не могу поведать о всех способностях этой функции (более того — вероятнее всего я их всех и не знаю), так что сможете считать чтение соответственной документации домашним заданием.

В заключение к этому разделу хотелось бы поведать об увлекательной особенности оператора <>. Дело в том, что он может употребляться без указания файлового дескриптора:

#!/usr/bin/perl
print while(<>); # аналогично print $_ while($_ = <>);

В данном случае, если скрипт был вызван без аргументов, оператор будет создавать чтение из STDIN. В неприятном случае все аргументы будут рассматриваться, как названия файлов. Чтение будет выполняться по очереди из каждого файла.

Можно сказать, что этот скрипт представляет собой аналог утилиты cat.

Работа с каталогами

Самый обычной метод получить имена всего, что есть в каталоге — это пользоваться функциями opendir и readdir:

#!/usr/bin/perl
use strict;
opendir DIR, "/home/afiskon" or die $!;
while(my $fname = readdir DIR) {
print "$fname\n";
}
closedir DIR;

Здесь все так просто, что даже комментировать не охото. Давайте лучше сходу перейдем к более увлекательному примеру:

#!/usr/bin/perl
use strict;

my @flist = glob "~/*.txt";
print "$_\n" for(@flist);

Функция glob возвращает перечень файлов, как это сделала бы оболочка csh. Тильда значит домашний каталог, звездочка — всякую последовательность знаков. Также можно использовать символ вопроса, фигурные и квадратные скобки.

Существует и поболее маленькая запись:

my @flist = <~/*.txt>; # на сто процентов эквивалентно glob "~/*.txt"

А еще можно так:

print "$_\n" while(<~/*.txt>);

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

Другие операции над файлами и каталогами

Эта заметка была бы не полной, если б я не поведал, как в Perl сделать/удалить каталог либо найти размер файла. Но не волнуйтесь, этот раздел очень обычный. Практически на данный момент моя задачка — привести перечень функций и операторов, чтоб в случае необходимости вы знали, в какой мануал заглянуть (вы ведь уже запомнили команду «perldoc -f имя_функции», правильно?) :

# удаление 1-го либо нескольких файлов
# функция возвращает число удачно удаленных файлов
вывод, файлы, каталоги и глобы
unlink $file1, $file2, $file3;

# а еще можно так:
unlink glob "~/*.core";

# переименовать либо переместить файл
rename $old, $new;

# сделать каталог, 2-ой аргумент представляет
# собой права доступа и является необязательным
mkdir $dir_name, 0755;

вывод, файлы, каталоги и глобы
# удалить пустой каталог
rmdir dir;

# поменять права доступа к файлу либо файлам
chmod 0755, $file1, $file2, $file3;

# поменять хозяев файлов
chown $user, $group, glob "*.txt"

# по моему опыту работать с ссылками приходится редко
# но на всякий случай вот перечень имен функций:
# link, symlink, readlink

Также в Perl есть некоторое количество достаточно нужных операторов:

if(-e $fname) { # если файл либо каталог существует
  if(-f $fname) { # является файлом
    my $fsize = -s $fname; # получить размер файла
    # сделать с ним еще что-то
  } elsif(-d $fname) { # является каталогом
    my $readable = -r $fname; # доступен на чтение?
    # ....
  } else {
    die "EPIC FAIL\n";
  }
}

С непривычки эти операторы могут показаться необычными, но по сути они не много чем отличаются от очевидных «больше» и «меньше». Полный перечень операторов этого типа можно поглядеть, выполнив команду perldoc -f -X.

Заключение

Мои поздравления! Вы только-только окончили читать последнюю часть «Основ Perl». Сейчас вы понимаете, что в этом языке нет ничего магического — он не то, чтоб неописуемо сложен, очень даже читаем, если знаешь матчасть, и отлично документирован.

К огорчению, за кадром остались еще огромное количество вопросов, к примеру взаимодействие процессов, объектно-ориентированное программирование, постоянные выражения и многие другие. Если вы хотят продолжить исследование Perl, то я безотступно рекомендую приобрести книжки «Изучаем Perl» и «Perl: изучаем глубже», создатели — Шварц Р. и Феникс Т., пока их еще просто отыскать.

Я надеюсь, что «основы» посодействуют для вас написать ваши 1-ые скрипты и разобраться в чужом коде. С течением времени у вас будут появляться вопросы «а как мне сделать то-то» и «а что происходит в этом скрипте в строе N».

Не ленитесь заглядывать в документацию и просить помощи у более опытнейших программистов на форумах, в чатах и в направленных на определенную тематику обществах (к примеру, жж-сообществе ru_perl). И в какой-то момент вы станете реальным гуру языка Perl. Фортуны!

Дополнение. Рекомендую также поглядеть презентацию «Мифы Perl» Алексея Капранова, представленную на DEVCONF::Perl() 2010.

Дополнение. Некто Тезка совсем справедливо увидел в комментах:

А про eval, system, etc не написали, как в прошлой главе обозначили сие намерение.

Правильно, но урок и так вышел большой, так что оставляю на самостоятельное исследование. Самое главное, что я поведал про perldoc.

Дополнение. См также заметки, посвященные постоянным выражениям и объектно-ориентированному программированию в Perl. Сможете считать их дополнениями к этой серии уроков.

Похожие статьи

0

unix прокомментировал 5 сентября 2008 в 18:12

вывод, файлы, каталоги и глобы

С момента публикации моего предшествующего урока программирования на Perl прошло уже более 2-ух месяцев. И вот она — давно ожидаемая последняя часть!

Если вы пропустили прошлые три части, я бы рекомендовал начать чтение с начала. В принципе, эту серию уроков можно читать в случайном порядке и во всем разобраться, но для чего усложнять для себя жизнь?

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

К счастью, с этим для вас поможет фактически неважно какая книга по основам ОС семейства UNIX. Ну и в сети соответственных статей должно быть в обилии.

Ввод и вывод

Как обычно, давайте начнем с примера:

#!/usr/bin/perl
use strict;

while(my $line = <STDIN>) {
chomp($line); # отсекаем знак \n
  last if($line eq "exit");
  print "Вы ввели '$line'. Для выхода из цикла введите exit\n";
}

Разглядим четвертую строчку. STDIN — это файловый дескриптор, связанный со стандартным потоком ввода. Чтение из файла делается при помощи оператора «треугольные скобки».

Да, это не так обычно, как readln, но такая запись тоже имеет право на жизнь, тем паче, что она короче.

Функция chomp инспектирует, находится ли в конце строки-аргумента знак новейшей строчки (\n) и если он находится, отсекает его. Если такового знака нет, строчка остается без конфигураций.

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

print STDOUT "Вывод строчки в стандартный поток вывода\n";
print STDERR "Вывод строчки в стандартный поток ошибок\n";

Направьте внимание, что после файлового дескриптора не ставится запятая. Вопрос «почему это так» — выходит за рамки статьи. Сможете считать, что это просто исключение из правил.

Приведенный выше скрипт можно малость «ужать» за счет использования переменной $_. Припоминаю, что в первый раз мы столкнулись с ней во 2-м уроке.

#!/usr/bin/perl
use strict;

while(<STDIN>) { # итог чтения сохраняется в переменной $_
  chomp; # отсекаем знак \n в переменной $_
  last if($_ eq "exit");
  printf "Вы ввели '%s'. Для выхода из цикла введите exit\n", $_;
}

Заметьте также, что функция print была заменена на printf, которая должна быть отлично знакома программерам на Си. Я полагаю, что вы уже знакомы с форматированным выводом. Если это не так — ничего ужасного, всю нужную информацию можно получить, выполнив команды perldoc -f printf и perldoc -f sprintf.

Файлы — чтение и запись

Чтение и запись в случае с файлами делается точь-в-точь как чтение из STDIN и запись в STDOUT либо STDERR. Единственное, о чем следует позаботится — это сделать дескриптор, связанный с данным файлом.

#!/usr/bin/perl
use strict;
# создаем файловый дескриптор
open FID, "input.txt"
  or die "Failed to open input.txt: $!\n";
my $i = 0;
print "line ".++$i.": $_" while(<FID>);
close FID; # закрываем файловый дескриптор

Фактически создание файлового дескриптора происходит на четвертой строке. Функция open воспринимает два аргумента — дескриптор и название файла. В случае ошибки, к примеру, если файла с именованием input.txt не существует, функция возвратит false, а сообщение об ошибке будет записано в переменную $!.

Но что делает оператор «или» после вызова open? Конструкция вида «функция1 or функция2» встречается в perl-скриптах достаточно нередко, так что давайте разберемся, как она работает.

Будем считать, что функция1 и функция2 возвращают ересь в случае ошибки и правду по другому. Поначалу производится функция1.

Если она заканчивается удачно, будет возвращено настоящее значение и интерпретатору Perl следует вычислить «истина либо (что-то, что возвратит функция2)». Но «истина либо ложь» = «истина либо истина» = «истина». Другими словами, в данном случае итог не находится в зависимости от того, что возвратит функция2, а означает не следует растрачивать время на ее выполнение.

Если же функция1 закончится с ошибкой и возвратит «ложь», то итог «ложь либо функция2» впрямую находится в зависимости от того, что возвратит функция2, означает в данном случае интерпретатор будет должен ее вызвать. Таким макаром конструкция «функция1 or функция2» значит «вызвать функцию1 и если она возвратит ересь (и только в данном случае!) вызвать функцию2».

Означает, если вызов open закончится безуспешно, будет вызвана функция die, которая делает что? Как нетрудно додуматься по ее наименованию — выводит сообщение об ошибке и заканчивает работу скрипта. Остальная часть примера так элементарна, что я не вижу смысла ее обрисовывать.

Только-только мы разглядели открытие файла на чтение. Чтоб открыть файл на запись, необходимо перед его именованием указать > либо >>:

вывод, файлы, каталоги и глобы
#!/usr/bin/perl
use strict;
# пример 1
open FID, ">output1.txt"; # один символ "больше"
  or die "Failed to open output1.txt: $!\n";
print FID "111\n"; # направьте внимание - запятой нет
close FID;

# пример 2
open FID, ">>output2.txt"; # два знака "больше"
  or die "Failed to open output2.txt: $!\n";
print FID "222\n";
вывод, файлы, каталоги и глобы
close FID;

В первом случае, если файл output1.txt уже существует, он будет очищен, по другому — файл output1.txt будет сотворен. Во 2-м случае, если файл output2.txt уже существует, запись будет делается в его конец, по другому также будет сотворен новый файл. Чтоб ощутить разницу, сможете пару раз запустить этот скрипт и поглядеть, что будет записано в каждом из файлов.

Тут мы разглядели только самые всераспространенные методы вызова функции open. Вывод команды perdoc -f open занимает Девятнадцать кб.

Это не случаем, ведь функцию open можно вызывать с 3-мя аргументами, с ее помощью можно сохранять файловые дескрипторы в скалярных переменных и даже перенаправлять данные в уже открытых дескрипторах. Очевидно, в рамках одной заметки я не могу поведать о всех способностях этой функции (более того — вероятнее всего я их всех и не знаю), так что сможете считать чтение соответственной документации домашним заданием.

В заключение к этому разделу хотелось бы поведать об увлекательной особенности оператора <>. Дело в том, что он может употребляться без указания файлового дескриптора:

#!/usr/bin/perl
print while(<>); # аналогично print $_ while($_ = <>);

В данном случае, если скрипт был вызван без аргументов, оператор будет создавать чтение из STDIN. В неприятном случае все аргументы будут рассматриваться, как названия файлов. Чтение будет выполняться по очереди из каждого файла.

Можно сказать, что этот скрипт представляет собой аналог утилиты cat.

Работа с каталогами

Самый обычной метод получить имена всего, что есть в каталоге — это пользоваться функциями opendir и readdir:

#!/usr/bin/perl
use strict;
opendir DIR, "/home/afiskon" or die $!;
while(my $fname = readdir DIR) {
print "$fname\n";
}
closedir DIR;

Здесь все так просто, что даже комментировать не охото. Давайте лучше сходу перейдем к более увлекательному примеру:

#!/usr/bin/perl
use strict;

my @flist = glob "~/*.txt";
print "$_\n" for(@flist);

Функция glob возвращает перечень файлов, как это сделала бы оболочка csh. Тильда значит домашний каталог, звездочка — всякую последовательность знаков. Также можно использовать символ вопроса, фигурные и квадратные скобки.

Существует и поболее маленькая запись:

my @flist = <~/*.txt>; # на сто процентов эквивалентно glob "~/*.txt"

А еще можно так:

print "$_\n" while(<~/*.txt>);

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

Другие операции над файлами и каталогами

Эта заметка была бы не полной, если б я не поведал, как в Perl сделать/удалить каталог либо найти размер файла. Но не волнуйтесь, этот раздел очень обычный. Практически на данный момент моя задачка — привести перечень функций и операторов, чтоб в случае необходимости вы знали, в какой мануал заглянуть (вы ведь уже запомнили команду «perldoc -f имя_функции», правильно?) :

# удаление 1-го либо нескольких файлов
# функция возвращает число удачно удаленных файлов
вывод, файлы, каталоги и глобы
unlink $file1, $file2, $file3;

# а еще можно так:
unlink glob "~/*.core";

# переименовать либо переместить файл
rename $old, $new;

# сделать каталог, 2-ой аргумент представляет
# собой права доступа и является необязательным
mkdir $dir_name, 0755;

вывод, файлы, каталоги и глобы
# удалить пустой каталог
rmdir dir;

# поменять права доступа к файлу либо файлам
chmod 0755, $file1, $file2, $file3;

# поменять хозяев файлов
chown $user, $group, glob "*.txt"

# по моему опыту работать с ссылками приходится редко
# но на всякий случай вот перечень имен функций:
# link, symlink, readlink

Также в Perl есть некоторое количество достаточно нужных операторов:

if(-e $fname) { # если файл либо каталог существует
  if(-f $fname) { # является файлом
    my $fsize = -s $fname; # получить размер файла
    # сделать с ним еще что-то
  } elsif(-d $fname) { # является каталогом
    my $readable = -r $fname; # доступен на чтение?
    # ....
  } else {
    die "EPIC FAIL\n";
  }
}

С непривычки эти операторы могут показаться необычными, но по сути они не много чем отличаются от очевидных «больше» и «меньше». Полный перечень операторов этого типа можно поглядеть, выполнив команду perldoc -f -X.

Заключение

Мои поздравления! Вы только-только окончили читать последнюю часть «Основ Perl». Сейчас вы понимаете, что в этом языке нет ничего магического — он не то, чтоб неописуемо сложен, очень даже читаем, если знаешь матчасть, и отлично документирован.

К огорчению, за кадром остались еще огромное количество вопросов, к примеру взаимодействие процессов, объектно-ориентированное программирование, постоянные выражения и многие другие. Если вы хотят продолжить исследование Perl, то я безотступно рекомендую приобрести книжки «Изучаем Perl» и «Perl: изучаем глубже», создатели — Шварц Р. и Феникс Т., пока их еще просто отыскать.

Я надеюсь, что «основы» посодействуют для вас написать ваши 1-ые скрипты и разобраться в чужом коде. С течением времени у вас будут появляться вопросы «а как мне сделать то-то» и «а что происходит в этом скрипте в строе N».

Не ленитесь заглядывать в документацию и просить помощи у более опытнейших программистов на форумах, в чатах и в направленных на определенную тематику обществах (к примеру, жж-сообществе ru_perl). И в какой-то момент вы станете реальным гуру языка Perl. Фортуны!

Дополнение. Рекомендую также поглядеть презентацию «Мифы Perl» Алексея Капранова, представленную на DEVCONF::Perl() 2010.

Дополнение. Некто Тезка совсем справедливо увидел в комментах:

А про eval, system, etc не написали, как в прошлой главе обозначили сие намерение.

Правильно, но урок и так вышел большой, так что оставляю на самостоятельное исследование. Самое главное, что я поведал про perldoc.

Дополнение. См также заметки, посвященные постоянным выражениям и объектно-ориентированному программированию в Perl. Сможете считать их дополнениями к этой серии уроков.

Похожие статьи

0

unix прокомментировал 1 сентября 2008 в 16:41

потоками в Haskell

Как вы уже могли додуматься, я опять взялся за исследование Haskell. Разумеется, этот язык нельзя учить наскоком. Я решил запастись терпением и вникать во все медлительно, но правильно.

К примеру, не так давно я разбирался с многопоточностью.

Оказалось, что в Haskell употребляются легковесные потоки, так же как в Erlang, Go либо OCaml‘овском Lwt. Взаимодействие меж потоками происходит с помощью захватываемых изменяемых переменных (locking mutable variables), либо MVars.

В отличии, скажем, от Erlang, программка на Haskell заканчивается, когда свою работу завершает основной поток. Готовых средств, позволяющих выяснить состояние других потоков, скажем, производится ли данный поток либо уже закончился, не предвидено. Это изготовлено с целью минимизации затратных расходов.

MVar можно представить, как разделяемую несколькими потоками переменную, доступ к которой ограничивается мьютексом. В отличии от аналогичной конструкции в C++, MVar также может быть пустым. В этом смысле MVar припоминает тип Maybe либо очередь из 1-го элемента.

Написанное выше становится более понятным при взоре на типы главных функций для работы со всем этим хозяйством.

Создание нового потока делается при помощи функции forkIO:

forkIO :: IO () -> IO ThreadId

Новый MVar можно сделать одним из последующих методов:

newEmptyMVar :: IO (MVar a)
newMVar :: a -> IO (MVar a)

Выяснить, является ли MVar пустым, можно с помощью функции isEmptyMVar:

isEmptyMVar :: MVar a -> IO Bool

Для записи в MVar предназначена функция putMVar:

putMVar :: MVar a -> a -> IO ()

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

Разблокирование потоков делается в порядке FIFO.

Функция для чтения из MVar:

takeMVar :: MVar a -> IO a

Аналогично putMVar, функция takeMVar перекрывает текущий поток, если MVar пуст. Остальные характеристики такие же.

Еще пара нужных функций с тривиальной семантикой:

modifyMVar :: MVar a -> (a -> IO (a, b)) -> IO b
modifyMVar_ :: MVar a -> (a -> IO a) -> IO ()

Функция modifyMVar реализована, как обертка над вызовами takeMVar и putMVar. Потому она не является атомарной в случае, если в MVar пишут несколько потоков. Но если все потоки работают с переменной через modifyMVar, тогда все ОК.

Посреди других нужных функций необходимо подчеркнуть readMVar, swapMVar, tryTakeMVar, tryPutMVar, yield и threadDelay (последняя есть исключительно в GHC). За подробностями обращайтесь к документации.

На 1-ый взор может показаться, что этот API несколько убог. В Erlang, к примеру, для взаимодействия меж процессами употребляются очереди, в которые можно класть куда более 1-го элемента. К тому же, эти элементы могут быть хоть какого типа. Но если задуматься, MVar даже круче.

Во-1-х, он как будто горшочек из-под меда. В нем можно держать все что угодно. Это может быть и очередь, и очередь с ценностями, и очередь ограниченного размера и двунаправленный канал.

Во-2-х, каждый поток может иметь сколько угодно таких очередей и каналов. Либо напротив, из одной очереди может читать огромное количество потоков. В конце концов, все это — со статической проверкой типов.

Достаточно теории, давайте уже напишем какую-нибудь программку. Помнится, Erlang хорошо распараллеливал по всем ядрам микропроцессора задачку взлома хэшей способом грубой силы. Поглядим, как с этой же задачей управится Haskell.

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

module Bruteforce.Common where

import Data.Word
import Text.Printf
import Data.Digest.SHA2

passwordList :: String -> Int -> [String]
passwordList charList len =
    stream beginState
  where
    beginState = replicate len charList
    endState = replicate len [ last charList ]
    nextState ((_:[]):xs) = charList : nextState xs
    nextState ((_:ys):xs) = ys : xs
    nextState x = error $ "nextState " ++ show x
    stream st =
      let pw = map head st in
      if st == endState then [ pw ]
                        else pw : stream (nextState st)

hash :: String -> String
hash =
  concatMap (printf "%02x" :: Word8 -> String) .
    toOctets . sha256Ascii

Разумеется, здесь мы не гонимся за эффективностью. Куда важнее на данный момент распараллеливание либо его отсутствие. Обратите повышенное внимание на функцию passwordList.

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

Программка, работающая в один поток:

import Bruteforce.Common
 
main :: IO ()
main = do
  let hashList = [
        -- 1234
        "03ac674216f3e15c761ee1a5e255f067" ++
        "953623c8b388b4459e13f978d7c846f4",
        -- r2d2
        "8adce0a3431e8b11ef69e7f7765021d3" ++
        "ee0b70fff58e0480cadb4c468d78105f"
        ]
      pwLen = 4
      charList = ['0'..'9'] ++ ['a'..'z']
      pwHashList = [(pw,hash pw) | pw <- passwordList charList pwLen]
      rslt = [pw ++ ":" ++ h | (pw,h) <- pwHashList, h `elem` hashList]
  mapM_ putStrLn {- $ take (length hashList) -} rslt

На машине с четырехядерным микропроцессором Intel Core i7-3770K частотой 3.5 GHz программка совладевает с задачей за 12.7 секунд. Можно значительно ускорить ее, не производя перебор после того, как мы сломали все имеющиеся хэши (см закомментированную часть кода). Но в данном случае скорость программки будет находится в зависимости от порядка, в каком перебираются пароли, что не нужно.

Программка, решающая ту же задачку в несколько потоков:

import Bruteforce.Common
потоками в Haskell
import Control.Concurrent
import Control.Monad

workerLoop :: MVar [String] -> MVar [ [String] ] -> String -> Int ->
                [String] -> IO ()
workerLoop taskQueue resultQueue charList pwLen hashList = do
  maybeTask <- modifyMVar taskQueue
                 (\q -> return $ case q of
                                   [] -> ([], Nothing)
                                   (x:xs) -> (xs, Just x))
  case maybeTask of
    Nothing -> return ()

Щас я навалю про потоки

    Just task -> do
      let postfixList = passwordList charList $ pwLen - length task
          pwList = map (task ++) postfixList
          pwHashList = [(pw, hash pw) | pw <- pwList]
          rslt = [pw ++ ":" ++ h | (pw,h) <- pwHashList,
                                    h `elem` hashList]
      rslt `seq` modifyMVar_ resultQueue (\q -> return $ rslt:q)
      workerLoop taskQueue resultQueue charList pwLen hashList

mainLoop :: MVar [ [String] ] -> Int -> IO ()
mainLoop _ Нуль = return ()
mainLoop resultQueue taskNumber = do
  results <- modifyMVar resultQueue (\q -> return ([], q))
  case results of
    [] -> do
      threadDelay 100 тыщ -- 100 ms
      mainLoop resultQueue taskNumber
    _ -> do
      mapM_ (mapM_ putStrLn) results
      mainLoop resultQueue (taskNumber - length results)

main :: IO ()
main = do
  let hashList = [
        -- 1234
        "03ac674216f3e15c761ee1a5e255f067" ++
        "953623c8b388b4459e13f978d7c846f4",
        -- r2d2
потоками в Haskell
        "8adce0a3431e8b11ef69e7f7765021d3" ++
        "ee0b70fff58e0480cadb4c468d78105f"
        ]
      pwLen = 4
      chunkLen = 2
      charList = ['0'..'9'] ++ ['a'..'z']
      taskList = passwordList charList chunkLen
      taskNumber = length taskList
  workerNumber <- getNumCapabilities
  taskQueue <- newMVar taskList
  resultQueue <- newMVar []
  workerNumber `replicateM_` forkIO (workerLoop taskQueue resultQueue
                                             charList pwLen hashList)
  mainLoop resultQueue taskNumber

Функция getNumCapabilities возвращает количество потоков операционной системы, которое употребляется runtime system. Как будет показано ниже, это количество можно задавать при запуске программки. В этом случае разумно использовать столько же легковесных потоков, сколько употребляется реальных.

Программка употребляет две очереди. В реальности это обыденные списки, а никакие не очереди, но мне кажется, будет понятнее, если мыслить о их, как об очередях. Очередь taskQueue имеет тип MVar [String].

В ней содержатся задачки, представляющие из себя префиксы паролей для перебора. Поток берет префикс из очереди (головы перечня) и перебирает все пароли с этим префиксом. Очередь resultQueue имеет тип MVar [ [String] ].

Когда поток заканчивает работу над задачей, он помещает в эту очередь (также голову перечня) перечень строк, которые он желал бы вывести на экран.

Окончание головного потока приводит к окончанию работы всей программки. Потому он должен закончится только после окончания дочерних потоков. Чтоб главный поток не висел без дела, дадим ему кое-какую работу.

Работа эта состоит в том, чтоб разгребать resultQueue и выводить итог работы других потоков на экран. Строго говоря, мы обязаны так делать, так как ввод/вывод в Haskell не является thread safe. Заодно главный поток подсчитывает, сколько задач сейчас осталось выполнить.

Когда счетчик задач обнуляется, главный поток заканчивается.

Направьте внимание на то, как дочерние потоки пишут в resultQueue:

rslt `seq` modifyMVar_ resultQueue (\q -> return $ rslt:q)

Мы помним, что данные в Haskell по дефлоту являются ленивыми, и MVar — не исключение. Если мы просто запишем в resultQueue некий итог, его реальное вычисление произойдет в основном потоке. От параллелизма не будет никакого выигрыша!

Потому мы принудительно вычисляем rslt при помощи функции seq и только после чего изменяем resultQueue. Здесь нельзя не отметить существование пакета strict-concurrency, который предлагает те же MVars (также каналы, речь о которых пойдет ниже), только со серьезной семантикой.

Скомпилировав программку с ключом -threaded и запустив с параметрами +RTS -N8 мы найдем, что та же самая задачка стала решаться за 3.4 секунды. Не ровно вчетверо резвее, как ожидалось, но близко.

Это разъясняется затратными расходами на поддержку самой многопоточности, которая была добавлена в программку благодаря компиляции с ключом -threaded. Убедиться в наличии таких затратных расходов можно, запустив многопоточную версию программки без характеристик.

В данном случае она выполнится за 14.3 секунды. Если в той же программке использовать только четыре потока, а не восемь, как было изготовлено ранее, она отработает за 3.8 секунды. Это разъясняется тем, что применяемый нами микропроцессор поддерживает Hyper-Threading и количество логических ядер на нем как раз равно восьми.

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

newChan :: IO (Chan a)

Запись и чтение выполняются при помощи функций writeChan и readChan соответственно. Вызов writeChan никогда не блокируется. Вызов readChan блокируется только в этом случае, если канал пуст:

writeChan :: Chan a -> a -> IO ()
readChan :: Chan a -> IO a

Важную роль играет функция dupChan:

dupChan :: Chan a -> IO (Chan a)

Она делает дубликат канала. Пусть ch — это канал, а ch2 и ch3 — его дубликаты. Сходу после сотворения дубликат пуст, даже если в начальном канале были данные.

При записи сообщения в ch, оно также появится в ch2 и ch3. С этим же фуррором можно писать в ch2 либо ch3, сообщение придет в любой из 3-х каналов. Видите ли, с помощью каналов очень комфортно рассылать различного рода извещения.

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

За кадром остались функции par и pseq, программная транзакционная память (software transactional memory, STM), Data Parallel Haskell, также Cloud Haskell. Все эти вопросы заслуживают отдельных заметок.

Ссылки по теме:

  • Глава Concurrent and multicore programming в Real World Haskell;
  • Страничка Haskell for multicores на HaskellWiki;
  • На момент написания этой заметки готовилась к выходу книжка «Parallel and Concurrent Programming in Haskell», бесплатная онлайн-версия которой доступна тут;

Исходники к заметке вы отыщите в репозитории на BitBucket. Код собирается командой cabal-dev install. Вопросы и дополнения, как обычно, жарко приветствуются.

Дополнение: Программная транзакционная память в Haskell

Похожие статьи

  • Скандальная правда о Haskell и ленивых вычислениях

    В ближайшее время я пару раз упоминал о том, что не совершенно понимаю, как на Haskell можно разрабатывать истинные, огромные проекты. Тому было несколько обстоятельств, но приемущественно меня беспокои...

  • Предпосылки, по которым мне нравится Haskell

    Последний гиковcкий выпуск Radio-T (номер 253) вышел на уникальность увлекательным. Речь зашла о Scala, рефакторинге, TDD, багтрекерах, и даже (наконец!) о моем возлюбленном Haskell. К огорчению, тема...

  • Кроссплатформенное GUI приложение на Haskell

    В этой заметке пойдет речь о разработке кроссплатформенных GUI приложений на языке программирования Haskell с внедрением библиотеки wxWidgets. Повышенное внимание будет уделено уменьшению размера пр...

  • Программные каналы и потоки Linux (UNIX), перенаправление потоков

    Неплохого времени, читатели моего блога!В данной статье желаю систематизировать свои зания по основным механизмам работы программных потоков и каналов в интерпретаторе и в общем в ОС Linux, а так ж...

  • Реализация метода поиска A на Haskell

    Вы когда-нибудь пробовали написать программку, решающую судоку, задачку о волке, козе и капусте либо головоломку вроде кубика Рубика? У этих задач есть кое-что общее — точно понятно изначальное услови...

0

unix прокомментировал 1 сентября 2008 в 16:41

В отличии, скажем, от Erlang, программка на Haskell заканчивается, когда свою работу завершает основной поток. Готовых средств, позволяющих выяснить состояние других потоков, скажем, производится ли данный поток либо уже закончился, не предвидено. Это изготовлено с целью минимизации затратных расходов.

0

unix прокомментировал 1 сентября 2008 в 16:41

потоками в Haskell

Как вы уже могли додуматься, я опять взялся за исследование Haskell. Разумеется, этот язык нельзя учить наскоком. Я решил запастись терпением и вникать во все медлительно, но правильно.

К примеру, не так давно я разбирался с многопоточностью.

Оказалось, что в Haskell употребляются легковесные потоки, так же как в Erlang, Go либо OCaml‘овском Lwt. Взаимодействие меж потоками происходит с помощью захватываемых изменяемых переменных (locking mutable variables), либо MVars.

В отличии, скажем, от Erlang, программка на Haskell заканчивается, когда свою работу завершает основной поток. Готовых средств, позволяющих выяснить состояние других потоков, скажем, производится ли данный поток либо уже закончился, не предвидено. Это изготовлено с целью минимизации затратных расходов.

MVar можно представить, как разделяемую несколькими потоками переменную, доступ к которой ограничивается мьютексом. В отличии от аналогичной конструкции в C++, MVar также может быть пустым. В этом смысле MVar припоминает тип Maybe либо очередь из 1-го элемента.

Написанное выше становится более понятным при взоре на типы главных функций для работы со всем этим хозяйством.

Создание нового потока делается при помощи функции forkIO:

forkIO :: IO () -> IO ThreadId

Новый MVar можно сделать одним из последующих методов:

newEmptyMVar :: IO (MVar a)
newMVar :: a -> IO (MVar a)

Выяснить, является ли MVar пустым, можно с помощью функции isEmptyMVar:

isEmptyMVar :: MVar a -> IO Bool

Для записи в MVar предназначена функция putMVar:

putMVar :: MVar a -> a -> IO ()

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

Разблокирование потоков делается в порядке FIFO.

Функция для чтения из MVar:

takeMVar :: MVar a -> IO a

Аналогично putMVar, функция takeMVar перекрывает текущий поток, если MVar пуст. Остальные характеристики такие же.

Еще пара нужных функций с тривиальной семантикой:

modifyMVar :: MVar a -> (a -> IO (a, b)) -> IO b
modifyMVar_ :: MVar a -> (a -> IO a) -> IO ()

Функция modifyMVar реализована, как обертка над вызовами takeMVar и putMVar. Потому она не является атомарной в случае, если в MVar пишут несколько потоков. Но если все потоки работают с переменной через modifyMVar, тогда все ОК.

Посреди других нужных функций необходимо подчеркнуть readMVar, swapMVar, tryTakeMVar, tryPutMVar, yield и threadDelay (последняя есть исключительно в GHC). За подробностями обращайтесь к документации.

На 1-ый взор может показаться, что этот API несколько убог. В Erlang, к примеру, для взаимодействия меж процессами употребляются очереди, в которые можно класть куда более 1-го элемента. К тому же, эти элементы могут быть хоть какого типа. Но если задуматься, MVar даже круче.

Во-1-х, он как будто горшочек из-под меда. В нем можно держать все что угодно. Это может быть и очередь, и очередь с ценностями, и очередь ограниченного размера и двунаправленный канал.

Во-2-х, каждый поток может иметь сколько угодно таких очередей и каналов. Либо напротив, из одной очереди может читать огромное количество потоков. В конце концов, все это — со статической проверкой типов.

Достаточно теории, давайте уже напишем какую-нибудь программку. Помнится, Erlang хорошо распараллеливал по всем ядрам микропроцессора задачку взлома хэшей способом грубой силы. Поглядим, как с этой же задачей управится Haskell.

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

module Bruteforce.Common where

import Data.Word
import Text.Printf
import Data.Digest.SHA2

passwordList :: String -> Int -> [String]
passwordList charList len =
    stream beginState
  where
    beginState = replicate len charList
    endState = replicate len [ last charList ]
    nextState ((_:[]):xs) = charList : nextState xs
    nextState ((_:ys):xs) = ys : xs
    nextState x = error $ "nextState " ++ show x
    stream st =
      let pw = map head st in
      if st == endState then [ pw ]
                        else pw : stream (nextState st)

hash :: String -> String
hash =
  concatMap (printf "%02x" :: Word8 -> String) .
    toOctets . sha256Ascii

Разумеется, здесь мы не гонимся за эффективностью. Куда важнее на данный момент распараллеливание либо его отсутствие. Обратите повышенное внимание на функцию passwordList.

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

Программка, работающая в один поток:

import Bruteforce.Common
 
main :: IO ()
main = do
  let hashList = [
        -- 1234
        "03ac674216f3e15c761ee1a5e255f067" ++
        "953623c8b388b4459e13f978d7c846f4",
        -- r2d2
        "8adce0a3431e8b11ef69e7f7765021d3" ++
        "ee0b70fff58e0480cadb4c468d78105f"
        ]
      pwLen = 4
      charList = ['0'..'9'] ++ ['a'..'z']
      pwHashList = [(pw,hash pw) | pw <- passwordList charList pwLen]
      rslt = [pw ++ ":" ++ h | (pw,h) <- pwHashList, h `elem` hashList]
  mapM_ putStrLn {- $ take (length hashList) -} rslt

На машине с четырехядерным микропроцессором Intel Core i7-3770K частотой 3.5 GHz программка совладевает с задачей за 12.7 секунд. Можно значительно ускорить ее, не производя перебор после того, как мы сломали все имеющиеся хэши (см закомментированную часть кода). Но в данном случае скорость программки будет находится в зависимости от порядка, в каком перебираются пароли, что не нужно.

Программка, решающая ту же задачку в несколько потоков:

import Bruteforce.Common
потоками в Haskell
import Control.Concurrent
import Control.Monad

workerLoop :: MVar [String] -> MVar [ [String] ] -> String -> Int ->
                [String] -> IO ()
workerLoop taskQueue resultQueue charList pwLen hashList = do
  maybeTask <- modifyMVar taskQueue
                 (\q -> return $ case q of
                                   [] -> ([], Nothing)
                                   (x:xs) -> (xs, Just x))
  case maybeTask of
    Nothing -> return ()

Щас я навалю про потоки

    Just task -> do
      let postfixList = passwordList charList $ pwLen - length task
          pwList = map (task ++) postfixList
          pwHashList = [(pw, hash pw) | pw <- pwList]
          rslt = [pw ++ ":" ++ h | (pw,h) <- pwHashList,
                                    h `elem` hashList]
      rslt `seq` modifyMVar_ resultQueue (\q -> return $ rslt:q)
      workerLoop taskQueue resultQueue charList pwLen hashList

mainLoop :: MVar [ [String] ] -> Int -> IO ()
mainLoop _ Нуль = return ()
mainLoop resultQueue taskNumber = do
  results <- modifyMVar resultQueue (\q -> return ([], q))
  case results of
    [] -> do
      threadDelay 100 тыщ -- 100 ms
      mainLoop resultQueue taskNumber
    _ -> do
      mapM_ (mapM_ putStrLn) results
      mainLoop resultQueue (taskNumber - length results)

main :: IO ()
main = do
  let hashList = [
        -- 1234
        "03ac674216f3e15c761ee1a5e255f067" ++
        "953623c8b388b4459e13f978d7c846f4",
        -- r2d2
потоками в Haskell
        "8adce0a3431e8b11ef69e7f7765021d3" ++
        "ee0b70fff58e0480cadb4c468d78105f"
        ]
      pwLen = 4
      chunkLen = 2
      charList = ['0'..'9'] ++ ['a'..'z']
      taskList = passwordList charList chunkLen
      taskNumber = length taskList
  workerNumber <- getNumCapabilities
  taskQueue <- newMVar taskList
  resultQueue <- newMVar []
  workerNumber `replicateM_` forkIO (workerLoop taskQueue resultQueue
                                             charList pwLen hashList)
  mainLoop resultQueue taskNumber

Функция getNumCapabilities возвращает количество потоков операционной системы, которое употребляется runtime system. Как будет показано ниже, это количество можно задавать при запуске программки. В этом случае разумно использовать столько же легковесных потоков, сколько употребляется реальных.

Программка употребляет две очереди. В реальности это обыденные списки, а никакие не очереди, но мне кажется, будет понятнее, если мыслить о их, как об очередях. Очередь taskQueue имеет тип MVar [String].

В ней содержатся задачки, представляющие из себя префиксы паролей для перебора. Поток берет префикс из очереди (головы перечня) и перебирает все пароли с этим префиксом. Очередь resultQueue имеет тип MVar [ [String] ].

Когда поток заканчивает работу над задачей, он помещает в эту очередь (также голову перечня) перечень строк, которые он желал бы вывести на экран.

Окончание головного потока приводит к окончанию работы всей программки. Потому он должен закончится только после окончания дочерних потоков. Чтоб главный поток не висел без дела, дадим ему кое-какую работу.

Работа эта состоит в том, чтоб разгребать resultQueue и выводить итог работы других потоков на экран. Строго говоря, мы обязаны так делать, так как ввод/вывод в Haskell не является thread safe. Заодно главный поток подсчитывает, сколько задач сейчас осталось выполнить.

Когда счетчик задач обнуляется, главный поток заканчивается.

Направьте внимание на то, как дочерние потоки пишут в resultQueue:

rslt `seq` modifyMVar_ resultQueue (\q -> return $ rslt:q)

Мы помним, что данные в Haskell по дефлоту являются ленивыми, и MVar — не исключение. Если мы просто запишем в resultQueue некий итог, его реальное вычисление произойдет в основном потоке. От параллелизма не будет никакого выигрыша!

Потому мы принудительно вычисляем rslt при помощи функции seq и только после чего изменяем resultQueue. Здесь нельзя не отметить существование пакета strict-concurrency, который предлагает те же MVars (также каналы, речь о которых пойдет ниже), только со серьезной семантикой.

Скомпилировав программку с ключом -threaded и запустив с параметрами +RTS -N8 мы найдем, что та же самая задачка стала решаться за 3.4 секунды. Не ровно вчетверо резвее, как ожидалось, но близко.

Это разъясняется затратными расходами на поддержку самой многопоточности, которая была добавлена в программку благодаря компиляции с ключом -threaded. Убедиться в наличии таких затратных расходов можно, запустив многопоточную версию программки без характеристик.

В данном случае она выполнится за 14.3 секунды. Если в той же программке использовать только четыре потока, а не восемь, как было изготовлено ранее, она отработает за 3.8 секунды. Это разъясняется тем, что применяемый нами микропроцессор поддерживает Hyper-Threading и количество логических ядер на нем как раз равно восьми.

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

newChan :: IO (Chan a)

Запись и чтение выполняются при помощи функций writeChan и readChan соответственно. Вызов writeChan никогда не блокируется. Вызов readChan блокируется только в этом случае, если канал пуст:

writeChan :: Chan a -> a -> IO ()
readChan :: Chan a -> IO a

Важную роль играет функция dupChan:

dupChan :: Chan a -> IO (Chan a)

Она делает дубликат канала. Пусть ch — это канал, а ch2 и ch3 — его дубликаты. Сходу после сотворения дубликат пуст, даже если в начальном канале были данные.

При записи сообщения в ch, оно также появится в ch2 и ch3. С этим же фуррором можно писать в ch2 либо ch3, сообщение придет в любой из 3-х каналов. Видите ли, с помощью каналов очень комфортно рассылать различного рода извещения.

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

За кадром остались функции par и pseq, программная транзакционная память (software transactional memory, STM), Data Parallel Haskell, также Cloud Haskell. Все эти вопросы заслуживают отдельных заметок.

Ссылки по теме:

  • Глава Concurrent and multicore programming в Real World Haskell;
  • Страничка Haskell for multicores на HaskellWiki;
  • На момент написания этой заметки готовилась к выходу книжка «Parallel and Concurrent Programming in Haskell», бесплатная онлайн-версия которой доступна тут;

Исходники к заметке вы отыщите в репозитории на BitBucket. Код собирается командой cabal-dev install. Вопросы и дополнения, как обычно, жарко приветствуются.

Дополнение: Программная транзакционная память в Haskell

Похожие статьи

  • Скандальная правда о Haskell и ленивых вычислениях

    В ближайшее время я пару раз упоминал о том, что не совершенно понимаю, как на Haskell можно разрабатывать истинные, огромные проекты. Тому было несколько обстоятельств, но приемущественно меня беспокои...

  • Предпосылки, по которым мне нравится Haskell

    Последний гиковcкий выпуск Radio-T (номер 253) вышел на уникальность увлекательным. Речь зашла о Scala, рефакторинге, TDD, багтрекерах, и даже (наконец!) о моем возлюбленном Haskell. К огорчению, тема...

  • Кроссплатформенное GUI приложение на Haskell

    В этой заметке пойдет речь о разработке кроссплатформенных GUI приложений на языке программирования Haskell с внедрением библиотеки wxWidgets. Повышенное внимание будет уделено уменьшению размера пр...

  • Программные каналы и потоки Linux (UNIX), перенаправление потоков

    Неплохого времени, читатели моего блога!В данной статье желаю систематизировать свои зания по основным механизмам работы программных потоков и каналов в интерпретаторе и в общем в ОС Linux, а так ж...

  • Реализация метода поиска A на Haskell

    Вы когда-нибудь пробовали написать программку, решающую судоку, задачку о волке, козе и капусте либо головоломку вроде кубика Рубика? У этих задач есть кое-что общее — точно понятно изначальное услови...

0

unix прокомментировал 1 сентября 2008 в 16:41

потоками в Haskell

Как вы уже могли додуматься, я опять взялся за исследование Haskell. Разумеется, этот язык нельзя учить наскоком. Я решил запастись терпением и вникать во все медлительно, но правильно.

К примеру, не так давно я разбирался с многопоточностью.

Оказалось, что в Haskell употребляются легковесные потоки, так же как в Erlang, Go либо OCaml‘овском Lwt. Взаимодействие меж потоками происходит с помощью захватываемых изменяемых переменных (locking mutable variables), либо MVars.

В отличии, скажем, от Erlang, программка на Haskell заканчивается, когда свою работу завершает основной поток. Готовых средств, позволяющих выяснить состояние других потоков, скажем, производится ли данный поток либо уже закончился, не предвидено. Это изготовлено с целью минимизации затратных расходов.

MVar можно представить, как разделяемую несколькими потоками переменную, доступ к которой ограничивается мьютексом. В отличии от аналогичной конструкции в C++, MVar также может быть пустым. В этом смысле MVar припоминает тип Maybe либо очередь из 1-го элемента.

Написанное выше становится более понятным при взоре на типы главных функций для работы со всем этим хозяйством.

Создание нового потока делается при помощи функции forkIO:

forkIO :: IO () -> IO ThreadId

Новый MVar можно сделать одним из последующих методов:

newEmptyMVar :: IO (MVar a)
newMVar :: a -> IO (MVar a)

Выяснить, является ли MVar пустым, можно с помощью функции isEmptyMVar:

isEmptyMVar :: MVar a -> IO Bool

Для записи в MVar предназначена функция putMVar:

putMVar :: MVar a -> a -> IO ()

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

Разблокирование потоков делается в порядке FIFO.

Функция для чтения из MVar:

takeMVar :: MVar a -> IO a

Аналогично putMVar, функция takeMVar перекрывает текущий поток, если MVar пуст. Остальные характеристики такие же.

Еще пара нужных функций с тривиальной семантикой:

modifyMVar :: MVar a -> (a -> IO (a, b)) -> IO b
modifyMVar_ :: MVar a -> (a -> IO a) -> IO ()

Функция modifyMVar реализована, как обертка над вызовами takeMVar и putMVar. Потому она не является атомарной в случае, если в MVar пишут несколько потоков. Но если все потоки работают с переменной через modifyMVar, тогда все ОК.

Посреди других нужных функций необходимо подчеркнуть readMVar, swapMVar, tryTakeMVar, tryPutMVar, yield и threadDelay (последняя есть исключительно в GHC). За подробностями обращайтесь к документации.

На 1-ый взор может показаться, что этот API несколько убог. В Erlang, к примеру, для взаимодействия меж процессами употребляются очереди, в которые можно класть куда более 1-го элемента. К тому же, эти элементы могут быть хоть какого типа. Но если задуматься, MVar даже круче.

Во-1-х, он как будто горшочек из-под меда. В нем можно держать все что угодно. Это может быть и очередь, и очередь с ценностями, и очередь ограниченного размера и двунаправленный канал.

Во-2-х, каждый поток может иметь сколько угодно таких очередей и каналов. Либо напротив, из одной очереди может читать огромное количество потоков. В конце концов, все это — со статической проверкой типов.

Достаточно теории, давайте уже напишем какую-нибудь программку. Помнится, Erlang хорошо распараллеливал по всем ядрам микропроцессора задачку взлома хэшей способом грубой силы. Поглядим, как с этой же задачей управится Haskell.

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

module Bruteforce.Common where

import Data.Word
import Text.Printf
import Data.Digest.SHA2

passwordList :: String -> Int -> [String]
passwordList charList len =
    stream beginState
  where
    beginState = replicate len charList
    endState = replicate len [ last charList ]
    nextState ((_:[]):xs) = charList : nextState xs
    nextState ((_:ys):xs) = ys : xs
    nextState x = error $ "nextState " ++ show x
    stream st =
      let pw = map head st in
      if st == endState then [ pw ]
                        else pw : stream (nextState st)

hash :: String -> String
hash =
  concatMap (printf "%02x" :: Word8 -> String) .
    toOctets . sha256Ascii

Разумеется, здесь мы не гонимся за эффективностью. Куда важнее на данный момент распараллеливание либо его отсутствие. Обратите повышенное внимание на функцию passwordList.

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

Программка, работающая в один поток:

import Bruteforce.Common
 
main :: IO ()
main = do
  let hashList = [
        -- 1234
        "03ac674216f3e15c761ee1a5e255f067" ++
        "953623c8b388b4459e13f978d7c846f4",
        -- r2d2
        "8adce0a3431e8b11ef69e7f7765021d3" ++
        "ee0b70fff58e0480cadb4c468d78105f"
        ]
      pwLen = 4
      charList = ['0'..'9'] ++ ['a'..'z']
      pwHashList = [(pw,hash pw) | pw <- passwordList charList pwLen]
      rslt = [pw ++ ":" ++ h | (pw,h) <- pwHashList, h `elem` hashList]
  mapM_ putStrLn {- $ take (length hashList) -} rslt

На машине с четырехядерным микропроцессором Intel Core i7-3770K частотой 3.5 GHz программка совладевает с задачей за 12.7 секунд. Можно значительно ускорить ее, не производя перебор после того, как мы сломали все имеющиеся хэши (см закомментированную часть кода). Но в данном случае скорость программки будет находится в зависимости от порядка, в каком перебираются пароли, что не нужно.

Программка, решающая ту же задачку в несколько потоков:

import Bruteforce.Common
потоками в Haskell
import Control.Concurrent
import Control.Monad

workerLoop :: MVar [String] -> MVar [ [String] ] -> String -> Int ->
                [String] -> IO ()
workerLoop taskQueue resultQueue charList pwLen hashList = do
  maybeTask <- modifyMVar taskQueue
                 (\q -> return $ case q of
                                   [] -> ([], Nothing)
                                   (x:xs) -> (xs, Just x))
  case maybeTask of
    Nothing -> return ()

Щас я навалю про потоки

    Just task -> do
      let postfixList = passwordList charList $ pwLen - length task
          pwList = map (task ++) postfixList
          pwHashList = [(pw, hash pw) | pw <- pwList]
          rslt = [pw ++ ":" ++ h | (pw,h) <- pwHashList,
                                    h `elem` hashList]
      rslt `seq` modifyMVar_ resultQueue (\q -> return $ rslt:q)
      workerLoop taskQueue resultQueue charList pwLen hashList

mainLoop :: MVar [ [String] ] -> Int -> IO ()
mainLoop _ Нуль = return ()
mainLoop resultQueue taskNumber = do
  results <- modifyMVar resultQueue (\q -> return ([], q))
  case results of
    [] -> do
      threadDelay 100 тыщ -- 100 ms
      mainLoop resultQueue taskNumber
    _ -> do
      mapM_ (mapM_ putStrLn) results
      mainLoop resultQueue (taskNumber - length results)

main :: IO ()
main = do
  let hashList = [
        -- 1234
        "03ac674216f3e15c761ee1a5e255f067" ++
        "953623c8b388b4459e13f978d7c846f4",
        -- r2d2
потоками в Haskell
        "8adce0a3431e8b11ef69e7f7765021d3" ++
        "ee0b70fff58e0480cadb4c468d78105f"
        ]
      pwLen = 4
      chunkLen = 2
      charList = ['0'..'9'] ++ ['a'..'z']
      taskList = passwordList charList chunkLen
      taskNumber = length taskList
  workerNumber <- getNumCapabilities
  taskQueue <- newMVar taskList
  resultQueue <- newMVar []
  workerNumber `replicateM_` forkIO (workerLoop taskQueue resultQueue
                                             charList pwLen hashList)
  mainLoop resultQueue taskNumber

Функция getNumCapabilities возвращает количество потоков операционной системы, которое употребляется runtime system. Как будет показано ниже, это количество можно задавать при запуске программки. В этом случае разумно использовать столько же легковесных потоков, сколько употребляется реальных.

Программка употребляет две очереди. В реальности это обыденные списки, а никакие не очереди, но мне кажется, будет понятнее, если мыслить о их, как об очередях. Очередь taskQueue имеет тип MVar [String].

В ней содержатся задачки, представляющие из себя префиксы паролей для перебора. Поток берет префикс из очереди (головы перечня) и перебирает все пароли с этим префиксом. Очередь resultQueue имеет тип MVar [ [String] ].

Когда поток заканчивает работу над задачей, он помещает в эту очередь (также голову перечня) перечень строк, которые он желал бы вывести на экран.

Окончание головного потока приводит к окончанию работы всей программки. Потому он должен закончится только после окончания дочерних потоков. Чтоб главный поток не висел без дела, дадим ему кое-какую работу.

Работа эта состоит в том, чтоб разгребать resultQueue и выводить итог работы других потоков на экран. Строго говоря, мы обязаны так делать, так как ввод/вывод в Haskell не является thread safe. Заодно главный поток подсчитывает, сколько задач сейчас осталось выполнить.

Когда счетчик задач обнуляется, главный поток заканчивается.

Направьте внимание на то, как дочерние потоки пишут в resultQueue:

rslt `seq` modifyMVar_ resultQueue (\q -> return $ rslt:q)

Мы помним, что данные в Haskell по дефлоту являются ленивыми, и MVar — не исключение. Если мы просто запишем в resultQueue некий итог, его реальное вычисление произойдет в основном потоке. От параллелизма не будет никакого выигрыша!

Потому мы принудительно вычисляем rslt при помощи функции seq и только после чего изменяем resultQueue. Здесь нельзя не отметить существование пакета strict-concurrency, который предлагает те же MVars (также каналы, речь о которых пойдет ниже), только со серьезной семантикой.

Скомпилировав программку с ключом -threaded и запустив с параметрами +RTS -N8 мы найдем, что та же самая задачка стала решаться за 3.4 секунды. Не ровно вчетверо резвее, как ожидалось, но близко.

Это разъясняется затратными расходами на поддержку самой многопоточности, которая была добавлена в программку благодаря компиляции с ключом -threaded. Убедиться в наличии таких затратных расходов можно, запустив многопоточную версию программки без характеристик.

В данном случае она выполнится за 14.3 секунды. Если в той же программке использовать только четыре потока, а не восемь, как было изготовлено ранее, она отработает за 3.8 секунды. Это разъясняется тем, что применяемый нами микропроцессор поддерживает Hyper-Threading и количество логических ядер на нем как раз равно восьми.

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

newChan :: IO (Chan a)

Запись и чтение выполняются при помощи функций writeChan и readChan соответственно. Вызов writeChan никогда не блокируется. Вызов readChan блокируется только в этом случае, если канал пуст:

writeChan :: Chan a -> a -> IO ()
readChan :: Chan a -> IO a

Важную роль играет функция dupChan:

dupChan :: Chan a -> IO (Chan a)

Она делает дубликат канала. Пусть ch — это канал, а ch2 и ch3 — его дубликаты. Сходу после сотворения дубликат пуст, даже если в начальном канале были данные.

При записи сообщения в ch, оно также появится в ch2 и ch3. С этим же фуррором можно писать в ch2 либо ch3, сообщение придет в любой из 3-х каналов. Видите ли, с помощью каналов очень комфортно рассылать различного рода извещения.

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

За кадром остались функции par и pseq, программная транзакционная память (software transactional memory, STM), Data Parallel Haskell, также Cloud Haskell. Все эти вопросы заслуживают отдельных заметок.

Ссылки по теме:

  • Глава Concurrent and multicore programming в Real World Haskell;
  • Страничка Haskell for multicores на HaskellWiki;
  • На момент написания этой заметки готовилась к выходу книжка «Parallel and Concurrent Programming in Haskell», бесплатная онлайн-версия которой доступна тут;

Исходники к заметке вы отыщите в репозитории на BitBucket. Код собирается командой cabal-dev install. Вопросы и дополнения, как обычно, жарко приветствуются.

Дополнение: Программная транзакционная память в Haskell

Похожие статьи

  • Скандальная правда о Haskell и ленивых вычислениях

    В ближайшее время я пару раз упоминал о том, что не совершенно понимаю, как на Haskell можно разрабатывать истинные, огромные проекты. Тому было несколько обстоятельств, но приемущественно меня беспокои...

  • Предпосылки, по которым мне нравится Haskell

    Последний гиковcкий выпуск Radio-T (номер 253) вышел на уникальность увлекательным. Речь зашла о Scala, рефакторинге, TDD, багтрекерах, и даже (наконец!) о моем возлюбленном Haskell. К огорчению, тема...

  • Кроссплатформенное GUI приложение на Haskell

    В этой заметке пойдет речь о разработке кроссплатформенных GUI приложений на языке программирования Haskell с внедрением библиотеки wxWidgets. Повышенное внимание будет уделено уменьшению размера пр...

  • Программные каналы и потоки Linux (UNIX), перенаправление потоков

    Неплохого времени, читатели моего блога!В данной статье желаю систематизировать свои зания по основным механизмам работы программных потоков и каналов в интерпретаторе и в общем в ОС Linux, а так ж...

  • Реализация метода поиска A на Haskell

    Вы когда-нибудь пробовали написать программку, решающую судоку, задачку о волке, козе и капусте либо головоломку вроде кубика Рубика? У этих задач есть кое-что общее — точно понятно изначальное услови...

0

unix прокомментировал 1 сентября 2008 в 16:41

потоками в Haskell

Как вы уже могли додуматься, я опять взялся за исследование Haskell. Разумеется, этот язык нельзя учить наскоком. Я решил запастись терпением и вникать во все медлительно, но правильно.

К примеру, не так давно я разбирался с многопоточностью.

Оказалось, что в Haskell употребляются легковесные потоки, так же как в Erlang, Go либо OCaml‘овском Lwt. Взаимодействие меж потоками происходит с помощью захватываемых изменяемых переменных (locking mutable variables), либо MVars.

В отличии, скажем, от Erlang, программка на Haskell заканчивается, когда свою работу завершает основной поток. Готовых средств, позволяющих выяснить состояние других потоков, скажем, производится ли данный поток либо уже закончился, не предвидено. Это изготовлено с целью минимизации затратных расходов.

MVar можно представить, как разделяемую несколькими потоками переменную, доступ к которой ограничивается мьютексом. В отличии от аналогичной конструкции в C++, MVar также может быть пустым. В этом смысле MVar припоминает тип Maybe либо очередь из 1-го элемента.

Написанное выше становится более понятным при взоре на типы главных функций для работы со всем этим хозяйством.

Создание нового потока делается при помощи функции forkIO:

forkIO :: IO () -> IO ThreadId

Новый MVar можно сделать одним из последующих методов:

newEmptyMVar :: IO (MVar a)
newMVar :: a -> IO (MVar a)

Выяснить, является ли MVar пустым, можно с помощью функции isEmptyMVar:

isEmptyMVar :: MVar a -> IO Bool

Для записи в MVar предназначена функция putMVar:

putMVar :: MVar a -> a -> IO ()

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

Разблокирование потоков делается в порядке FIFO.

Функция для чтения из MVar:

takeMVar :: MVar a -> IO a

Аналогично putMVar, функция takeMVar перекрывает текущий поток, если MVar пуст. Остальные характеристики такие же.

Еще пара нужных функций с тривиальной семантикой:

modifyMVar :: MVar a -> (a -> IO (a, b)) -> IO b
modifyMVar_ :: MVar a -> (a -> IO a) -> IO ()

Функция modifyMVar реализована, как обертка над вызовами takeMVar и putMVar. Потому она не является атомарной в случае, если в MVar пишут несколько потоков. Но если все потоки работают с переменной через modifyMVar, тогда все ОК.

Посреди других нужных функций необходимо подчеркнуть readMVar, swapMVar, tryTakeMVar, tryPutMVar, yield и threadDelay (последняя есть исключительно в GHC). За подробностями обращайтесь к документации.

На 1-ый взор может показаться, что этот API несколько убог. В Erlang, к примеру, для взаимодействия меж процессами употребляются очереди, в которые можно класть куда более 1-го элемента. К тому же, эти элементы могут быть хоть какого типа. Но если задуматься, MVar даже круче.

Во-1-х, он как будто горшочек из-под меда. В нем можно держать все что угодно. Это может быть и очередь, и очередь с ценностями, и очередь ограниченного размера и двунаправленный канал.

Во-2-х, каждый поток может иметь сколько угодно таких очередей и каналов. Либо напротив, из одной очереди может читать огромное количество потоков. В конце концов, все это — со статической проверкой типов.

Достаточно теории, давайте уже напишем какую-нибудь программку. Помнится, Erlang хорошо распараллеливал по всем ядрам микропроцессора задачку взлома хэшей способом грубой силы. Поглядим, как с этой же задачей управится Haskell.

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

module Bruteforce.Common where

import Data.Word
import Text.Printf
import Data.Digest.SHA2

passwordList :: String -> Int -> [String]
passwordList charList len =
    stream beginState
  where
    beginState = replicate len charList
    endState = replicate len [ last charList ]
    nextState ((_:[]):xs) = charList : nextState xs
    nextState ((_:ys):xs) = ys : xs
    nextState x = error $ "nextState " ++ show x
    stream st =
      let pw = map head st in
      if st == endState then [ pw ]
                        else pw : stream (nextState st)

hash :: String -> String
hash =
  concatMap (printf "%02x" :: Word8 -> String) .
    toOctets . sha256Ascii

Разумеется, здесь мы не гонимся за эффективностью. Куда важнее на данный момент распараллеливание либо его отсутствие. Обратите повышенное внимание на функцию passwordList.

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

Программка, работающая в один поток:

import Bruteforce.Common
 
main :: IO ()
main = do
  let hashList = [
        -- 1234
        "03ac674216f3e15c761ee1a5e255f067" ++
        "953623c8b388b4459e13f978d7c846f4",
        -- r2d2
        "8adce0a3431e8b11ef69e7f7765021d3" ++
        "ee0b70fff58e0480cadb4c468d78105f"
        ]
      pwLen = 4
      charList = ['0'..'9'] ++ ['a'..'z']
      pwHashList = [(pw,hash pw) | pw <- passwordList charList pwLen]
      rslt = [pw ++ ":" ++ h | (pw,h) <- pwHashList, h `elem` hashList]
  mapM_ putStrLn {- $ take (length hashList) -} rslt

На машине с четырехядерным микропроцессором Intel Core i7-3770K частотой 3.5 GHz программка совладевает с задачей за 12.7 секунд. Можно значительно ускорить ее, не производя перебор после того, как мы сломали все имеющиеся хэши (см закомментированную часть кода). Но в данном случае скорость программки будет находится в зависимости от порядка, в каком перебираются пароли, что не нужно.

Программка, решающая ту же задачку в несколько потоков:

import Bruteforce.Common
потоками в Haskell
import Control.Concurrent
import Control.Monad

workerLoop :: MVar [String] -> MVar [ [String] ] -> String -> Int ->
                [String] -> IO ()
workerLoop taskQueue resultQueue charList pwLen hashList = do
  maybeTask <- modifyMVar taskQueue
                 (\q -> return $ case q of
                                   [] -> ([], Nothing)
                                   (x:xs) -> (xs, Just x))
  case maybeTask of
    Nothing -> return ()

Щас я навалю про потоки

    Just task -> do
      let postfixList = passwordList charList $ pwLen - length task
          pwList = map (task ++) postfixList
          pwHashList = [(pw, hash pw) | pw <- pwList]
          rslt = [pw ++ ":" ++ h | (pw,h) <- pwHashList,
                                    h `elem` hashList]
      rslt `seq` modifyMVar_ resultQueue (\q -> return $ rslt:q)
      workerLoop taskQueue resultQueue charList pwLen hashList

mainLoop :: MVar [ [String] ] -> Int -> IO ()
mainLoop _ Нуль = return ()
mainLoop resultQueue taskNumber = do
  results <- modifyMVar resultQueue (\q -> return ([], q))
  case results of
    [] -> do
      threadDelay 100 тыщ -- 100 ms
      mainLoop resultQueue taskNumber
    _ -> do
      mapM_ (mapM_ putStrLn) results
      mainLoop resultQueue (taskNumber - length results)

main :: IO ()
main = do
  let hashList = [
        -- 1234
        "03ac674216f3e15c761ee1a5e255f067" ++
        "953623c8b388b4459e13f978d7c846f4",
        -- r2d2
потоками в Haskell
        "8adce0a3431e8b11ef69e7f7765021d3" ++
        "ee0b70fff58e0480cadb4c468d78105f"
        ]
      pwLen = 4
      chunkLen = 2
      charList = ['0'..'9'] ++ ['a'..'z']
      taskList = passwordList charList chunkLen
      taskNumber = length taskList
  workerNumber <- getNumCapabilities
  taskQueue <- newMVar taskList
  resultQueue <- newMVar []
  workerNumber `replicateM_` forkIO (workerLoop taskQueue resultQueue
                                             charList pwLen hashList)
  mainLoop resultQueue taskNumber

Функция getNumCapabilities возвращает количество потоков операционной системы, которое употребляется runtime system. Как будет показано ниже, это количество можно задавать при запуске программки. В этом случае разумно использовать столько же легковесных потоков, сколько употребляется реальных.

Программка употребляет две очереди. В реальности это обыденные списки, а никакие не очереди, но мне кажется, будет понятнее, если мыслить о их, как об очередях. Очередь taskQueue имеет тип MVar [String].

В ней содержатся задачки, представляющие из себя префиксы паролей для перебора. Поток берет префикс из очереди (головы перечня) и перебирает все пароли с этим префиксом. Очередь resultQueue имеет тип MVar [ [String] ].

Когда поток заканчивает работу над задачей, он помещает в эту очередь (также голову перечня) перечень строк, которые он желал бы вывести на экран.

Окончание головного потока приводит к окончанию работы всей программки. Потому он должен закончится только после окончания дочерних потоков. Чтоб главный поток не висел без дела, дадим ему кое-какую работу.

Работа эта состоит в том, чтоб разгребать resultQueue и выводить итог работы других потоков на экран. Строго говоря, мы обязаны так делать, так как ввод/вывод в Haskell не является thread safe. Заодно главный поток подсчитывает, сколько задач сейчас осталось выполнить.

Когда счетчик задач обнуляется, главный поток заканчивается.

Направьте внимание на то, как дочерние потоки пишут в resultQueue:

rslt `seq` modifyMVar_ resultQueue (\q -> return $ rslt:q)

Мы помним, что данные в Haskell по дефлоту являются ленивыми, и MVar — не исключение. Если мы просто запишем в resultQueue некий итог, его реальное вычисление произойдет в основном потоке. От параллелизма не будет никакого выигрыша!

Потому мы принудительно вычисляем rslt при помощи функции seq и только после чего изменяем resultQueue. Здесь нельзя не отметить существование пакета strict-concurrency, который предлагает те же MVars (также каналы, речь о которых пойдет ниже), только со серьезной семантикой.

Скомпилировав программку с ключом -threaded и запустив с параметрами +RTS -N8 мы найдем, что та же самая задачка стала решаться за 3.4 секунды. Не ровно вчетверо резвее, как ожидалось, но близко.

Это разъясняется затратными расходами на поддержку самой многопоточности, которая была добавлена в программку благодаря компиляции с ключом -threaded. Убедиться в наличии таких затратных расходов можно, запустив многопоточную версию программки без характеристик.

В данном случае она выполнится за 14.3 секунды. Если в той же программке использовать только четыре потока, а не восемь, как было изготовлено ранее, она отработает за 3.8 секунды. Это разъясняется тем, что применяемый нами микропроцессор поддерживает Hyper-Threading и количество логических ядер на нем как раз равно восьми.

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

newChan :: IO (Chan a)

Запись и чтение выполняются при помощи функций writeChan и readChan соответственно. Вызов writeChan никогда не блокируется. Вызов readChan блокируется только в этом случае, если канал пуст:

writeChan :: Chan a -> a -> IO ()
readChan :: Chan a -> IO a

Важную роль играет функция dupChan:

dupChan :: Chan a -> IO (Chan a)

Она делает дубликат канала. Пусть ch — это канал, а ch2 и ch3 — его дубликаты. Сходу после сотворения дубликат пуст, даже если в начальном канале были данные.

При записи сообщения в ch, оно также появится в ch2 и ch3. С этим же фуррором можно писать в ch2 либо ch3, сообщение придет в любой из 3-х каналов. Видите ли, с помощью каналов очень комфортно рассылать различного рода извещения.

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

За кадром остались функции par и pseq, программная транзакционная память (software transactional memory, STM), Data Parallel Haskell, также Cloud Haskell. Все эти вопросы заслуживают отдельных заметок.

Ссылки по теме:

  • Глава Concurrent and multicore programming в Real World Haskell;
  • Страничка Haskell for multicores на HaskellWiki;
  • На момент написания этой заметки готовилась к выходу книжка «Parallel and Concurrent Programming in Haskell», бесплатная онлайн-версия которой доступна тут;

Исходники к заметке вы отыщите в репозитории на BitBucket. Код собирается командой cabal-dev install. Вопросы и дополнения, как обычно, жарко приветствуются.

Дополнение: Программная транзакционная память в Haskell

Похожие статьи

  • Скандальная правда о Haskell и ленивых вычислениях

    В ближайшее время я пару раз упоминал о том, что не совершенно понимаю, как на Haskell можно разрабатывать истинные, огромные проекты. Тому было несколько обстоятельств, но приемущественно меня беспокои...

  • Предпосылки, по которым мне нравится Haskell

    Последний гиковcкий выпуск Radio-T (номер 253) вышел на уникальность увлекательным. Речь зашла о Scala, рефакторинге, TDD, багтрекерах, и даже (наконец!) о моем возлюбленном Haskell. К огорчению, тема...

  • Кроссплатформенное GUI приложение на Haskell

    В этой заметке пойдет речь о разработке кроссплатформенных GUI приложений на языке программирования Haskell с внедрением библиотеки wxWidgets. Повышенное внимание будет уделено уменьшению размера пр...

  • Программные каналы и потоки Linux (UNIX), перенаправление потоков

    Неплохого времени, читатели моего блога!В данной статье желаю систематизировать свои зания по основным механизмам работы программных потоков и каналов в интерпретаторе и в общем в ОС Linux, а так ж...

  • Реализация метода поиска A на Haskell

    Вы когда-нибудь пробовали написать программку, решающую судоку, задачку о волке, козе и капусте либо головоломку вроде кубика Рубика? У этих задач есть кое-что общее — точно понятно изначальное услови...

0

unix прокомментировал 15 августа 2008 в 17:31

UNIX

В одном из собственных прошлых постов (см Чем неплох и чем плох Linux) я троллил о преимуществах рассуждал об различиях операционных систем семейства UNIX (Linux и *BSD) от семейства Windows и о том, кому и для чего стоит попробовать перейти на Ubuntu. Пожалуй, самый комфортабельный метод выполнить переход — в течение некого времени использовать под Windows только тот софт, который есть под Linux.

Тогда после смены операционной системы вам фактически ничего не поменяется. Эта заметка представляет собой обзор Linux-аналогов фаворитных Windows-программ. Внимание — под катом Четыреста Кб снимков экрана.

Все упомянутые в заметке программки полностью бесплатны и использовать их можно как под Windows, так и под Linux. Даже если вы не планируете отрешаться от Windows, почему бы для вас не использовать бесплатный и законный Thunderbird заместо крякнутого The Bat! либо OpenOffice заместо Microsoft Office? Поверьте, документы и презентации в OpenOffice получаются ничем не ужаснее, чем в Microsoft Office.

1. Джентльменский набор

Я так подозреваю, что посреди читателей все ну либо практически все слышали о Firefox, Thunderbird, OpenOffice и прочем бесплатном софте. Я приведу только лаконичный перечень этих и неких других программ, без снимков экрана и подробного описания, так как вероятнее всего вы с ними уже знакомы.

  • Firefox, Opera, Chrome — все эти браузеры отлично известны хоть какому более-менее опытнейшему интернет-пользователю. И они все портированы под Linux.
  • ThunderBird — кроссплатформенный почтовый клиент от компании Мозилла. По своим способностям ничем не уступает The Bat. Меня лично поражает, что кто-то до сего времени пользуется последним.
  • OpenOffice — бесплатный офисный пакет, разрабатываемый под началом Oracle Corporation (ранее — Sun Microsystems). Имеет форк LibreOffice, работы над которым ведет независящее собщество разработчиков. Формат OpenDocument был принят в качестве муниципального эталона Рф и ряда других государств.
  • Gimp, Inkscape — бесплатные редакторы растровой и векторной графики соответственно (аналоги Photoshop и Corel Draw / Adobe Illustrator). Все изображения в этом блоге я редактирую при помощи Gimp.
  • Evince — свободная программка для чтения PDF/DjVu файлов. Невзирая на свою малую известность, со собственной задачей Evince совладевает ничем не ужаснее Adobe Reader.

Дополнение: Также из почтовых клиентов заслуживает внимания Claws Mail, в особенности если вы находите Thunderbird очень томным и неспешным.

2. P2P-клиенты

Более пользующимися популярностью p2p-сетями сейчас являются BitTorrent и eDonkey2000. Еще я слышал про DC, но никогда им не воспользовался и не понимаю, как он вообщем может работать.

Остальные пиринговые сети, к примеру, Freenet, в текущее время не достаточно всераспространены и являются быстрее экспериментальными. Так что в рамках этой статьи я расскажу только о 2-ух p2p-клиентах.

UNIX

1-ый именуется Deluge и является всеполноценным аналогом BitTorrent клиента uTorrent.

#image.jpg

2-ой — aMule, представляет собой брата-близнеца ed2k-клиента eMule.

#image.jpg

Даже не знаю, что еще о их можно поведать. Офсайты программ — deluge-torrent.org и amule.org соответственно.

UNIX

Дополнение: Как выяснилось, время от времени Deluge может жрать очень много памяти (см снимок экрана в конце). Отлично зарекомендовал себя BitTorrent клиент sharkTorrent (снимок экрана, офсайт). Невзирая на простой вид, он имеет весь функционал, нужный торрент-клиенту.

В отличии от Deluge, написан на C++, со всеми вытекающими. Обратите также внимание на qBittorrent и Transmission.

3. Игры

Принято считать, что под Linux нет компьютерных игр. По сути это не так — игр под Linux много и большая часть из их бесплатные. Прямо рай для игромана!

Я расскажу только о нескольких игрушках, которые мне очень нравятся.

Дополнение: С возникновением Steam игр для Linux стала значительно больше.

Nexuiz — это шутер от первого лица. У меня он больше всего ассоциаций вызывает с Unreal Tournament. Невзирая на то, что linux-игры, обычно, не требовательны к ресурсам компьютера, для Nexuiz лучше запастись неплохой видеокартой.

#image.jpg

Мне так нравится эта игра, что я решил в порядке исключения выложить два ее снимка экрана.

#image.jpg

Поглядеть больше снимков экрана и скачать игру можно на офсайте Nexuiz.

UNIX

Hedgewars — 2-ая моя возлюбленная игра. Она очень похожа на Worms Armageddon, только заместо червяков ведут войну ежики.

#image.jpg

На официальном сервере игры всегда много игроков — создаете игру, ожидаете минутку и можно начинать! В особенности любопытно чатиться во время игры с какими-нибудь французами либо германцами. Разработчики часто добавляют в игру новые способности.

Как-то я пару месяцев не играл в Hedgewars. За этот период времени в игре появились телепорты, лазерные прицелы, коктейль Молотова и много другого орудия. Когда я зашел в игру, то просто не вызнал ее.

Поглядеть демо видеоклипы и скачать Hedgewars можно на hedgewars.org. Кстати, на форуме проекта тусуется много русских юзеров.

FreeCiv — это свободный аналог игры Sid Meier’s Civilization II. Заскучали по строительству дорог, развитию науки и захвату городов? Означает, FreeCiv предназначена для вас!

Офсайт игры хостится на wikia.com.

#image.jpg

Если вы думаете, что разработчики свободных игр не способны придумать что-то без помощи других, поиграйте в Battle for Wesnoth (wesnoth.org). Эта пошаговая стратегия не похожа ни на Героев, ни на Disciples, ни на что или другое.

Карта, к примеру, разбивается на шестиугольники, а сила и скорость юнитов зависят от времени суток и того, на каком поле они находятся. Вселенная игры заселена колдунами, орками, ельфами ну и конечно людьми. Можно играть по сети, а можно проходить (достаточно длинноватые!) компании.

#image.jpg

Существует еще величавое огромное количество open source игр. Когда-то в этом блоге я писал про шахматную игру Brutal Chess. Еще мне очень нравятся игры LordsAWar (аналог Warlords II) и XGalaga.

Уверен, что каждый может отыскать много Linux-игр по вкусу.

4. Интернет-чаты

Свободных программ для общения в IRC, ICQ либо Jabber достаточно много. Как мне понятно, одним из самых фаворитных клиентов в этой области является Pidgin. Вы спросите меня, как же Skype?

Skype отлично работает под Linux. Также у него есть свободный аналог, именуется он Ekiga.

#image.jpg

Слева на снимке экрана изображен Pidgin, справа — Ekiga. Pidgin я временами использую и смею заверить, что он ничем не ужаснее QIP. Голосом я по сети не общаюсь и никогда не общался (почему — в свое время я писал в этом посте), так что о Ekiga ничего сказать не могу.

Дополнение: Очередной неплохой ICQ/Jabber/Mail.ru клиент — QutIM. Он, в отличии от Pidgin, больше похож на старенькый хороший QIP. Если вы пользуетесь только Jabber, направьте внимание на Psi.

UNIX

Дополнение: Также я желал включить в этот раздел IRC-клиент XChat, но не сделал это, так как его версия для Windows платная. Оказалось, что есть бесплатные сборки — SilvereX и ZeroStress.

UNIX

5. Графика и видео

Кроме упомянутых Gimp и Inkscape я желал бы направить внимание еще на две программки — MPlayer и XNView.

MPlayer — это видео-проигрыватель, ставший эталоном де-факто в мире UNIX.

Bloat: How and Why UNIX Grew Up (and Out) - Rusty Russell,Matt Evans

#image.jpg

Под Windows я бы рекомендовал использовать его сборку под заглавием SMPLayer. Это фактически тот же Light Alloy, исключительно в нем не надо отгадывать загадки про лук и морковку (кто пробовал — тот знает).

Как работают DNS-серверы в UNIX-системах?

XNView — свободная программка для просмотра изображений.

#image.jpg

XNView предоставляет много нужных функций — от очевидных обрезать/повернуть/масштабировать до удаления эффекта бардовых глаз и сотворения снимков экрана. Кстати, все снимки экрана к этой заметке были изготовлены при помощи XNView (под Windows 7, который шел в комплекте с моим новым ноутбуком).

6. Разработка

Geany — это среда разработки с открытым начальным кодом.

#image.jpg

Geany поддерживает плагины, подсветку синтаксиса 40+ языков программирования, фолдинг, автодополнение, автоматическое закрытие HTML/XML-тегов и другие полезные функции. Очень легкая и приятная в использовании программка.

Дополнение: Программерам на C/C++/D также советую направить внимание на кроссплатформенную IDE Code::Blocks. Основная фишка — уплотненная интеграция с библиотекой wxWidgets, что позволяет стремительно создавать кроссплатформенные GUI приложения. Ну и для всего остального Code::Blocks тоже годится.

UNIX

Dia — свободный редактор диаграмм и блок-схем, кандидатура Microsoft Visio.

#image.jpg

Я поведал об этой программке у нас в кабинете и многие с радостью на нее подсели. Похоже, что она хорошо совладевает со собственной задачей. Направьте внимание на количество диаграмм, поддерживаемых Dia (на снимке экрана вы видите меньше их половины).

Существует программка, позволяющая преобразовывать диаграммы, сделанные в Dia, в программный код.

Qemu — бесплатная виртуальная машина, аналог VMWare Player (Workstation).

#image.jpg

На снимке экрана вы видите Qemu Manager — сборку Qemu для Windows. Я отнес этот эмулятор к разделу «Разработка», так как обычно эмуляторами пользуются как раз программеры. К примеру, когда необходимо протестировать кроссплатформенную программку либо при написании драйверов.

Дополнение: Суровый недочет Qemu — неспешная скорость работы. VirtualBox работает намного резвее и также портирован под Юниксы. К примеру, во FreeBSD ему соответствует пакет vboxgtk.

Kompozer — свободный WYSIWYG HTML-редактор, аналог Dreamweaver.

#image.jpg

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

Скачать можно на kompozer.net.

Дополнение: См также отладчик kgdb.

7. Заключение

Я надеюсь, что данная заметка дозволит для вас составить представление о том, как богат выбор программного обеспечения в мире UNIX. Я желал поведать еще об одной программке, но не знал к какому разделу ее отнести.

Она именуется Double Commander и представляет собой двухоконный файловый менеджер, как Total Commander. Оставляю для вас его для самостоятельного исследования.

UNIX

Дополнение: Запамятовал про RealVNC (бесплатный аналог RAdmin) и PeaZip (аналог WinRAR). Как мне понятно, у RealVNC есть препядствия с шифрованием трафика, так что примите надлежащие меры безопасности (VPN, SSH-туннелинг, …).

Дополнение: WebMoney Keeper Classic под UNIX нет, но ничто не мешает перейти на Keeper Light либо Keeper Mini. Для работы с ними не надо ничего, не считая веб-браузера. Не знаю, можно ли перейти с Classic на Light средствами самой системы, но, как минимум, ничто не мешает зарегистрироваться в Light и перевести на него все средства.

Дополнение: Также удалось отыскать кроссплатформенный аудио-плеер со странноватым заглавием Aqualung. Поддерживает все пользующиеся популярностью аудио-форматы, интернет-радио, RSS и Atom подкасты, скины, также многие другие фишки. Работает под Windows, Linux, MacOS, *BSD.

Судя по логам subversion, проект живой.

Еще одна подмена Winamp — аудиоплеер DeaDBeeF. Есть версии для Linux, *BSD и Android. К огорчению, под Windows не портирован. Повеселили способности сворачивать программку в трей, редактировать мета-информацию аудио-файлов, также работать с несколькими плейлистами.

Переключение меж последними происходит при помощи вкладок. По моим ощущениям, DeadDBeeF во много раз удобнее Aqualung.

За наводку спасибо товарищу SHok.

Дополнение: Отыскал еще парочку нужных программ: RawStudio — для работы с фото в RAW, Umbrello — UML редактор с возможностью генерации кода.

Дополнение: Дмитрий Дегтярев порекомендовал мне звуковой редактор Audacity. Редактор прост в использовании и при всем этом имеет большая часть нужных функций — нарезание дорожек, накладывание звука, управление громкостью и тп, также разные фильтры.

Похожие статьи

  • Философия UNIX либо fork() vs CreateThread()

    Вот уже вторую неделю в Москве царствует нестерпимая жара. Вентиляторы и кондюки в магазинах не отыскать, прохладительные напитки не помогают. Уровень желания работать (УЖР) по десятибалльной шкале...

  • Права доступа Unix

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

  • Права доступа в Unix

    Нашел старую статью по правам доступа, я понимаю на данный момент есть ACL и прочее, поэтому некоторые постулаты нужно принимать с фильтрацией, но все же новым думаю полезно. Файлы в Linux име...

  • Программные каналы и потоки Linux (UNIX), перенаправление потоков

    Неплохого времени, читатели моего блога!В данной статье желаю систематизировать свои зания по основным механизмам работы программных потоков и каналов в интерпретаторе и в общем в ОС Linux, а так ж...

  • 15000 день unix эпохи

    На данный момент, 20 6 января, в полночь по GMT, наступил Пятнадцать тыщ день от начала летосчисления Unix машин. Юниксоиды всех стран встречаются, празднуют, проводят массовые гулянья и гадают. Встречи локальн...

0

unix прокомментировал 15 августа 2008 в 17:31

Тогда после смены операционной системы вам фактически ничего не поменяется. Эта заметка представляет собой обзор Linux-аналогов фаворитных Windows-программ. Внимание — под катом Четыреста Кб снимков экрана.

0

unix прокомментировал 15 августа 2008 в 17:31

UNIX

В одном из собственных прошлых постов (см Чем неплох и чем плох Linux) я троллил о преимуществах рассуждал об различиях операционных систем семейства UNIX (Linux и *BSD) от семейства Windows и о том, кому и для чего стоит попробовать перейти на Ubuntu. Пожалуй, самый комфортабельный метод выполнить переход — в течение некого времени использовать под Windows только тот софт, который есть под Linux.

Тогда после смены операционной системы вам фактически ничего не поменяется. Эта заметка представляет собой обзор Linux-аналогов фаворитных Windows-программ. Внимание — под катом Четыреста Кб снимков экрана.

Все упомянутые в заметке программки полностью бесплатны и использовать их можно как под Windows, так и под Linux. Даже если вы не планируете отрешаться от Windows, почему бы для вас не использовать бесплатный и законный Thunderbird заместо крякнутого The Bat! либо OpenOffice заместо Microsoft Office? Поверьте, документы и презентации в OpenOffice получаются ничем не ужаснее, чем в Microsoft Office.

1. Джентльменский набор

Я так подозреваю, что посреди читателей все ну либо практически все слышали о Firefox, Thunderbird, OpenOffice и прочем бесплатном софте. Я приведу только лаконичный перечень этих и неких других программ, без снимков экрана и подробного описания, так как вероятнее всего вы с ними уже знакомы.

  • Firefox, Opera, Chrome — все эти браузеры отлично известны хоть какому более-менее опытнейшему интернет-пользователю. И они все портированы под Linux.
  • ThunderBird — кроссплатформенный почтовый клиент от компании Мозилла. По своим способностям ничем не уступает The Bat. Меня лично поражает, что кто-то до сего времени пользуется последним.
  • OpenOffice — бесплатный офисный пакет, разрабатываемый под началом Oracle Corporation (ранее — Sun Microsystems). Имеет форк LibreOffice, работы над которым ведет независящее собщество разработчиков. Формат OpenDocument был принят в качестве муниципального эталона Рф и ряда других государств.
  • Gimp, Inkscape — бесплатные редакторы растровой и векторной графики соответственно (аналоги Photoshop и Corel Draw / Adobe Illustrator). Все изображения в этом блоге я редактирую при помощи Gimp.
  • Evince — свободная программка для чтения PDF/DjVu файлов. Невзирая на свою малую известность, со собственной задачей Evince совладевает ничем не ужаснее Adobe Reader.

Дополнение: Также из почтовых клиентов заслуживает внимания Claws Mail, в особенности если вы находите Thunderbird очень томным и неспешным.

2. P2P-клиенты

Более пользующимися популярностью p2p-сетями сейчас являются BitTorrent и eDonkey2000. Еще я слышал про DC, но никогда им не воспользовался и не понимаю, как он вообщем может работать.

Остальные пиринговые сети, к примеру, Freenet, в текущее время не достаточно всераспространены и являются быстрее экспериментальными. Так что в рамках этой статьи я расскажу только о 2-ух p2p-клиентах.

UNIX

1-ый именуется Deluge и является всеполноценным аналогом BitTorrent клиента uTorrent.

#image.jpg

2-ой — aMule, представляет собой брата-близнеца ed2k-клиента eMule.

#image.jpg

Даже не знаю, что еще о их можно поведать. Офсайты программ — deluge-torrent.org и amule.org соответственно.

UNIX

Дополнение: Как выяснилось, время от времени Deluge может жрать очень много памяти (см снимок экрана в конце). Отлично зарекомендовал себя BitTorrent клиент sharkTorrent (снимок экрана, офсайт). Невзирая на простой вид, он имеет весь функционал, нужный торрент-клиенту.

В отличии от Deluge, написан на C++, со всеми вытекающими. Обратите также внимание на qBittorrent и Transmission.

3. Игры

Принято считать, что под Linux нет компьютерных игр. По сути это не так — игр под Linux много и большая часть из их бесплатные. Прямо рай для игромана!

Я расскажу только о нескольких игрушках, которые мне очень нравятся.

Дополнение: С возникновением Steam игр для Linux стала значительно больше.

Nexuiz — это шутер от первого лица. У меня он больше всего ассоциаций вызывает с Unreal Tournament. Невзирая на то, что linux-игры, обычно, не требовательны к ресурсам компьютера, для Nexuiz лучше запастись неплохой видеокартой.

#image.jpg

Мне так нравится эта игра, что я решил в порядке исключения выложить два ее снимка экрана.

#image.jpg

Поглядеть больше снимков экрана и скачать игру можно на офсайте Nexuiz.

UNIX

Hedgewars — 2-ая моя возлюбленная игра. Она очень похожа на Worms Armageddon, только заместо червяков ведут войну ежики.

#image.jpg

На официальном сервере игры всегда много игроков — создаете игру, ожидаете минутку и можно начинать! В особенности любопытно чатиться во время игры с какими-нибудь французами либо германцами. Разработчики часто добавляют в игру новые способности.

Как-то я пару месяцев не играл в Hedgewars. За этот период времени в игре появились телепорты, лазерные прицелы, коктейль Молотова и много другого орудия. Когда я зашел в игру, то просто не вызнал ее.

Поглядеть демо видеоклипы и скачать Hedgewars можно на hedgewars.org. Кстати, на форуме проекта тусуется много русских юзеров.

FreeCiv — это свободный аналог игры Sid Meier’s Civilization II. Заскучали по строительству дорог, развитию науки и захвату городов? Означает, FreeCiv предназначена для вас!

Офсайт игры хостится на wikia.com.

#image.jpg

Если вы думаете, что разработчики свободных игр не способны придумать что-то без помощи других, поиграйте в Battle for Wesnoth (wesnoth.org). Эта пошаговая стратегия не похожа ни на Героев, ни на Disciples, ни на что или другое.

Карта, к примеру, разбивается на шестиугольники, а сила и скорость юнитов зависят от времени суток и того, на каком поле они находятся. Вселенная игры заселена колдунами, орками, ельфами ну и конечно людьми. Можно играть по сети, а можно проходить (достаточно длинноватые!) компании.

#image.jpg

Существует еще величавое огромное количество open source игр. Когда-то в этом блоге я писал про шахматную игру Brutal Chess. Еще мне очень нравятся игры LordsAWar (аналог Warlords II) и XGalaga.

Уверен, что каждый может отыскать много Linux-игр по вкусу.

4. Интернет-чаты

Свободных программ для общения в IRC, ICQ либо Jabber достаточно много. Как мне понятно, одним из самых фаворитных клиентов в этой области является Pidgin. Вы спросите меня, как же Skype?

Skype отлично работает под Linux. Также у него есть свободный аналог, именуется он Ekiga.

#image.jpg

Слева на снимке экрана изображен Pidgin, справа — Ekiga. Pidgin я временами использую и смею заверить, что он ничем не ужаснее QIP. Голосом я по сети не общаюсь и никогда не общался (почему — в свое время я писал в этом посте), так что о Ekiga ничего сказать не могу.

Дополнение: Очередной неплохой ICQ/Jabber/Mail.ru клиент — QutIM. Он, в отличии от Pidgin, больше похож на старенькый хороший QIP. Если вы пользуетесь только Jabber, направьте внимание на Psi.

UNIX

Дополнение: Также я желал включить в этот раздел IRC-клиент XChat, но не сделал это, так как его версия для Windows платная. Оказалось, что есть бесплатные сборки — SilvereX и ZeroStress.

UNIX

5. Графика и видео

Кроме упомянутых Gimp и Inkscape я желал бы направить внимание еще на две программки — MPlayer и XNView.

MPlayer — это видео-проигрыватель, ставший эталоном де-факто в мире UNIX.

Bloat: How and Why UNIX Grew Up (and Out) - Rusty Russell,Matt Evans

#image.jpg

Под Windows я бы рекомендовал использовать его сборку под заглавием SMPLayer. Это фактически тот же Light Alloy, исключительно в нем не надо отгадывать загадки про лук и морковку (кто пробовал — тот знает).

Как работают DNS-серверы в UNIX-системах?

XNView — свободная программка для просмотра изображений.

#image.jpg

XNView предоставляет много нужных функций — от очевидных обрезать/повернуть/масштабировать до удаления эффекта бардовых глаз и сотворения снимков экрана. Кстати, все снимки экрана к этой заметке были изготовлены при помощи XNView (под Windows 7, который шел в комплекте с моим новым ноутбуком).

6. Разработка

Geany — это среда разработки с открытым начальным кодом.

#image.jpg

Geany поддерживает плагины, подсветку синтаксиса 40+ языков программирования, фолдинг, автодополнение, автоматическое закрытие HTML/XML-тегов и другие полезные функции. Очень легкая и приятная в использовании программка.

Дополнение: Программерам на C/C++/D также советую направить внимание на кроссплатформенную IDE Code::Blocks. Основная фишка — уплотненная интеграция с библиотекой wxWidgets, что позволяет стремительно создавать кроссплатформенные GUI приложения. Ну и для всего остального Code::Blocks тоже годится.

UNIX

Dia — свободный редактор диаграмм и блок-схем, кандидатура Microsoft Visio.

#image.jpg

Я поведал об этой программке у нас в кабинете и многие с радостью на нее подсели. Похоже, что она хорошо совладевает со собственной задачей. Направьте внимание на количество диаграмм, поддерживаемых Dia (на снимке экрана вы видите меньше их половины).

Существует программка, позволяющая преобразовывать диаграммы, сделанные в Dia, в программный код.

Qemu — бесплатная виртуальная машина, аналог VMWare Player (Workstation).

#image.jpg

На снимке экрана вы видите Qemu Manager — сборку Qemu для Windows. Я отнес этот эмулятор к разделу «Разработка», так как обычно эмуляторами пользуются как раз программеры. К примеру, когда необходимо протестировать кроссплатформенную программку либо при написании драйверов.

Дополнение: Суровый недочет Qemu — неспешная скорость работы. VirtualBox работает намного резвее и также портирован под Юниксы. К примеру, во FreeBSD ему соответствует пакет vboxgtk.

Kompozer — свободный WYSIWYG HTML-редактор, аналог Dreamweaver.

#image.jpg

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

Скачать можно на kompozer.net.

Дополнение: См также отладчик kgdb.

7. Заключение

Я надеюсь, что данная заметка дозволит для вас составить представление о том, как богат выбор программного обеспечения в мире UNIX. Я желал поведать еще об одной программке, но не знал к какому разделу ее отнести.

Она именуется Double Commander и представляет собой двухоконный файловый менеджер, как Total Commander. Оставляю для вас его для самостоятельного исследования.

UNIX

Дополнение: Запамятовал про RealVNC (бесплатный аналог RAdmin) и PeaZip (аналог WinRAR). Как мне понятно, у RealVNC есть препядствия с шифрованием трафика, так что примите надлежащие меры безопасности (VPN, SSH-туннелинг, …).

Дополнение: WebMoney Keeper Classic под UNIX нет, но ничто не мешает перейти на Keeper Light либо Keeper Mini. Для работы с ними не надо ничего, не считая веб-браузера. Не знаю, можно ли перейти с Classic на Light средствами самой системы, но, как минимум, ничто не мешает зарегистрироваться в Light и перевести на него все средства.

Дополнение: Также удалось отыскать кроссплатформенный аудио-плеер со странноватым заглавием Aqualung. Поддерживает все пользующиеся популярностью аудио-форматы, интернет-радио, RSS и Atom подкасты, скины, также многие другие фишки. Работает под Windows, Linux, MacOS, *BSD.

Судя по логам subversion, проект живой.

Еще одна подмена Winamp — аудиоплеер DeaDBeeF. Есть версии для Linux, *BSD и Android. К огорчению, под Windows не портирован. Повеселили способности сворачивать программку в трей, редактировать мета-информацию аудио-файлов, также работать с несколькими плейлистами.

Переключение меж последними происходит при помощи вкладок. По моим ощущениям, DeadDBeeF во много раз удобнее Aqualung.

За наводку спасибо товарищу SHok.

Дополнение: Отыскал еще парочку нужных программ: RawStudio — для работы с фото в RAW, Umbrello — UML редактор с возможностью генерации кода.

Дополнение: Дмитрий Дегтярев порекомендовал мне звуковой редактор Audacity. Редактор прост в использовании и при всем этом имеет большая часть нужных функций — нарезание дорожек, накладывание звука, управление громкостью и тп, также разные фильтры.

Похожие статьи

  • Философия UNIX либо fork() vs CreateThread()

    Вот уже вторую неделю в Москве царствует нестерпимая жара. Вентиляторы и кондюки в магазинах не отыскать, прохладительные напитки не помогают. Уровень желания работать (УЖР) по десятибалльной шкале...

  • Права доступа Unix

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

  • Права доступа в Unix

    Нашел старую статью по правам доступа, я понимаю на данный момент есть ACL и прочее, поэтому некоторые постулаты нужно принимать с фильтрацией, но все же новым думаю полезно. Файлы в Linux име...

  • Программные каналы и потоки Linux (UNIX), перенаправление потоков

    Неплохого времени, читатели моего блога!В данной статье желаю систематизировать свои зания по основным механизмам работы программных потоков и каналов в интерпретаторе и в общем в ОС Linux, а так ж...

  • 15000 день unix эпохи

    На данный момент, 20 6 января, в полночь по GMT, наступил Пятнадцать тыщ день от начала летосчисления Unix машин. Юниксоиды всех стран встречаются, празднуют, проводят массовые гулянья и гадают. Встречи локальн...

0

unix прокомментировал 15 августа 2008 в 17:31

UNIX

В одном из собственных прошлых постов (см Чем неплох и чем плох Linux) я троллил о преимуществах рассуждал об различиях операционных систем семейства UNIX (Linux и *BSD) от семейства Windows и о том, кому и для чего стоит попробовать перейти на Ubuntu. Пожалуй, самый комфортабельный метод выполнить переход — в течение некого времени использовать под Windows только тот софт, который есть под Linux.

Тогда после смены операционной системы вам фактически ничего не поменяется. Эта заметка представляет собой обзор Linux-аналогов фаворитных Windows-программ. Внимание — под катом Четыреста Кб снимков экрана.

Все упомянутые в заметке программки полностью бесплатны и использовать их можно как под Windows, так и под Linux. Даже если вы не планируете отрешаться от Windows, почему бы для вас не использовать бесплатный и законный Thunderbird заместо крякнутого The Bat! либо OpenOffice заместо Microsoft Office? Поверьте, документы и презентации в OpenOffice получаются ничем не ужаснее, чем в Microsoft Office.

1. Джентльменский набор

Я так подозреваю, что посреди читателей все ну либо практически все слышали о Firefox, Thunderbird, OpenOffice и прочем бесплатном софте. Я приведу только лаконичный перечень этих и неких других программ, без снимков экрана и подробного описания, так как вероятнее всего вы с ними уже знакомы.

  • Firefox, Opera, Chrome — все эти браузеры отлично известны хоть какому более-менее опытнейшему интернет-пользователю. И они все портированы под Linux.
  • ThunderBird — кроссплатформенный почтовый клиент от компании Мозилла. По своим способностям ничем не уступает The Bat. Меня лично поражает, что кто-то до сего времени пользуется последним.
  • OpenOffice — бесплатный офисный пакет, разрабатываемый под началом Oracle Corporation (ранее — Sun Microsystems). Имеет форк LibreOffice, работы над которым ведет независящее собщество разработчиков. Формат OpenDocument был принят в качестве муниципального эталона Рф и ряда других государств.
  • Gimp, Inkscape — бесплатные редакторы растровой и векторной графики соответственно (аналоги Photoshop и Corel Draw / Adobe Illustrator). Все изображения в этом блоге я редактирую при помощи Gimp.
  • Evince — свободная программка для чтения PDF/DjVu файлов. Невзирая на свою малую известность, со собственной задачей Evince совладевает ничем не ужаснее Adobe Reader.

Дополнение: Также из почтовых клиентов заслуживает внимания Claws Mail, в особенности если вы находите Thunderbird очень томным и неспешным.

2. P2P-клиенты

Более пользующимися популярностью p2p-сетями сейчас являются BitTorrent и eDonkey2000. Еще я слышал про DC, но никогда им не воспользовался и не понимаю, как он вообщем может работать.

Остальные пиринговые сети, к примеру, Freenet, в текущее время не достаточно всераспространены и являются быстрее экспериментальными. Так что в рамках этой статьи я расскажу только о 2-ух p2p-клиентах.

UNIX

1-ый именуется Deluge и является всеполноценным аналогом BitTorrent клиента uTorrent.

#image.jpg

2-ой — aMule, представляет собой брата-близнеца ed2k-клиента eMule.

#image.jpg

Даже не знаю, что еще о их можно поведать. Офсайты программ — deluge-torrent.org и amule.org соответственно.

UNIX

Дополнение: Как выяснилось, время от времени Deluge может жрать очень много памяти (см снимок экрана в конце). Отлично зарекомендовал себя BitTorrent клиент sharkTorrent (снимок экрана, офсайт). Невзирая на простой вид, он имеет весь функционал, нужный торрент-клиенту.

В отличии от Deluge, написан на C++, со всеми вытекающими. Обратите также внимание на qBittorrent и Transmission.

3. Игры

Принято считать, что под Linux нет компьютерных игр. По сути это не так — игр под Linux много и большая часть из их бесплатные. Прямо рай для игромана!

Я расскажу только о нескольких игрушках, которые мне очень нравятся.

Дополнение: С возникновением Steam игр для Linux стала значительно больше.

Nexuiz — это шутер от первого лица. У меня он больше всего ассоциаций вызывает с Unreal Tournament. Невзирая на то, что linux-игры, обычно, не требовательны к ресурсам компьютера, для Nexuiz лучше запастись неплохой видеокартой.

#image.jpg

Мне так нравится эта игра, что я решил в порядке исключения выложить два ее снимка экрана.

#image.jpg

Поглядеть больше снимков экрана и скачать игру можно на офсайте Nexuiz.

UNIX

Hedgewars — 2-ая моя возлюбленная игра. Она очень похожа на Worms Armageddon, только заместо червяков ведут войну ежики.

#image.jpg

На официальном сервере игры всегда много игроков — создаете игру, ожидаете минутку и можно начинать! В особенности любопытно чатиться во время игры с какими-нибудь французами либо германцами. Разработчики часто добавляют в игру новые способности.

Как-то я пару месяцев не играл в Hedgewars. За этот период времени в игре появились телепорты, лазерные прицелы, коктейль Молотова и много другого орудия. Когда я зашел в игру, то просто не вызнал ее.

Поглядеть демо видеоклипы и скачать Hedgewars можно на hedgewars.org. Кстати, на форуме проекта тусуется много русских юзеров.

FreeCiv — это свободный аналог игры Sid Meier’s Civilization II. Заскучали по строительству дорог, развитию науки и захвату городов? Означает, FreeCiv предназначена для вас!

Офсайт игры хостится на wikia.com.

#image.jpg

Если вы думаете, что разработчики свободных игр не способны придумать что-то без помощи других, поиграйте в Battle for Wesnoth (wesnoth.org). Эта пошаговая стратегия не похожа ни на Героев, ни на Disciples, ни на что или другое.

Карта, к примеру, разбивается на шестиугольники, а сила и скорость юнитов зависят от времени суток и того, на каком поле они находятся. Вселенная игры заселена колдунами, орками, ельфами ну и конечно людьми. Можно играть по сети, а можно проходить (достаточно длинноватые!) компании.

#image.jpg

Существует еще величавое огромное количество open source игр. Когда-то в этом блоге я писал про шахматную игру Brutal Chess. Еще мне очень нравятся игры LordsAWar (аналог Warlords II) и XGalaga.

Уверен, что каждый может отыскать много Linux-игр по вкусу.

4. Интернет-чаты

Свободных программ для общения в IRC, ICQ либо Jabber достаточно много. Как мне понятно, одним из самых фаворитных клиентов в этой области является Pidgin. Вы спросите меня, как же Skype?

Skype отлично работает под Linux. Также у него есть свободный аналог, именуется он Ekiga.

#image.jpg

Слева на снимке экрана изображен Pidgin, справа — Ekiga. Pidgin я временами использую и смею заверить, что он ничем не ужаснее QIP. Голосом я по сети не общаюсь и никогда не общался (почему — в свое время я писал в этом посте), так что о Ekiga ничего сказать не могу.

Дополнение: Очередной неплохой ICQ/Jabber/Mail.ru клиент — QutIM. Он, в отличии от Pidgin, больше похож на старенькый хороший QIP. Если вы пользуетесь только Jabber, направьте внимание на Psi.

UNIX

Дополнение: Также я желал включить в этот раздел IRC-клиент XChat, но не сделал это, так как его версия для Windows платная. Оказалось, что есть бесплатные сборки — SilvereX и ZeroStress.

UNIX

5. Графика и видео

Кроме упомянутых Gimp и Inkscape я желал бы направить внимание еще на две программки — MPlayer и XNView.

MPlayer — это видео-проигрыватель, ставший эталоном де-факто в мире UNIX.

Bloat: How and Why UNIX Grew Up (and Out) - Rusty Russell,Matt Evans

#image.jpg

Под Windows я бы рекомендовал использовать его сборку под заглавием SMPLayer. Это фактически тот же Light Alloy, исключительно в нем не надо отгадывать загадки про лук и морковку (кто пробовал — тот знает).

Как работают DNS-серверы в UNIX-системах?

XNView — свободная программка для просмотра изображений.

#image.jpg

XNView предоставляет много нужных функций — от очевидных обрезать/повернуть/масштабировать до удаления эффекта бардовых глаз и сотворения снимков экрана. Кстати, все снимки экрана к этой заметке были изготовлены при помощи XNView (под Windows 7, который шел в комплекте с моим новым ноутбуком).

6. Разработка

Geany — это среда разработки с открытым начальным кодом.

#image.jpg

Geany поддерживает плагины, подсветку синтаксиса 40+ языков программирования, фолдинг, автодополнение, автоматическое закрытие HTML/XML-тегов и другие полезные функции. Очень легкая и приятная в использовании программка.

Дополнение: Программерам на C/C++/D также советую направить внимание на кроссплатформенную IDE Code::Blocks. Основная фишка — уплотненная интеграция с библиотекой wxWidgets, что позволяет стремительно создавать кроссплатформенные GUI приложения. Ну и для всего остального Code::Blocks тоже годится.

UNIX

Dia — свободный редактор диаграмм и блок-схем, кандидатура Microsoft Visio.

#image.jpg

Я поведал об этой программке у нас в кабинете и многие с радостью на нее подсели. Похоже, что она хорошо совладевает со собственной задачей. Направьте внимание на количество диаграмм, поддерживаемых Dia (на снимке экрана вы видите меньше их половины).

Существует программка, позволяющая преобразовывать диаграммы, сделанные в Dia, в программный код.

Qemu — бесплатная виртуальная машина, аналог VMWare Player (Workstation).

#image.jpg

На снимке экрана вы видите Qemu Manager — сборку Qemu для Windows. Я отнес этот эмулятор к разделу «Разработка», так как обычно эмуляторами пользуются как раз программеры. К примеру, когда необходимо протестировать кроссплатформенную программку либо при написании драйверов.

Дополнение: Суровый недочет Qemu — неспешная скорость работы. VirtualBox работает намного резвее и также портирован под Юниксы. К примеру, во FreeBSD ему соответствует пакет vboxgtk.

Kompozer — свободный WYSIWYG HTML-редактор, аналог Dreamweaver.

#image.jpg

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

Скачать можно на kompozer.net.

Дополнение: См также отладчик kgdb.

7. Заключение

Я надеюсь, что данная заметка дозволит для вас составить представление о том, как богат выбор программного обеспечения в мире UNIX. Я желал поведать еще об одной программке, но не знал к какому разделу ее отнести.

Она именуется Double Commander и представляет собой двухоконный файловый менеджер, как Total Commander. Оставляю для вас его для самостоятельного исследования.

UNIX

Дополнение: Запамятовал про RealVNC (бесплатный аналог RAdmin) и PeaZip (аналог WinRAR). Как мне понятно, у RealVNC есть препядствия с шифрованием трафика, так что примите надлежащие меры безопасности (VPN, SSH-туннелинг, …).

Дополнение: WebMoney Keeper Classic под UNIX нет, но ничто не мешает перейти на Keeper Light либо Keeper Mini. Для работы с ними не надо ничего, не считая веб-браузера. Не знаю, можно ли перейти с Classic на Light средствами самой системы, но, как минимум, ничто не мешает зарегистрироваться в Light и перевести на него все средства.

Дополнение: Также удалось отыскать кроссплатформенный аудио-плеер со странноватым заглавием Aqualung. Поддерживает все пользующиеся популярностью аудио-форматы, интернет-радио, RSS и Atom подкасты, скины, также многие другие фишки. Работает под Windows, Linux, MacOS, *BSD.

Судя по логам subversion, проект живой.

Еще одна подмена Winamp — аудиоплеер DeaDBeeF. Есть версии для Linux, *BSD и Android. К огорчению, под Windows не портирован. Повеселили способности сворачивать программку в трей, редактировать мета-информацию аудио-файлов, также работать с несколькими плейлистами.

Переключение меж последними происходит при помощи вкладок. По моим ощущениям, DeadDBeeF во много раз удобнее Aqualung.

За наводку спасибо товарищу SHok.

Дополнение: Отыскал еще парочку нужных программ: RawStudio — для работы с фото в RAW, Umbrello — UML редактор с возможностью генерации кода.

Дополнение: Дмитрий Дегтярев порекомендовал мне звуковой редактор Audacity. Редактор прост в использовании и при всем этом имеет большая часть нужных функций — нарезание дорожек, накладывание звука, управление громкостью и тп, также разные фильтры.

Похожие статьи

  • Философия UNIX либо fork() vs CreateThread()

    Вот уже вторую неделю в Москве царствует нестерпимая жара. Вентиляторы и кондюки в магазинах не отыскать, прохладительные напитки не помогают. Уровень желания работать (УЖР) по десятибалльной шкале...

  • Права доступа Unix

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

  • Права доступа в Unix

    Нашел старую статью по правам доступа, я понимаю на данный момент есть ACL и прочее, поэтому некоторые постулаты нужно принимать с фильтрацией, но все же новым думаю полезно. Файлы в Linux име...

  • Программные каналы и потоки Linux (UNIX), перенаправление потоков

    Неплохого времени, читатели моего блога!В данной статье желаю систематизировать свои зания по основным механизмам работы программных потоков и каналов в интерпретаторе и в общем в ОС Linux, а так ж...

  • 15000 день unix эпохи

    На данный момент, 20 6 января, в полночь по GMT, наступил Пятнадцать тыщ день от начала летосчисления Unix машин. Юниксоиды всех стран встречаются, празднуют, проводят массовые гулянья и гадают. Встречи локальн...

0

unix прокомментировал 15 августа 2008 в 17:31

UNIX

В одном из собственных прошлых постов (см Чем неплох и чем плох Linux) я троллил о преимуществах рассуждал об различиях операционных систем семейства UNIX (Linux и *BSD) от семейства Windows и о том, кому и для чего стоит попробовать перейти на Ubuntu. Пожалуй, самый комфортабельный метод выполнить переход — в течение некого времени использовать под Windows только тот софт, который есть под Linux.

Тогда после смены операционной системы вам фактически ничего не поменяется. Эта заметка представляет собой обзор Linux-аналогов фаворитных Windows-программ. Внимание — под катом Четыреста Кб снимков экрана.

Все упомянутые в заметке программки полностью бесплатны и использовать их можно как под Windows, так и под Linux. Даже если вы не планируете отрешаться от Windows, почему бы для вас не использовать бесплатный и законный Thunderbird заместо крякнутого The Bat! либо OpenOffice заместо Microsoft Office? Поверьте, документы и презентации в OpenOffice получаются ничем не ужаснее, чем в Microsoft Office.

1. Джентльменский набор

Я так подозреваю, что посреди читателей все ну либо практически все слышали о Firefox, Thunderbird, OpenOffice и прочем бесплатном софте. Я приведу только лаконичный перечень этих и неких других программ, без снимков экрана и подробного описания, так как вероятнее всего вы с ними уже знакомы.

  • Firefox, Opera, Chrome — все эти браузеры отлично известны хоть какому более-менее опытнейшему интернет-пользователю. И они все портированы под Linux.
  • ThunderBird — кроссплатформенный почтовый клиент от компании Мозилла. По своим способностям ничем не уступает The Bat. Меня лично поражает, что кто-то до сего времени пользуется последним.
  • OpenOffice — бесплатный офисный пакет, разрабатываемый под началом Oracle Corporation (ранее — Sun Microsystems). Имеет форк LibreOffice, работы над которым ведет независящее собщество разработчиков. Формат OpenDocument был принят в качестве муниципального эталона Рф и ряда других государств.
  • Gimp, Inkscape — бесплатные редакторы растровой и векторной графики соответственно (аналоги Photoshop и Corel Draw / Adobe Illustrator). Все изображения в этом блоге я редактирую при помощи Gimp.
  • Evince — свободная программка для чтения PDF/DjVu файлов. Невзирая на свою малую известность, со собственной задачей Evince совладевает ничем не ужаснее Adobe Reader.

Дополнение: Также из почтовых клиентов заслуживает внимания Claws Mail, в особенности если вы находите Thunderbird очень томным и неспешным.

2. P2P-клиенты

Более пользующимися популярностью p2p-сетями сейчас являются BitTorrent и eDonkey2000. Еще я слышал про DC, но никогда им не воспользовался и не понимаю, как он вообщем может работать.

Остальные пиринговые сети, к примеру, Freenet, в текущее время не достаточно всераспространены и являются быстрее экспериментальными. Так что в рамках этой статьи я расскажу только о 2-ух p2p-клиентах.

UNIX

1-ый именуется Deluge и является всеполноценным аналогом BitTorrent клиента uTorrent.

#image.jpg

2-ой — aMule, представляет собой брата-близнеца ed2k-клиента eMule.

#image.jpg

Даже не знаю, что еще о их можно поведать. Офсайты программ — deluge-torrent.org и amule.org соответственно.

UNIX

Дополнение: Как выяснилось, время от времени Deluge может жрать очень много памяти (см снимок экрана в конце). Отлично зарекомендовал себя BitTorrent клиент sharkTorrent (снимок экрана, офсайт). Невзирая на простой вид, он имеет весь функционал, нужный торрент-клиенту.

В отличии от Deluge, написан на C++, со всеми вытекающими. Обратите также внимание на qBittorrent и Transmission.

3. Игры

Принято считать, что под Linux нет компьютерных игр. По сути это не так — игр под Linux много и большая часть из их бесплатные. Прямо рай для игромана!

Я расскажу только о нескольких игрушках, которые мне очень нравятся.

Дополнение: С возникновением Steam игр для Linux стала значительно больше.

Nexuiz — это шутер от первого лица. У меня он больше всего ассоциаций вызывает с Unreal Tournament. Невзирая на то, что linux-игры, обычно, не требовательны к ресурсам компьютера, для Nexuiz лучше запастись неплохой видеокартой.

#image.jpg

Мне так нравится эта игра, что я решил в порядке исключения выложить два ее снимка экрана.

#image.jpg

Поглядеть больше снимков экрана и скачать игру можно на офсайте Nexuiz.

UNIX

Hedgewars — 2-ая моя возлюбленная игра. Она очень похожа на Worms Armageddon, только заместо червяков ведут войну ежики.

#image.jpg

На официальном сервере игры всегда много игроков — создаете игру, ожидаете минутку и можно начинать! В особенности любопытно чатиться во время игры с какими-нибудь французами либо германцами. Разработчики часто добавляют в игру новые способности.

Как-то я пару месяцев не играл в Hedgewars. За этот период времени в игре появились телепорты, лазерные прицелы, коктейль Молотова и много другого орудия. Когда я зашел в игру, то просто не вызнал ее.

Поглядеть демо видеоклипы и скачать Hedgewars можно на hedgewars.org. Кстати, на форуме проекта тусуется много русских юзеров.

FreeCiv — это свободный аналог игры Sid Meier’s Civilization II. Заскучали по строительству дорог, развитию науки и захвату городов? Означает, FreeCiv предназначена для вас!

Офсайт игры хостится на wikia.com.

#image.jpg

Если вы думаете, что разработчики свободных игр не способны придумать что-то без помощи других, поиграйте в Battle for Wesnoth (wesnoth.org). Эта пошаговая стратегия не похожа ни на Героев, ни на Disciples, ни на что или другое.

Карта, к примеру, разбивается на шестиугольники, а сила и скорость юнитов зависят от времени суток и того, на каком поле они находятся. Вселенная игры заселена колдунами, орками, ельфами ну и конечно людьми. Можно играть по сети, а можно проходить (достаточно длинноватые!) компании.

#image.jpg

Существует еще величавое огромное количество open source игр. Когда-то в этом блоге я писал про шахматную игру Brutal Chess. Еще мне очень нравятся игры LordsAWar (аналог Warlords II) и XGalaga.

Уверен, что каждый может отыскать много Linux-игр по вкусу.

4. Интернет-чаты

Свободных программ для общения в IRC, ICQ либо Jabber достаточно много. Как мне понятно, одним из самых фаворитных клиентов в этой области является Pidgin. Вы спросите меня, как же Skype?

Skype отлично работает под Linux. Также у него есть свободный аналог, именуется он Ekiga.

#image.jpg

Слева на снимке экрана изображен Pidgin, справа — Ekiga. Pidgin я временами использую и смею заверить, что он ничем не ужаснее QIP. Голосом я по сети не общаюсь и никогда не общался (почему — в свое время я писал в этом посте), так что о Ekiga ничего сказать не могу.

Дополнение: Очередной неплохой ICQ/Jabber/Mail.ru клиент — QutIM. Он, в отличии от Pidgin, больше похож на старенькый хороший QIP. Если вы пользуетесь только Jabber, направьте внимание на Psi.

UNIX

Дополнение: Также я желал включить в этот раздел IRC-клиент XChat, но не сделал это, так как его версия для Windows платная. Оказалось, что есть бесплатные сборки — SilvereX и ZeroStress.

UNIX

5. Графика и видео

Кроме упомянутых Gimp и Inkscape я желал бы направить внимание еще на две программки — MPlayer и XNView.

MPlayer — это видео-проигрыватель, ставший эталоном де-факто в мире UNIX.

Bloat: How and Why UNIX Grew Up (and Out) - Rusty Russell,Matt Evans

#image.jpg

Под Windows я бы рекомендовал использовать его сборку под заглавием SMPLayer. Это фактически тот же Light Alloy, исключительно в нем не надо отгадывать загадки про лук и морковку (кто пробовал — тот знает).

Как работают DNS-серверы в UNIX-системах?

XNView — свободная программка для просмотра изображений.

#image.jpg

XNView предоставляет много нужных функций — от очевидных обрезать/повернуть/масштабировать до удаления эффекта бардовых глаз и сотворения снимков экрана. Кстати, все снимки экрана к этой заметке были изготовлены при помощи XNView (под Windows 7, который шел в комплекте с моим новым ноутбуком).

6. Разработка

Geany — это среда разработки с открытым начальным кодом.

#image.jpg

Geany поддерживает плагины, подсветку синтаксиса 40+ языков программирования, фолдинг, автодополнение, автоматическое закрытие HTML/XML-тегов и другие полезные функции. Очень легкая и приятная в использовании программка.

Дополнение: Программерам на C/C++/D также советую направить внимание на кроссплатформенную IDE Code::Blocks. Основная фишка — уплотненная интеграция с библиотекой wxWidgets, что позволяет стремительно создавать кроссплатформенные GUI приложения. Ну и для всего остального Code::Blocks тоже годится.

UNIX

Dia — свободный редактор диаграмм и блок-схем, кандидатура Microsoft Visio.

#image.jpg

Я поведал об этой программке у нас в кабинете и многие с радостью на нее подсели. Похоже, что она хорошо совладевает со собственной задачей. Направьте внимание на количество диаграмм, поддерживаемых Dia (на снимке экрана вы видите меньше их половины).

Существует программка, позволяющая преобразовывать диаграммы, сделанные в Dia, в программный код.

Qemu — бесплатная виртуальная машина, аналог VMWare Player (Workstation).

#image.jpg

На снимке экрана вы видите Qemu Manager — сборку Qemu для Windows. Я отнес этот эмулятор к разделу «Разработка», так как обычно эмуляторами пользуются как раз программеры. К примеру, когда необходимо протестировать кроссплатформенную программку либо при написании драйверов.

Дополнение: Суровый недочет Qemu — неспешная скорость работы. VirtualBox работает намного резвее и также портирован под Юниксы. К примеру, во FreeBSD ему соответствует пакет vboxgtk.

Kompozer — свободный WYSIWYG HTML-редактор, аналог Dreamweaver.

#image.jpg

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

Скачать можно на kompozer.net.

Дополнение: См также отладчик kgdb.

7. Заключение

Я надеюсь, что данная заметка дозволит для вас составить представление о том, как богат выбор программного обеспечения в мире UNIX. Я желал поведать еще об одной программке, но не знал к какому разделу ее отнести.

Она именуется Double Commander и представляет собой двухоконный файловый менеджер, как Total Commander. Оставляю для вас его для самостоятельного исследования.

UNIX

Дополнение: Запамятовал про RealVNC (бесплатный аналог RAdmin) и PeaZip (аналог WinRAR). Как мне понятно, у RealVNC есть препядствия с шифрованием трафика, так что примите надлежащие меры безопасности (VPN, SSH-туннелинг, …).

Дополнение: WebMoney Keeper Classic под UNIX нет, но ничто не мешает перейти на Keeper Light либо Keeper Mini. Для работы с ними не надо ничего, не считая веб-браузера. Не знаю, можно ли перейти с Classic на Light средствами самой системы, но, как минимум, ничто не мешает зарегистрироваться в Light и перевести на него все средства.

Дополнение: Также удалось отыскать кроссплатформенный аудио-плеер со странноватым заглавием Aqualung. Поддерживает все пользующиеся популярностью аудио-форматы, интернет-радио, RSS и Atom подкасты, скины, также многие другие фишки. Работает под Windows, Linux, MacOS, *BSD.

Судя по логам subversion, проект живой.

Еще одна подмена Winamp — аудиоплеер DeaDBeeF. Есть версии для Linux, *BSD и Android. К огорчению, под Windows не портирован. Повеселили способности сворачивать программку в трей, редактировать мета-информацию аудио-файлов, также работать с несколькими плейлистами.

Переключение меж последними происходит при помощи вкладок. По моим ощущениям, DeadDBeeF во много раз удобнее Aqualung.

За наводку спасибо товарищу SHok.

Дополнение: Отыскал еще парочку нужных программ: RawStudio — для работы с фото в RAW, Umbrello — UML редактор с возможностью генерации кода.

Дополнение: Дмитрий Дегтярев порекомендовал мне звуковой редактор Audacity. Редактор прост в использовании и при всем этом имеет большая часть нужных функций — нарезание дорожек, накладывание звука, управление громкостью и тп, также разные фильтры.

Похожие статьи

  • Философия UNIX либо fork() vs CreateThread()

    Вот уже вторую неделю в Москве царствует нестерпимая жара. Вентиляторы и кондюки в магазинах не отыскать, прохладительные напитки не помогают. Уровень желания работать (УЖР) по десятибалльной шкале...

  • Права доступа Unix

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

  • Права доступа в Unix

    Нашел старую статью по правам доступа, я понимаю на данный момент есть ACL и прочее, поэтому некоторые постулаты нужно принимать с фильтрацией, но все же новым думаю полезно. Файлы в Linux име...

  • Программные каналы и потоки Linux (UNIX), перенаправление потоков

    Неплохого времени, читатели моего блога!В данной статье желаю систематизировать свои зания по основным механизмам работы программных потоков и каналов в интерпретаторе и в общем в ОС Linux, а так ж...

  • 15000 день unix эпохи

    На данный момент, 20 6 января, в полночь по GMT, наступил Пятнадцать тыщ день от начала летосчисления Unix машин. Юниксоиды всех стран встречаются, празднуют, проводят массовые гулянья и гадают. Встречи локальн...

0

Windows 7

Среда Windows 7 на первых порах кажется весьма непривычной для многих.

Windows 8

Если резюмировать все выступления Microsoft на конференции Build 2013.

Windows XP

Если Windows не может корректно завершить работу, в большинстве случаев это

Windows Vista

Если к вашему компьютеру подключено сразу несколько мониторов, и вы регулярно...