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

13.9. Программные каналы

Упражнение 13.57. Напишите программу, определяющую, возвращает ли fstat количество байт в FIFO в качестве поля size структуры tstat.

uses linux;

var

s:tstat;

begin

if paramcount<>1 then

begin

writeln('Используйте: ',paramstr(0),' имя_файла');

exit;

end;

if not fstat(paramstr(1),s) then

begin

writeln('Ошибка вызова stat для файла ',paramstr(1));

exit;

end;

writeln('Размер файла ',paramstr(1),' равен ',s.size);

end.

Упражнение 13.58. Напишите программу для определения того, что возвращает функция select при проверке возможности записи в дескриптор канала, у которого закрыт второй конец.

uses linux;

var

fds:fdset;

fdin,fdout,ret:longint;

begin

if not assignpipe(fdin,fdout) then

begin

writeln('Ошибка создания программного канала');

exit;

end;

fd_zero(fds);

fd_set(fdin,fds);

fd_set(fdout,fds);

fdwrite(fdout,'Некая достаточно длинная строка',31);

fdclose(fdin);

writeln('Вызов select');

ret:=select(2,nil,@fds,nil,1000);

writeln('select вернул ',ret);

end.

Упражнение 13.59. Используя канал между родителем (клиентом) и потомком (сервером), создайте программу, в которой клиент считывает имя файла из стандартного ввода и записывает в канал. Если файл существует, сервер считывает его и записывает в канал, в противном случае возвращает клиенту сообщение об ошибке.

uses linux,sysutils;

const

BLOCKSIZE=1024;

var

pid,(*идентификатор процесса*)

filesize,(*размер файла*)

fd,(*дескриптор файла*)

kol,(*количество прочитанных байт*)

i:longint;

in1,out1,in2,out2:longint;(*дескрипторы программных каналов*)

filename:string[80];

st:tstat;(*для получения информации о размере файла*)

buf:array[0..BLOCKSIZE-1]of char;(*буфер чтения-записи*)

begin

(*попытка создания двух программных каналов*)

if not assignpipe(in1,out1) then

begin

writeln('Ошибка создания первого программного канала');

exit;

end;

if not assignpipe(in2,out2) then

begin

writeln('Ошибка создания второго программного канала');

fdclose(in1); (*закрываем ранее созданный канал 1*)

fdclose(out1);

exit;

end;

pid:=fork; (*клонирование процесса*)

if pid=-1 then (*ошибка клонирования*)

begin

writeln('Ошибка создания потомка');

exit;

end;

if pid=0 (*сервер - потомок*) then (*ветка потомка*)

begin

fdclose(out1);(*закрываем для надежности ненужные каналы:

первый - для записи, второй - для чтения*)

fdclose(in2);

fdread(in1,filename,80); (*читаем из первого канала имя файла*)

{}writeln('Сервер: получено имя файла - ',filename);

if access(filename,f_ok or r_ok) then (*если файл существует и доступен для чтения*)

begin

fstat(filename,st);(*получем информацию о файле*)

filesize:=st.size; (*узнаем размер файла*)

{}writeln('Сервер: определен размер файла - ',filesize);

fdwrite(out2,filesize,sizeof(filesize)); (*пишем во второй канал размер файла*)

{}writeln('Сервер: размер файла записан в канал');

fd:=fdopen(filename,Open_RDONLY);(*открываем файл для чтения*)

i:=1;

kol:=fdread(fd,buf,BLOCKSIZE); (*читаем блоками по BLOCKSIZE байт*)

while kol>0 do

begin

fdwrite(out2,buf,kol); (*пишем во второй канал столько, сколько прочли из файла*)

{}writeln('Сервер: записано в канал ',i*kol/BLOCKSIZE:1:1,' Kb');

kol:=fdread(fd,buf,BLOCKSIZE);

end;

fdclose(fd);(*закрываем файл*)

{}writeln('Сервер: файл записан в канал');

end

else (*если файл не существует или недоступен для чтения*)

begin

filesize:=-1; (*записываем в программный канал признак ошибки*)

fdwrite(out2,filesize,sizeof(filesize));

end;

{}writeln('Сервер: работа завершена');

halt(0); (*завершаем работу потомка*)

end

else (*клиент - родитель*) (*ветка родителя*)

begin

fdclose(in1); (*закрываем ненужные каналы: первый для чтения, второй - для записи*)

fdclose(out2);

write('Введите имя файла: '); (*запрос имени файла*)

readln(filename);

fdwrite(out1,filename,80); (*пишем имя в программный канал*)

{}writeln('Клиент: имя файла записано в канал');

fdread(in2,filesize,sizeof(filesize)); (*получем размер файла из канала*)

{}writeln('Клиент: из канала получен размер файла - ',filesize);

if in2=-1 then (*при ошибке*)

writeln('Файл ',filename,' не существует или недоступен для чтения')

else

begin

(*создаем файл*)

{}writeln('Клиент: файл создан, идет прием');

for i:=length(filename) downto 1 do

if filename[i]='/' then

begin

delete(filename,1,i);

break;

end;

fd:=fdopen(filename,Open_WRONLY or Open_CREAT or Open_TRUNC, octal(644));

if fd=-1 then

begin

writeln('Ошибка создания файла ',filename);

kill(pid,9);

halt(1);

end;

for i:=1 to filesize do(*пока есть что читать из канала*)

begin

fdread(in2,buf,1);

if i mod BLOCKSIZE=0 then

{}writeln('Клиент: записано в файл ',i div BLOCKSIZE,' Kb');

fdwrite(fd,buf,1);(*записываем в файл*)

end;

fdclose(fd);(*закрываем созданный файл*)

{}writeln('Клиент: файл закрыт');

end;

waitpid(pid,nil,0); (*ожидаем завершения потомка*)

{}writeln('Клиент: сервер завершен, конец работы');

end;

end.

Упражнение 13.60. Используя popen, создайте канал между who и more.

uses linux;

var

f1,f2:text;

s:string;

begin

popen(f1,'who','r');

if linuxerror <> 0 then

begin

writeln('Ошибка открытия канала с who для чтения');

exit;

end;

popen(f2,'more','w');

if linuxerror <> 0 then

begin

writeln('Ошибка открытия канала с more для записи');

exit;

end;

while not eof(f1) do

begin

readln(f1,s);

writeln(f2,s);

end;

pclose(f1);

pclose(f2);

end.

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