6. Напишите программу, которая использует вашу функцию для ее тестирования, а также другую программу, создающую входные данные для первой программы. Протестируйте функцию.
7. Перепишите вашу функцию с использованием fgets()
и протестируйте ее. Является ли новый код более сложным или менее сложным? Какова его производительность по сравнению с версией getc()
?
8. Изучите страницу справки V7 для /usr/man/man3/end.3
в дистрибутиве V7). Пролила ли она свет на то, как может работать 'sbrk(0)
'?
9. Усовершенствуйте ch03-memaddr.c
так, чтобы она печатала расположение аргументов и переменных окружения. В какой области адресного пространства они находятся?
Глава 4
Файлы и файловый ввод/вывод
Данная глава описывает базовые файловые операции: открытие и создание файлов, чтение и запись в них, перемещение в них и их закрытие. По ходу дела она представляет стандартные механизмы для обнаружения ошибок и сообщений о них. Глава заканчивается описанием того, как установить длину файла и принудительно сбросить данные файла и вспомогательные данные на диск.
4.1. Введение в модель ввода/вывода Linux/Unix
Модель API Linux/Unix для ввода/вывода проста. Ее можно суммировать четырьмя словами. открыть, прочитать, записать, закрыть. Фактически, это имена системных вызовов: open()
, read()
, write()
, close()
. Вот их объявления:
#include
#include
#include
#include
int open(const char *pathname, int flags, mode_t mode);
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
int close(int fd);
В следующем и дальнейших разделах мы проиллюстрируем модель, написав очень простую версию cat
. Она так проста, что даже не имеет опций; все, что она делает, — объединяет содержимое двух именованных файлов и выводит его в стандартный вывод. Она выводит минимум сообщений об ошибках. Написав, мы сравним ее с V7 cat
.
Мы представим программу сверху вниз, начав с командной строки. В последующих разделах мы представим обработку ошибок, а затем перейдем к сущностным задачам, показав, каким образом осуществляется реальный файловый ввод/вывод.
4.2. Представление базовой структуры программы
Наша версия cat следует структуре, которая обычно является полезной. Первая часть начинается с комментариев, заголовочных файлов, объявлений и функции main():
1 /*
2 * ch04-cat.c --- Демонстрация open(), read(), write(), close(),
3 * errno и strerror().
4 */
5
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13
14 char *myname;
15 int process(char *file);
16
17 /* main --- перечислить аргументы файла */
18
19 int
20 main(int argc, char **argv)
21 {
22 int i;
23 int errs = 0;
24
25 myname = argv[0];
26
27 if (argc == 1)
28 errs = process("-");
29 else
30 for (i = 1; i < argc; i++)
31 errs += process(argv[i]);
32
33 return (errs != 0);
34 }
Переменная myname
(строка 14) используется далее для сообщений об ошибках; main()
первым делом устанавливает в ней имя программы (argv[0]
). Затем main()
в цикле перечисляет аргументы. Для каждого аргумента она вызывает функцию process()
.