Идентификатор процесса
Как уже отмечено в начале этой главы, система присваивает каждому процессу неотрицательное число, которое называется идентификатором процесса. В любой момент времени идентификатор процесса является уникальным, хотя после завершения процесса он может использоваться снова для другого процесса. Некоторые идентификаторы процесса зарезервированы системой для особых процессов. Процесс с идентификатором 0, хотя он и называется планировщиком (scheduler), на самом деле является процессом подкачки памяти (swapper). Процесс с идентификатором 1 – это процесс инициализации, выполняющий программу /etc/init. Этот процесс, явно или неявно, является предком всех других процессов в системе UNIX.
Программа может получить свой идентификатор процесса при помощи следующего системного вызова:
pid := getpid;
Аналогично вызов getppid возвращает идентификатор родителя вызывающего процесса:
ppid := getppid;
Например:
Uses linux;
begin
Writeln ('Process Id = ',getpid,' Parent process Id = ',getppid);
end.
Следующая процедура gentemp использует вызов getpid для формирования уникального имени временного файла. Это имя имеет форму:
/tmp/tmp<pid>.<no>
Суффикс номера <nо> увеличивается на единицу при каждом вызове процедуры gentemp. Процедура также вызывает функцию access, чтобы убедиться, что файл еще не существует:
uses linux,strings;
const
num:integer=0;
namebuf:array [0..19] of char='';
prefix='/tmp/tmp';
function gentemp:pchar;
var
length:integer;
pid:longint;
begin
pid := getpid; (* получить идентификатор процесса *)
(* Стандартные процедуры работы со строками *)
strcopy (namebuf, prefix);
length := strlen (namebuf);
(* Добавить к имени файла идентификатор процесса *)
itoa (pid, @namebuf[length]);
strcat (namebuf, '.');
length := strlen (namebuf);
repeat
(* Добавить суффикс с номером *)
itoa(num, @namebuf[length]);
inc(num);
until(not access (namebuf, F_OK));
gentemp:=namebuf;
end;
Процедура itoa просто преобразует целое число в эквивалентную строку:
(* Функция itoa - преобразует целое число в строку *)
function itoa(i:integer;str:pchar):integer;
var
power, j : integer;
begin
j := i;
power := 1;
while j >= 10 do
begin
power := power * 10;
j := j div 10;
end;
while power > 0 do
begin
str^ := char(byte('0') + i div power);
inc(str);
i := i mod power;
power := power div 10;
end;
str^ := #0;
end;
Обратите внимание на способ преобразования цифры в ее символьный эквивалент в первом операторе во втором цикле for – он опирается на знание таблицы символов ASCII. Следует также отметить, что большую часть работы можно было бы выполнить гораздо проще при помощи процедуры sprintf. Описание процедуры sprintf смотрите в главе 11.
Упражнение 5.11. Переделайте процедуру gentemp так, чтобы она принимала в качестве аргумента префикс имени временного файла.