- •Анотація
- •1 Середовище програмування ос unix
- •1.1 Структура ос unix
- •1.2 Створення програми
- •1. Препроцесор
- •2. Транслятор
- •2.1 Компілятор
- •2.2 Асемблер
- •3. Редактор зв'язків(Компонувальником)
- •1.3 Формати об'єктних файлів
- •2 Використання файлової системи unix
- •2.1 Основні поняття
- •2.1.1 Типи та іменування файлів
- •2.1.2 Права доступу до файлів
- •2.1.3 Cистемные структури керування файлами
- •2.1.4 Системні виклики роботи з файлами
- •2.2 Створення та відкриття файлів
- •2.2.1 Системний виклик open
- •2.2.2 Системний виклик create
- •2.2.3 Системний виклик close
- •2.3 Читання та зипис в файл
- •2.3.1 Системний виклик read
- •2.3.2 Системний виклик write
- •2.4 Позіціонування у файлі
- •2.4.1 Системний виклик lseek
- •2.4.2 Системні виклики pread і pwrite
- •2.4.3 Системні виклики readv і writev
- •2.5 Контрольні операції над файлами
- •2.5.1 Системні виклики stat, fstat і lstat
- •2.5.2 Контроль прав доступу до файлу
- •2.5.3 Функція fcntl
- •2.5.4 Системні виклики truncate і ftruncate
- •2.6 Управління каталогами
- •2.6.1 Створення і видалення
- •2.6.2 Читання каталога
- •2.6.3 Зміна каталога
- •2.7 Управління посиланнями
- •2.7.1 Управління жорсткими посиланнями
- •2.7.2 Управління символічними посиланнями
- •2.7.3 Перейменування файлів і каталогів
- •3 Керування процесами ос unix
- •3.1 Процеси ос unix
- •3.2 Сисвизови створення процесів
- •3.3 Завершення процесу
- •3.4 Взаємодія процесів в ос unix
- •3.5 Сигнали
- •3.5.1 Поняття сигналу
- •3.5.2 Розробка оброблювачів сигналів
- •3.5.3 Генерація сигналів
- •3.5.4 Посилка сигналів іншим процесам
- •3.5.5 Блокування сигналів
- •3.5.6 Очікування сигналу
- •3.6 Трасування процесу.
- •3.7 Канали й fifo-Файли
- •3.7.1 Поняття
- •3.7.2 Створення каналу
- •3.7.3 Створення fifo-Файлів
- •3.8 Семафори
- •3.9 Повідомлення.
- •3.10 Поділювана пам'ять.
- •Література
- •Системне програмування Навчальний посібник
- •65082, Одеса, вул. Дворянська, 1/3
2.5.2 Контроль прав доступу до файлу
access(filename,mode)
char *filename;
int mode;
Функція access перевіряє, чи має процес дозвіл на читання, запис або виконання файлу Якщо pathname є символьним посиланням, то перевіряються права доступу до файлу, на який вона указує. mode - це маска, що складається з одного або більш за прапори R_OK, W_OK, X_OK і F_OK.
R_OK, W_OK і X_OK використовуються для перевірки, чи існує файл і чи можна його читати, записувати в нього або виконувати, F_OK просто перевіряє існування файлу.
Повертає 0 у разі успіху -1 у разі помилки (код помилки -в змінної errno)
Зміна власника і прав доступу до файлу
chown - зміна власника і групи файлу
int chown (path, owner, group)
char *path;
int owner, group;
Аргумент path є покажчиком на маршрутне ім'я файлу. Ідентифікатори власника і групи вказаного файлу встановлюються рівними числовим значенням, відповідно, аргументів owner і group.
Тільки суперкористувач може змінити власника файлу. Власник файлу може змінювати групу файлу на будь-яку групу, до якої він належить. Суперкористувач може довільно проводити цю заміну.
chmod - зміна режиму доступу до файлу
#include <sys/types.h>
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
int fchmod(int fildes, mode_t mode);
Можна змінювати коди доступу, відповідні бітовій масці
0777 | S_ISUID | S_ISGID | S_ISVTX
Аргумент path є покажчиком на маршрутне ім'я файлу. Системний виклик chmod встановлює режим доступу до вказаного файлу відповідно до бітового шаблону, що міститься в аргументі mode.
Змінювати права доступу до файлу може тільки процес, що має ідентифікатор користувача, що діє, рівний ідентифікатору власника файлу або суперкористувача.
Якщо системні виклики chown і chmod виконуються не суперкористувачем, то біти переустановлення ідентифікаторів користувача і групи, 04000 і 02000 відповідно, обнуляються.
Системний виклик umask
Ми вже згадували про маску, що накладається на набір прав доступу при створенні файлу. Накладення маски виконує системний виклик umask, який рідко використовується де-небудь ще, окрім як в команді umask.
umask — встановлює і повертає маску прав доступу для новостворюваних файлів.
#include <sys/stat.h>
mode_t umask(mode_t cmask);
cmask - нова маска
Повертає попереднє значення маски повернення код помилок не передбачений
Оскільки кожен процес має маску і будь-яка комбінація з 9 біт вважається допустимим, umask не передбачає вихід помилково. Він завжди повертає колишнє значення маски. Щоб дізнатися поточне значення маски не змінюючи її, потрібно виконати два послідовні виклики umask. Перший — щоб набути поточного значення маски (передавши у виклик будь-яке значення нової маски), другої, — щоб відновити її в первинний стан.
2.5.3 Функція fcntl
Над дескрипторами файлів можна виконувати деякі операції, наприклад, відкривати файли, дублюючи дескриптори відкритих файлів, отримувати або встановлювати прапори, що описують стан дескриптора, захоплювати блоки файлу і так далі Всі ці операції виконуються функцією fcntl.
#include <fcntl.h>
int fcntl (int fd, int cmd, arg)
Функція виконує команду cmd над дескриптором файлу fd.
Деякі команди вимагають завдання додаткових аргументів.
Таблиця 1
Основні команди cmd
F_DUPFD |
Дублювання дескриптора файлу. Повертає інший дескриптор, що асоціюється з тим же відкритим файлом; |
F_GETFD |
Отримує прапори, що асоціюються з дескриптором; |
F_SETFD |
Встановлює прапори, що асоціюються з дескриптором; |
F_GETFL |
Отримує прапори, що асоціюються з відкритим файлом; |
F_SETFL |
Встановлює прапори, що асоціюються з відкритим файлом; |
F_GETLK |
Отримує інформацію про захоплені області файлу; |
F_SETLK |
Встановлює або скидає захоплення файлу; |
F_SETLKW |
Ідентично F_SETLK, але чекає закінчення виконання; |
F_GETOWN |
Отримує процес або групу процесів, яким буде посланий сигнал SIGIO |
F_SETOWN |
Встановлює процес або групу процесів, яким буде посланий сигнал SIGIO |
Діагностика
При успішному завершенні системного виклику залежно від операції cmd повертаються наступні значення:
F_DUPFD Новий дескриптор файлу.
F_GETFD Значення прапора (визначений тільки молодший біт).
F_SETFD Значення, відмінне від -1.
F_GETFL Значення прапорів статусу файлу.
F_SETFL Значення, відмінне від -1.
F_GETLK Значення, відмінне від -1.
F_SETLK Значення, відмінне від -1.
F_SETLKW Значення, відмінне від -1.
У разі помилки повертається -1, а змінною errno привласнюється код помилки.
Отримання і установка прапора стану файлу
1) Як по дескриптору файлу дізнатися, відкритий він на читання, запис, читання і запис одночасно?
int flags;
if((flags=fcntl (fd, F_GETFL, NULL)) < 0 )
return NULL; /* fd ймовірно не відкритий */
flags &= O_RDONLY | O_WRONLY | O_RDWR;
switch(flags){
case O_RDONLY: return "r";
case O_WRONLY: return "w";
case O_RDWR: return "r+w";
default: return NULL;
}
2) приклад зміни прапора дескриптора:
int flags = fcntl (fd, F_GETFL, 0);
fcntl (fd, F_SETFL, flags | O_NONBLOCK);
3) установка нового власника
fcntl(fd, F_SETOWN, getpid())
4) setflag (int desc, int value)
{
int oldflags = fcntl (desc, F_GETFL, 0);
/* якщо відбулася помилка, виходимо з програми */
if (oldflags == -1)
return -1;
/* встановлюємо тільки потрібний прапор */
if (value != 0)
oldflags |= O_NONBLOCK;
else
oldflags &= ~O_NONBLOCK;
/* зберігаємо прапор в дескрипторі файлу */
return fcntl (desc, F_SETFL, oldflags);
}
Передається два параметри: дескриптор і індикатор – 0, якщо треба зняти прапор і не 0, якщо встановити.
|= додає ?=~ знімає ~ інвертує
Зберігаємо в дескрипторі, повертаємо в зухвалу процедуру.
Блокування файлів з використанням fcntl
Окрім модифікації файлового дескриптора системний виклик fcntl(2) використовується для блокування файлу. Блокування областей файлу дозволяє декільком програмам спільно працювати з вмістом одного і того ж файлу, не заважаючи один одному.
Прикладом ситуації, в якій може бути корисний захоплення файлу служить бути програма, яка може бути запущена декількома користувачами незалежно, записує протокол роботи у файл. Декілька процесів, що одночасно записують інформацію у файл можуть зміщувати інформацію різних користувачів, що приведе до плутанини. У разі захоплення файлу цього не відбудеться.
В цьому випадку cmd - тип блокуючої операції, а в у arg указується адреса структури flock, в яку записується інформація про блокування. Структура і відповідні макроси описані в заголовному файлі <fcntl.h>.
Таблиця 2
Опис полий структури flock
Поле |
Значення |
short l_type |
Тип блокування: записи – F_RDLCK, читання – F_WRLCK, скидання – F_UNLCK. |
short l_whence |
Адреса початку ділянки, що блокується; дається у вигляді зсуву відносно початку файлу (0), щодо поточної позиції покажчика (1), щодо кінця файлу (2) |
long l_start |
Зсув в байтах, що інтерпретується відповідно до значення l_whence |
long l_len |
Довжина ділянки, що блокується, в байтах. Якщо вказаний 0, блокується ділянка від l_start до кінця файлу |
long l_pid |
Ідентифікатор процесу, що встановив блокування (для GETLCK) |
long l_sysid |
Ссистемний ідентифікатор процесу, блокуючого файл |
Якщо задана область вже заблокована, fcntl повертає -1.
За допомогою команди F_GETLK можна дізнатися, ідентифікатор процесу, що заблокував дану область.
Ядро автоматично знімає блокування, встановлені процесом, при закритті файлу.
За допомогою цієї функції можна маніпулювати дескрипторами файлів і встановлювати рекомендаційні (advisory) блокування (необов'язкові). В цьому випадку, якщо програма сама не використовує блокувань, блокування, встановлені іншими програмами, не матимуть для неї ніякого ефекту. Існує можливість додати рекомендаційним блокуванням fcntl() обов'язковий характер, але для цього відповідна файлова система повинна бути змонтована із спеціальним ключем.
Базові правила використання блокувань:
Програми, які хочуть читати з файлу, належний відкрити файл, а потім використовувати fcntl в режимі F_RDLCK
Програми, які хочуть читати з файлу і записувати у файл повинні відкрити файл, а потім використовувати flock в режимі F_WRLCK.
Виклик flock блокуватиме файл до тих пір, поки він доступний, в цей час необхідні операції можуть бути виконані з деякою мірою безпеки.
Після виконання операцій приберіть блокування шляхом закриття файлового дескриптора або за допомогою F_UNLCK
Приклад
1. Для установки блокування ми заповнюємо поля структури flock необхідними значеннями і викликаємо fcntl() з командою F_SETLK (встановити блокування):
..
struct flock fi;
fd=open(file, O_RDWR);
fi.l_type = F_WRLCK;
fi.l_whence = SEEK_SET;
fi.l_start = 0;
fi.l_len = 64;
off = 0;
while (fcntl(fd, F_SETLK &fi)== -1)
{ fcntl(fd, F_GETLK & fi);
...
printf("байти %i - %i заблоковані процесом %i\n", off, off+64
fi.l_pid);
}
Якщо задана область вже заблокована, fcntl повертає -1. За допомогою команди F_GETLK можна дізнатися, ідентифікатор процесу, що заблокував дану область.
2. Для того, щоб зняти блокування, ми викликаємо fctnl() з командою F_SETLK (дивно, чи не так?) і параметром l_type = F_UNLCK:
fi.l_type = F_UNLCK;
if (fcntl(fd, F_SETLK &fi)== -1)
printf("Помилка разблокирования\n");