Скачиваний:
56
Добавлен:
08.01.2014
Размер:
2.6 Mб
Скачать

12.6. Дополнительные средства

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

12.6.1. Дополнение о сокетах

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

gethostent getservbyname

gethostbyaddr getservbyport

gethostbyname getservent

12.6.2. Потоки управления

Потоки управления, или нити (threads) являются облегченной версией процессов – поддерживающие их системы позволяют выполнять одновременно несколько таких потоков в рамках одного процесса, при этом все потоки могут работать с данными процесса. Их применение может быть очень ценным для повышения производительности и интерактивности определенных классов задач, но техника программирования многопотоковых программ является довольно сложной. Многие версии UNIX поддерживали различные подходы к организации потоков выполнения, но теперь выработана стандартная модель (POSIX threads), включенная в стандарт POSIX и пятую версию спецификации XSI. Интерфейс функций работы с потоками управления может быть описан в справочном руководстве системы под заголовком pthread_.

Для создания потока может использоваться вызов Clone:

Описание

uses linux;

TCloneFunc=function(args:pointer):longint;cdecl;

Clone(func:TCloneFunc;sp:pointer;flags:longint;args:pointer):longint;

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

При создании потомка запускается функция Func, которой передаются параметры Args. Возвращаемым значением Func является код завершения потомка.

Указатель sp хранит адрес памяти, зарезервированной под стек дочернего процесса.

Параметр Flags определяет поведение вызова Clone. Младший байт Flags содержит номер сигнала, который будет послан родителю при завершении потомка. Он может быть объединен с помощью побитового ИЛИ со следующими константами:

CLONE_VM Родитель и потомок разделяют память, включая отображенную вызовом mmap.

CLONE_FS Родитель и потомок разделяют параметры файловой системы; вызовы chroot, chdir и umask действуют на оба процесса.

CLONE_FILES Таблица дескрипторов файлов разделяется родителем и потомком.

CLONE_SIGHAND Таблица обработчиков сигналов разделяется родителем и потомком, однако маски сигналов различаются.

CLONE_PID Родитель и потомок имеют одинаковый pid.

Clone возвращает идентификатор потомка или -1 в случае ошибки, устанавливая значение linuxerror в Sys_EAGAIN (слишком много процессов) и Sys_ENOMEM (недостаточно памяти для создания дочернего процесса).

Пример использования Clone:

uses

Linux, Errors, crt;

const

Ready : Boolean = false;

aChar : Char = 'a';

function CloneProc( Arg: Pointer ): LongInt; Cdecl;

begin

WriteLn('Hello from the clone ',PChar(Arg));

repeat

Write(aChar);

Select(0,0,0,0,600);

until Ready;

WriteLn( 'Clone finished.');

CloneProc := 1;

end;

var

PID : LongInt;

procedure MainProc;

begin

WriteLn('cloned process PID: ', PID );

WriteLn('Press <ESC> to kill ... ' );

repeat

Write('.');

Select(0,0,0,0,300);

if KeyPressed then

case ReadKey of

#27: Ready := true;

'a': aChar := 'A';

'A': aChar := 'a';

'b': aChar := 'b';

'B': aChar := 'B';

end;

until Ready;

WriteLn('Ready.');

end;

const

StackSze = 16384;

theFlags = CLONE_VM+CLONE_FS+CLONE_FILES+CLONE_SIGHAND;

aMsg : PChar = 'Oops !';

var

theStack : Pointer;

ExitStat : LongInt;

begin

GetMem(theStack,StackSze);

PID := Clone(@CloneProc,

Pointer( LongInt(theStack)+StackSze),

theFlags,

aMsg);

if PID < 0 then

WriteLn('Error : ', LinuxError, ' when cloning.')

else

begin

MainProc;

case WaitPID(0,@ExitStat,Wait_Untraced or wait_clone) of

-1: WriteLn('error:',LinuxError,'; ',StrError(LinuxError));

0: WriteLn('error:',LinuxError,'; ',StrError(LinuxError));

else

WriteLn('Clone exited with: ',ExitStat shr 8);

end;

end;

FreeMem( theStack, StackSze );

end.

Соседние файлы в папке Полищук, Семериков. Системное программирование в UNIX средствами Free Pascal