После неудачного завершения системного вызова сгеаt переменная еrrnо может принимать следующие значения:
[ЕNOTDIR] - указанное имя содержит компоненту, которая не является справочником;
[ЕNOENТ] - задано слишком длинное или пустое имя файла, или указанный файл не существует или какой-либо из справочников, входящих в имя файла, не доступен для просмотра;
[ЕРЕКМ] - указанное имя содержит символ, отсутствующий в коде АSСП;
[ELООР] - число косвенных ссылок в указанном имени превышает максимально допустимое значение;
[ЕROFS] - попытка создания файла в файловой системе, закрытой на запись;
[ЕТХТВSУ] - попытка сократить длину файла, содержащего загрузочный модуль реентерабельной программы (разделяемый текстовый сегмент), которая в настоящей момент выполняется;
[ЕАССЕS] - режим доступа указанного файла не соответствует запросу;
[ЕFAULТ] - адреса аргументов системного вызова выходят за границы памяти, доступной данному процессу;
[ЕISDIR] - указанное имя файла является именем справочника;
[ЕМFILЕ] - переполнилась таблица открытых файлов процесса;
[ЕNXIO] - указано имя специального файла, для которого нет соответствующего устройства.
Параметр mode задается произвольно, в нем не обязательно должно быть разрешение на запись. Эта возможность используется программами, которые работают с временными файлами с фиксированными именами. Создание производится с режимом, запрещающим запись. Затем, если другая программа пытается выполнить вызов сгеаt, возвращается ошибка и программе становится известно, что в данный момент это имя использовать нельзя. Все действия, перечисленные для вызова сгеаtе, можно выполнить с помощью системного вызова ореn. Вызов сгеаtе оставлен для совместимости с ранними версиями ОС Unix.
Системный вызов read
Системный вызов геаd (чтение файла) имеет следующий формат:
read (fd, buf, nbytes)
char *buf;
int fd, nbytes;
Системный вызов read обеспечивает считывание nbytes данных в массив buf из файла с дескриптором fd. Информация читается из файла по текущему указателю позиции чтения/записи. После завершения пересылки данных значение указателя увеличивается на число считанных байт. Для некоторых файлов значение указателя позиции чтения/записи не имеет смысла (например, для терминала), тем не менее, данные передаются. При успешном завершении вызова, возвращается число считанных байт, в случае ошибки - значение -1, при достижении конца файла в процессе чтения - число 0.
При возникновении ошибки чтения, переменная еrrnо может принимать следующие значения:
[ЕВАDF] - указанный дескриптор не является дескриптором файла, открытого для чтения;
[ЕFAULТ] - адрес параметра системного вызова не входит в адресное пространство процесса;
[ЕINTR] - чтение с медленного устройства прервано до передачи данных.
Системный вызов write
Системный вызов write (запись в файл) имеет следующий формат:
write (fd, buf, nbytes)
char *buf;
int fd, nbytes;
Системный вызов write записывает nbytes данных из массива buf в файл с дескриптором fd. Информация записывается в файл по текущему указателю позиции чтения/записи. После завершения пересылки данных, значение указателя увеличивается на число записанных байт. Для некоторых файлов значение указателя позиции чтения/записи не имеет смысла, (например, для терминала), тем не менее, данные передаются.
Если статус файла, в который записывается информация, содержит признак set-UID и процесс работает в непривилегированном режиме, данный признак удаляется (в целях защиты информации). При успешном завершении вызова возвращается число записанных байт, в случае ошибки - значение -1. При возникновении ошибки, переменная еrrnо может принимать следующие значения:
[ЕВАDF] - указанный дескриптор не является дескриптором файла, открытого для записи;
[ЕРIРЕ] - попытка записи в программный канал, который никто не читает;
[ЕРIРЕ] - запись в файл типа "гнездо" в режиме S0СК_SТRЕАМ, при отсутствии соединения;
[ЕFВIG] - при записи в файл превышается допустимый размер файла;
[ЕFAULТ] - адрес параметра системного вызова не входит в адресное пространство процесса.
Системный вызов сlose (закрыть файл) имеет следующий формат:
аns = сlоsе (fd)
int fd;
Системный вызов сlosе удаляет дескриптор fd из таблицы дескрипторов открытых файлов процесса. Если удаленный дескриптор был последним ссылающимся на данный файл, то весь контекст работы с файлом теряется. Для обычного файла это указатель позиции чтения/записи и режим блокировки. Хотя, при завершении процесса, все открытые им файлы автоматически закрываются, число одновременно открытых файлов ограничено, поэтому данный вызов может оказаться необходимым для программ, работающих с большим количеством файлов.
При порождении нового процесса (см описание вызова fork) все его дескрипторы указывают на те же объекты, что и дескрипторы процесса-предка. После выполнения вызова ехесvе в порожденном процессе, новая программа также наследует все активные дескрипторы. Для того, чтобы сделать недоступными новой программе уже открытые файлы, соответствующие дескрипторы можно переопределить с помощью dup2 или удалить с помощью системного вызова unlink. Однако бывают ситуации, в которых уже открытые файлы могут потребоваться при неудачном завершении системного вызова execvе. В таких случаях, применение вызова fcntl обеспечивает закрытие определенных файлов после успешного старта новой программы. В случае успешного завершения, системный вызов с1оsе возвращает значение 0, иначе - значение -1 и код ошибки в переменной еrrnо. Код ошибки:
[ЕВАDF] - указанный дескриптор не является дескриптором открытого файла.
Системный вызов lsееk
Системный вызов lsееk (установка указателя чтения/записи) имеет следующий формат:
#define L_SЕТ 0 /* установка * /
# define L_INCR 1 /* смещение */
# define L_ХТND 2 /* увеличение размера файла */
long lseek (fd, offset, whence)
int fd, whence;
long offset;
Системный вызов lsееk изменяет значение указателя позиции чтения/записи дескриптора fd следующим образом: если значение параметра whence равно L_SЕТ, то указателю присваивается значение параметра, если значение параметра whence равно L_INCR, значение указателя увеличивается .на значение offset, если значение параметра whence равно L_XTND, то указателю присваивается значение (offset + fsize), где fsize- размер файла.
Следует отметить, что если установить указатель текущей позиции за конец файла, а затем записать что-либо, в файле получается промежуток, который физически не занимает места, а при чтении дает нули.
В случае успешного завершения, вызов lseek возвращает значение указателя текущей позиции чтения/записи (целое положительное число), определяющее смещение от начала файла (в байтах).
При возникновении ошибки, возвращается значение -1 и код ошибки в переменной еrrnо, которая может принимать следующие значения:
[ЕВАDF] - некорректный дескриптор файла;
[ЕSРIРЕ] - дескриптор относится не к файлу, а к программному каналу или файлу типа "гнездо";
[ЕINVAL] - недопустимое значение параметра.
4.2 Управление оперативной памятью
Изучение возможностей языка программирования С/С++ для обращения к ячейкам оперативной памяти, управления ОП.
Указатели на простые переменные
Указатель - это адрес памяти, распределяемой для размещения идентификатора (в качестве идентификатора может выступать имя переменной, массива, структуры, строкового литерала). В том случае, если переменная объявлена как указатель, то она содержит адрес памяти, по которому может находиться скалярная величина любого типа. При объявлении переменной типа указатель, необходимо определить тип объекта данных, адрес которых будет содержать переменная, и имя указателя с предшествующей звездочкой (или группой звездочек). Формат объявления указателя: спецификатор-типа [ модификатор ] * описатель
Спецификатор-типа задает тип объекта и может быть любого основного типа, типа структуры, смеси. Задавая вместо спецификатора-типа ключевое слово void, можно своеобразным образом отсрочить спецификацию типа, на который ссылается указатель. Переменная, объявляемая как указатель на тип void, может быть использована для ссылки на объект любого типа. Однако для того, чтобы можно было выполнить арифметические и логические операции над указателями или над объектами, на которые они указывают, необходимо при выполнении каждой операции явно определить тип объектов. Такие определения типов может быть выполнено с помощью операции приведения типов.
В качестве модификаторов при объявлении указателя могут выступать ключевые слова const, near, far, huge. Ключевое слово const указывает, что указатель не может быть изменен в программе. Размер переменной объявленной как указатель, зависит от архитектуры компьютера и от используемой модели памяти, для которой будет компилироваться программа. Указатели на различные типы данных не обязательно должны иметь одинаковую длину.
Для модификации размера указателя можно использовать ключевые слова near, far, huge.
Примеры:
unsigned int * a; // переменная а представляет собой указатель
// на тип unsigned int (целые числа без знака)
double * x; // переменная х указывает на тип данных с