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

Ускорение продвижения
Если вам трудно попасть на первые места в поиске самостоятельно, попробуйте технологию Буст, она ускоряет продвижение в десятки раз, а первые результаты появляются уже в течение первых 7 дней. Если ни один запрос у вас не продвинется в Топ10 за месяц, то в SeoHammer за бустер вернут деньги.



Иллюстрированный самоучитель по теории операционных систем

Примеры реализаций средств гармонического взаимодействия

Программные каналы Unix

Одним из наиболее типичных средств такого рода является труба (pipe) или программный канал – основное средство взаимодействия между процессами в ОС семейства Unix. В русскоязычной литературе трубы иногда ошибочно называют конвейерами. В действительности, конвейер – это группа процессов, последовательно соединенных друг с другом однонаправленными трубами.

Труба представляет собой поток байтов. Поток этот имеет начало (исток) и конец (приемник). В исток этого потока можно записывать данные, а из приемника – считывать. Нить, которая пытается считать данные из пустой трубы, будет задержана, пока там что-нибудь не появится. Наоборот, пишущая нить может записать в трубу некоторое количество данных, прежде чем труба заполнится, и дальнейшая запись будет заблокирована. На практике труба реализована в виде небольшого (несколько килобайтов) кольцевого буфера. Передатчик заполняет этот буфер, пока там есть место. Приемник считывает данные, пока буфер не опустеет.

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

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

Самым интересным свойством трубы является то, что чтение данных из и запись в нее осуществляется теми же самыми системными вызовами read и write, что и работа с обычным файлом, внешним устройством или сетевым соединением (сокетом). На этом основана техника переназначения ввода-вывода, широко используемая в командных интерпретаторах UNIX. Она состоит в том, что большинство системных утилит получают данные из потока стандартного ввода (stdin) и выдают их в поток стандартного вывода (stdout). При этом, указывая в качестве этих потоков терминальное устройство, файл или трубу, мы можем использовать в качестве ввода, соответственно: текст, набираемый с клавиатуры, содержимое файла или стандартный вывод другой программы. Аналогично мы можем выдавать данные сразу на экран, в файл или передавать их на вход другой программы.

Так, например, компилятор GNU С состоит из трех основных проходов: препроцессора, собственно компилятора, генерирующего текст на ассемблере, и ассемблера. При этом внутри компилятора, на самом деле, также выполняется несколько проходов по тексту (в описании перечислено восемнадцать), в основном для оптимизации, но нас это в данный момент не интересует, поскольку все они выполняются внутри одной задачи. При этом все три задачи объединяются трубами в единую линию обработки входного текста – конвейер (pipeline), так что промежуточные результаты компиляции не занимают места на диске.

В системе UNIX труба создается системным вызовом pipe(int flldes;2]). Этот вызов создает трубу и помещает дескрипторы файлов, соответствующие входному и выходному концам трубы, в массив fildes. Затем мы можем вы полнить fork, в различных процессах переназначить соответствующие конец трубы на место stdin и stdout и запустить требуемые программы (пример 7.7). При этом мы получим типичный конвейер – две задачи, стандартный ввод и вывод которых соединены трубой.

Пример 7.7. Код, создающий конвейер при помощи труб.

#include <unistd.h>
void pipeline(void) {
/* stage 1 */
int pipe1[2];
int child1;
int pipe2[2];
int child2;
int child3;
pipe(pipe1);
if ((child1=fork())==0) {
close(pipe1[0]); /* Закрыть лишний конец трубы */
closed); /* Переназначить стандартный вывод */
dup(pipe1[1]);
close(pipe1[1]);
/* Исполнить программу */
execlpC'du", "du", "-s", ".", NULL);
/* Мы можем попасть сюда только при ошибке exec */
perror("Cannot exec");
exit(0);
}
close(pipel [1]);
if (childl==-1) {
perror("Cannot fork");
}
/* stage 2 */
pipe(pipe2);
if ((child2=fork())==0) { ' .close (0); /J" Переназначить стандартный ввод */
dup(pipel[0]}; close (pipel [0]);
close (pipe2 [0]); /* Закрыть лишний конец трубы */ close (1); /* Переназначить стандартный вывод */
close (pipe2 [1]);
/* Исполнить программу */
execlp ("sort", "sort", "-nr", NULL);
/* Мы можем попасть сюда только при ошибке exec */
perror ("Cannot exec");
exit(O);
}
close (pipe1 [0]);
close (pipe2 [1]);
if (child2==-1) {
perror ("Cannot fork");
}
/* stage 3 */
if ((child3=fork())==0) {
close (0); /* Переназначить стандартный ввод */
dup(pipe2 [0]);
close (pipe2 [0]);
/* Исполнить программу */
execlp ("tail", "tail", "-1", NULL);
/* Мы можем попасть сюда только при ошибке exec */
perror ("Cannot exec");
exit (0);
}
close (pipe2 [0]);
if (child3==-1) {
perror ("Cannot fork");
}
while (wait (NULL)1=-1);
return;
}
Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.