Язык С

       

Низкоуровневый ввод/вывод - операторы READ и WRITE


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

N_READ=READ(FD,BUF,N); N_WRITTEN=WRITE(FD,BUF,N);

При каждом обращении возвращается счетчик байтов, указываю- щий фактическое число переданных байтов. При чтении возвра- щенное число байтов может оказаться меньше, чем запрошенное число. Возвращенное нулевое число байтов означает конец фай- ла, а "-1" указывает на наличие какой-либо ошибки. При запи- си возвращенное значение равно числу фактически записанных байтов; несовпадение этого числа с числом байтов, которое предполагалось записать, обычно свидетельствует об ошибке. Количество байтов, подлежащих чтению или записи, может быть совершенно произвольным. Двумя самыми распространенными величинами являются "1", которая означает передачу одного символа за обращение (т.е. Без использования буфера), и "512", которая соответствует физическому размеру блока на многих периферийных устройствах. Этот последний размер будет наиболее эффективным, но даже ввод или вывод по одному сим- волу за обращение не будет необыкновенно дорогим. Объединив все эти факты, мы написали простую программу для копирования ввода на вывод, эквивалентную программе ко- пировки файлов, написанной в главе 1. На системе UNIX эта программа будет копировать что угодно куда угодно, потому что ввод и вывод могут быть перенаправлены на любой файл или устройство. #DEFINE BUFSIZE 512 /*BEST SIZE FOR PDP-11 UNIX*/ MAIN() /*COPY INPUT TO OUTPUT*/ \( CHAR BUF[BUFSIZE]; INT N; WHILE((N=READ(0,BUF,BUFSIZE))>0) WRITE(1,BUF,N); \)


Если размер файла не будет кратен BUFSIZE, то при некотором обращении к READ будет возвращено меньшее число байтов, ко- торые затем записываются с помощью WRITE; при следующем пос- ле этого обращении к READ будет возвращен нуль. Поучительно разобраться, как можно использовать функции READ и WRITE для построения процедур более высокого уровня, таких как GETCHAR, PUTCHAR и т.д. Вот, например, вариант функции GETCHAR, осуществляющий ввод без использования буфе- ра.

#DEFINE CMASK 0377 /*FOR MAKING CHAR'S > 0*/ GETCHAR() /*UNBUFFERED SINGLE CHARACTER INPUT*/ \( CHAR C; RETURN((READ(0,&C,1)>0 7 & CMASK : EOF); \)

Переменная "C" должна быть описана как CHAR, потому что фун- кция READ принимает указатель на символы. Возвращаемый сим- вол должен быть маскирован числом 0377 для гарантии его по- ложительности; в противном случае знаковый разряд может сде- лать его значение отрицательным. (Константа 0377 подходит для эвм PDP-11, но не обязательно для других машин). Второй вариант функции GETCHAR осуществляет ввод больши- ми порциями, а выдает символы по одному за обращение.

#DEFINE CMASK 0377 /*FOR MAKING CHAR'S>0*/ #DEFINE BUFSIZE 512 GETCHAR() /*BUFFERED VERSION*/ \( STATIC CHAR BUF[BUFSIZE]; STATIC CHAR *BUFP = BUF; STATIC INT N = 0; IF (N==0) \( /*BUFFER IS EMPTY*/ N=READ(0,BUF,BUFSIZE); BUFP = BUF; \) RETURN((--N>=0) ? *BUFP++ & CMASK : EOF); \)




    Содержание раздела