- •Введення
- •1. Структура та обсяг дисципліни
- •2. Основи програмування на мові с
- •2.1 Найпростіші конструкції мови
- •2.2 Типи даних
- •2.4 Операції мови с
- •2.5 Структура простої с програми
- •2.6 Організація введення-виведення
- •2.7 Компіляція в системі Linux
- •2.8 Організація розгалужень в програмі
- •2.9 Організація циклів
- •2.10 Оператор break
- •2.11 Оператор continue
- •2.11 Масиви
- •2.12 Функції
- •2.13 Вызов функции с переменным числом параметров
- •2.14 Рекурсивні функції
- •2.15 Читання і запис текстових файлів
- •2.16 Структури даних
- •2.17 Перелік|перерахування| (enumeration)
- •2.18 Об'єднання (union)
- •3. Операційні системи і системне програмування
- •3.1. Поняття операційної системи
- •4. Корисні команди Linux
- •4.1. Загальні|спільні| команди
- •4.1.1. Команда arch – виведення архітектури комп'ютера
- •4.1.2. Команда clear – очищення екрану
- •4.1.3. Команда date
- •4.1.9. Команда uptime – інформація про роботу системи
- •4.1.10. Команда users – інформація про користувачів
- •4.1.11. Команди w, who і whoami інформація про користувачів
- •4.1.12. Команда xf8config – настройка графічної підсистеми
- •4.2. Команди для роботи з текстом
- •4.2.1. Команди diff і cmp
- •4.2.2. Команди grep і egrep – текстовий фільтр
- •4.2.3. Команди more и less – посторінкове виведення
- •4.2.4. Команди head і tail – виведення начала і хвоста файлу
- •4.2.5. Команда wc – підрахунок слів у файлі
- •5. Захист інформації в інформаційних системах
- •5.1 Основні завдання забезпечення безпеки
- •5.2 Базові поняття криптографії
- •5.2.1 Поняття криптографічного алгоритму і протоколу
- •5.2.2 Криптосистеми з секретним ключем
- •5.2.3 Криптосистеми із відкритим ключем
- •5.2.4. Гибридні криптосистеми
- •5.2.5. Цифрові підписи
- •5.2.6. Сертифікати
- •5.3. Принципи аутентифіекації і керування доступом
- •5.3.1. Основи аутентифікації
- •5.3.2. Основи керування доступом
- •5.4. Аутентифікація та керування доступом в unix
- •5.4.1. Облікові записи користувачів
- •5.4.2. Аутентифікація
- •5.4.3. Керування доступом
- •6. Програмний інтерфейс unix. Системні виклики і функції стандартних бібліотек
- •6.1. Підтримка програмування в oc unix. Вивчення передачі інформації
- •6.2. Змінні оточення
- •6.3. Обробка помилок
- •6.4. Правила формування і засоби розбору командних рядків
- •7. Операції над файлами
- •7.1 Файлові операції posix
- •7.2. Збирання інформації про атрибути файла
- •7.3. Операції над каталогами
- •Література
7.1 Файлові операції posix
Усі UNIX-системи реалізують доступ до файлів за допомогою компактного набору системних викликів, визначеного стандартом POSIX.
Відкриття і створення файлів
Для відкриття файла використовують системний виклик open(), першим параметром якого є шлях до файла.
#include<fcntl.h>
int open(const char *pathname, int flags[,mode_t mode]);
Виклик open() повертає цілочислове значення - файловий дескриптор. У разі помилки цей виклик поверне -1, а значення змінної errno відповідатиме коду помилки.
Розглянемо деякі значення, якиз може набувати параметр flags (їх можна поєднувати за допомогою побітового АБО).
O_RDONLY, O_WRONLY, O_RDWR – відкриття файла, відповідно, тільки на читання, тільки для записування, або для читання і записування (має бути задане одне із цих трьох значень, наведені нижче не обов’язкові).
O_CREAT – якщо файл із таким ім’ям відсутній, його буде створено, якщо файл є і увімкнуто прапорець O_EXCL, буде повернено помилку.
O_TRUNC – якщо файл відкривають для записування, його довжину накладають рівною нулю.
O_NONBLOCK – задане неблокувальне введення/виведення, особливості його використання розглянемо разом із викликом read().
Параметр mode потрібно задавати тільки тоді, коли задано прапорець O_CREAT. Значенням у цьому випадку буде вісімкове число, що задає права доступу до файла.
Приклад:
// відкриття файла для записування
int fd1=open(“./myfile.txt”,O_WRONLY|O_CREAT|O_TRUNC,0644);
// відкриття файла для читання, помилка, якщо файла немає
int fd1=open(“./myfile.txt”,O_RDONLY);
Системний виклик creat() створює новий або очищає існуючий файл і відкриває його на запис:
#include<sys/stat.h>
#include<fcntl.h>
int creat(const char *path,mode_t perms);
Тут:
path – шляхове ім’я файлу;
perms – права доступу.
Закриття файла
Файл закривають за допомогою системного виклику close(), що приймає файловий дескриптор:
#include<unistd.h>
int close(int fd);
Повертає 0 у випадку успіху, -1 у разі помилки.
Читання і записування даних
Для читання даних із відкритого файла використовують системний виклик read():
#include<unistd.h>
ssize_t read(int fd1, void *buf,size_t count);
Внаслідок цього виклику буде прочитано count байтів із файла, заданого відкритим дескріптором fd1, у пам’ять, на яку вказує buf (ця пам’ять виділяється заздалегідь). Виклик read повертає реальну кількість прочитаних даних. Покажчик позиції у файлі пересувають за зчитані дані.
char buf[100];
// читають 100 байт з файлу в buf
int bytes_read=read(fd1,buf,sizeof(buf));
Коли потрібна кількість даних у конкретний момент відсутня (наприклад, fd1 пов’язаний із мережевим з’єднанням, яким ще не прийшли дані), поведінка цього виклику залежить від значення прапорця O_NONBLOCK під час виклику open().
У разі блокувального виклику (O_NONBLOCK не увімкнуто) він призупинить поточний потік до тих пір, поки дані не з’являться, а в разі неблокувального (прапорець O_NONBLOCK увімкнуто) зчитає всі доступні дані і завершиться, призупинення потоку не відбудеться.
#include<sys/types.h>
#include<sys/uio.h>
ssize_t readv(int fildes,struct iovec *iov,int iovcnt);
З файлу з файловим дескриптором fildes зчитиваються дані, починаючи з поточної позиції файлового покажчика. Зчитані дані містяться в буфер додатку, покажчик на який передається в buf.
Функція readv() дозволяє виконати iovcnt послідовних операцій читання за одне звернення до readv(). Аргумент iov указує на масив структур, кожен елемент якої має вигляд:
struct {
void *iov_base; // покажчик на початок буфера
size-t iov_len; // розмір буфера
}iovec;
Функція readv() прочитує дані з файлу і послідовно розміщує їх в декількох буферах, визначених масивом iov. Такий характер роботи одержав назву scatter read (від scatter (англ.) - розкидати). Загальне число лічених байт в нормальній ситуації рівне сумі розмірів вказаних буферів. Для записування даних у відкритий файл через файловий дескриптор використовують системний виклик write():
#include<unistd.h>
ssize_t write(int fd1,const void *buf,size_t count);
внаслідок цього виклику буде записано count байтів у файл через дескриптор fd1 із пам’яті, на яку вказує buf. Виклик write() повертає обсяг записаних даних.
int fd1, bytes_written;
fd1=open(“./myfile.txt”,O_RDWR|O_CREAT,0644);
bytes_written=write(fd1,”Hello”,sizeof(“Hello”));
Реалізація копіювання даних
Наведемо приклад реалізації копіювання даних за дапомогою засобів POSIX:
char buf[1024];
int bytes_read, infile,outfile;
infile=open(“infile.txt”,O_RDONLY);
if(infile==-1)
{
printf(“Помилка під час відкриття файла \n”);
exit(-1);
}
// створення результуючого файла, перевірку помилок пропущено
outfile=open(“outfile.txt”,O_WRONLY|O_CREAT_O_TRUNC,0644);
do
{
bytes_read=read(infile,buf,sizeof(buf));
if(bytes_read>0)
write(outfile,buf,bytes_read);
}
while(bytes-read>0);
close(infile);
close(outfile);
Переміщення покажчика поточної позиції у файлі
У файловому дескрипторі запам'ятовується поточна позиція у файлі. При читанні або запису даних покажчик поточної позиції переміщається на ту кількість байтів, яка була прочитана або записана. Але іноді потрібно здійснити просте переміщення по файлу (позиціонування): може потрібно повернутися в початок файлу або прочитати його наново, не відкриваючи повторно.
Кожному відкритому файлу відповідає покажчик позициї (зсув) у середині файла. Його можна пересувати за допомогою системного виклику lseek().
#include<unistd.h>
off_t lseek(int fd1, off_t offset,int whence);
Функція повертає зсув нової позиції від початку файла. У разі помилки повертається -1.
Параметр offset задає величину переміщення покажчика в байтах.
Режим переміщення задають параметром whence, який може набувати значень:
SEEK_SET – абсолютне переміщення від початку файла;
SEEK_CUR – відносне переміщення від поточного місця покажчика позиції;
SEEK_END – переміщення від кінця файла.
Коли покажчик поточної позиції перед операцією записування опиняється за кінцем файла, він внаслідок записування автоматично розширюється до потрібної довжини. На цьому грунтується ефективний спосіб створення файлів необхідного розміру.
int fd1=open(“file”,O_RDWR|O_CREAT|O_TRUNC,0644);
lseek(fd1,needed_size,SEEK_SET);
write(fd1,””,1);
