Чтение файла: системный вызов read() 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Чтение файла: системный вызов read()



Системный вызов read(), объявленный в файле unistd.h, позволяет читать данные из файла. В отличие от библиотечных функций файлового ввода-вывода, которые предоставляют возможность интерпретации считываемых данных. Можно, например, записать в файл следующее содержимое:

2006

Теперь, используя библиотечные механизмы, можно читать файл по-разному:

fscanf (filep, "%s", buffer); fscanf (filep, "%d", number);

Системный вызов read() читает данные в "сыром" виде, то есть как последовательность байт, без какой-либо интерпретации. Ниже представлен адаптированный прототип read().

ssize_t read (int fd, void * buffer, size_t count);

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

Хочу сказать несколько слов о типах. Тип size_t в Linux используется для хранения размеров блоков памяти. Какой тип реально скрывается за size_t, зависит от архитектуры; как правило это unsigned long int или unsigned int. Тип ssize_t (Signed SIZE Type) - это тот же size_t, только знаковый. Используется, например, в тех случаях, когда нужно сообщить об ошибке, вернув отрицательный размер блока памяти. Системный вызов read() именно так и поступает.

Теперь напишем программу, которая просто читает файл и выводит его содержимое на экран. Имя файла будет передаваться в качестве аргумента (argv[1]). Ниже приведен исходный код этой программы.

/* myread.c */ #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> int main (int argc, char ** argv) {   int fd;   ssize_t ret;   char ch;   if (argc < 2)   {          fprintf (stderr, "Too few arguments\n");          exit (1);   }   fd = open (argv[1], O_RDONLY);   if (fd < 0)   {          fprintf (stderr, "Cannot open file\n");          exit (1);   }     while ((ret = read (fd, &ch, 1)) > 0)   {          putchar (ch);   }   if (ret < 0)   {          fprintf (stderr, "myread: Cannot read file\n");          exit (1);   }   close (fd);   exit (0); }

В этом примере используется укороченная версия open(), так как файл открывается только для чтения. В качестве буфера (второй аргумент read()) мы передаем адрес переменной типа char. По этому адресу будут считываться данные из файла (по одному байту за раз) и передаваться на стандартный вывод. Цикл чтения файла заканчивается, когда read() возвращает нуль (нечего больше читать) или -1 (ошибка). Системный вызов close() закрывает файл.

Как можно заметить, в нашем примере системный вызов read() вызывается ровно столько раз, сколько байт содержится в файле. Иногда это действительно нужно; но не здесь. Чтение-запись посимвольным методом (как в нашем примере) значительно замедляет процесс ввода-вывода за счет многократных обращений к системным вызовам. По этой же причине возрастает вероятность возникновения ошибки. Если нет действительной необходимости, файлы нужно читать блоками. О том, какой размер блока предпочтительнее, будет рассказано в последующих главах книги. Ниже приведен исходный код программы, которая делает то же самое, что и предыдущий пример, но с использованием блочного чтения файла. Размер блока установлен в 64 байта.

/* myread1.c */ #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #define BUFFER_SIZE 64 int main (int argc, char ** argv) {   int fd;   ssize_t read_bytes;   char buffer[BUFFER_SIZE+1];   if (argc < 2)   {          fprintf (stderr, "Too few arguments\n");          exit (1);   }   fd = open (argv[1], O_RDONLY);   if (fd < 0)   {          fprintf (stderr, "Cannot open file\n");          exit (1);   }     while ((read_bytes = read (fd, buffer, BUFFER_SIZE)) > 0)   {          buffer[read_bytes] = 0; /* Null-terminator for C-string */          fputs (buffer, stdout);   }   if (read_bytes < 0)   {          fprintf (stderr, "myread: Cannot read file\n");          exit (1);   }   close (fd);   exit (0); }

Теперь можно примерно оценить и сравнить скорость работы двух примеров. Для этого надо выбрать в системе достаточно большой файл (бинарник ядра или видеофильм, например) и посмотреть на то, как быстро читаются эти файлы:



Поделиться:


Последнее изменение этой страницы: 2021-06-14; просмотров: 51; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.144.193.129 (0.005 с.)