Основы программирования в Linux
□ 0 — стандартный ввод;
□ 1 — стандартный вывод;
□ 2 — стандартный поток ошибок.
Вы можете связать с файлами и устройствами другие дескрипторы файлов, используя системный вызов open, который уже обсуждался вкратце. Дескрипторы файлов, открытые автоматически, уже позволяют вам создавать простые программы с помощью вызова
.writewrite
Системный вызов
предназначен для записи изwriteпервыхbufбайтов в файл, ассоциированный с дескрипторомnbytes. Он возвращает количество реально записанных байтов, которое может быть меньшеfildes, если в дескрипторе файла обнаружена ошибка или дескриптор файла, расположенный на более низком уровне драйвера устройства, чувствителен к размеру блока. Если функция возвращает 0, это означает, что ничего не записано; если она возвращает -1, в системном вызовеnbytesвозникла ошибка, которая описывается в глобальной переменнойwrite,errnoДалее приведена синтаксическая запись.
<b>#include <unistd.h></b><b>size_t write(int fildes, const void *buf, size_t nbytes);</b>Благодаря полученным знаниям вы можете написать свою первую программу, simple_write.c:
#include <unistd.h>#include <stdlib.h>int main() {if ((write(1, "Here is some data\n", 18)) != 18)write(2, "A write error has occurred on file descriptor 1\n", 46);exit(0);}Эта программа просто помещает сообщение в стандартный вывод. Когда она завершается, все открытые дескрипторы файлов автоматически закрываются, и вам не нужно закрывать их явно. Но в случае буферизованного вывода это не так.
$ <b>./simple_write</b>Here is some data$И еще одно маленькое замечание: вызов
может сообщить о том, что записал меньше байтов, чем вы просили. Это не обязательно ошибка. В ваших программах вам придется для выявления ошибок проверить переменнуюwriteи еще раз вызватьerrnoдля записи оставшихся данных.writeread
Системный вызов
считывает доreadбайтов данных из файла, ассоциированного с дескриптором файлаnbytes, и помещает их в область данныхfildes. Он возвращает количество действительно прочитанных байтов, которое может быть меньше требуемого количества. Если вызовbufвозвращает 0, ему нечего считывать; он достиг конца файла. Ошибка при вызове заставляет его вернуть -1.read<b>#include <unistd.h></b><b>size_t read(int fildes, void *buf, size_t nbytes);</b>Программа simple_read.c копирует первые 128 байтов стандартного ввода в стандартный вывод. Она копирует все вводимые данные, если их меньше 128 байтов.
#include <unistd.h>#include <stdlib.h>int main() {char buffer[128];int nread;nread = read(0, buffer, 128);if (nread == -1)write(2, "A read error has occurred\n", 26);if ((write(1, buffer, nread)) != nread)write(2, <i>"A</i> write error has occurred\n", 27);exit(0);}Если вы выполните программу, то получите следующий результат:
$ echo <b>hello there | ./simple_read</b>hello there$ <b>./simple_read < draft1.txt</b>FilesIn this chapter we will be looking at files and directories and how tomanipulate them. We will learn how to create files, $Первое выполнение программы с помощью команды
формирует некоторый ввод программы, который по каналу передается в вашу программу. Во втором выполнении вы перенаправляете ввод из файла draft1.txt. В этом случае вы видите первую часть указанного файла, появляющуюся в стандартном выводе.echoПримечаниеОбратите внимание на то, что знак подсказки или приглашения командной оболочки появляется в конце последней строки вывода, поскольку в этом примере 128 байтов не формируют целое число строк.
open
Для создания дескриптора нового файла вы должны применить системный вызов
.open<b>#include <fcntl.h></b><b>#include <sys/types.h></b><b>#include <sys/stat.h></b><b>int open(const char *path, int oflags);</b><b>int open(const char *path, int oflags, mode_t mode);</b>ПримечаниеСтрого говоря, для использования вызова
вы не должны включать файлы sys/types.h и sys/stat.h в системах, удовлетворяющих стандартам POSIX, но они могут понадобиться в некоторых системах UNIX.openНе вдаваясь в подробности, скажем, что вызов
устанавливает путь к файлу или устройству. Если установка прошла успешно, он возвращает дескриптор файла, который может применяться в системных вызовахopen,readи др. Дескриптор файла уникален и не используется совместно другими процессами, которые могут в данный момент выполняться. Если файл открыт одновременно в двух программах, они поддерживают отдельные дескрипторы файла. Если они обе пишут в файл, то продолжат запись с того места, где остановились. Их данные не чередуются, но данные одной программы могут быть записаны поверх данных другой. У каждой программы свое представление о том, какая порция файла (каково смещение текущей позиции в файле) прочитана или записана. Вы можете помешать нежелательным накладкам такого сорта с помощью блокировки файла, которая будет обсуждаться в главе 7.write