- •Міністерство освіти і науки України
- •Жуковецька с.Л., Шестопалов с.В.
- •Анотація
- •Введення
- •Лабораторна робота №1 Технологія розробки програм у середовищі Linux
- •1. Команди роботи з командним інтерпретатором ос unix
- •2. Створення програми
- •3. Функції введення-виведення.
- •4. Приклад програми
- •5. Основні керуючі конструкції мови с
- •6. Індівідуальні завдання
- •Лабораторна робота № 2. Автоматизація пакетних завдань
- •1. Компіляція багатомодульною програми
- •2. Автоматизація пакетних завдань
- •4. Завдання
- •Лабораторна робота № 3. Взаємодія програми з середовищем виконання
- •1. Аргументи командного рядка
- •2. Змінні оточення
- •3. Індівідуальні завдання
- •Лабораторна робота №4. Контроль виконання програми
- •1. Коди завершення програми
- •2. Функції обробки значення errno
- •3. Функція atexit()
- •4. Макрос asssert()
- •5. Індівідуальні завдання
- •Лабораторна робота №5 Файлові api.
- •1 Основні поняття
- •2. Права доступу до файлів
- •3. Інтерфейси для файлового введення / виводу
- •4. Системні виклики роботи з файлами
- •5. Індівідуальні завдання
- •Варіанти завдань
- •Лабораторна робота №6 Робота з каталогами та посиланнями
- •Методичні вказівки
- •1. Створення та видалення каталогу
- •2. Читання каталогу
- •3. Зміна каталогу
- •4. Управління жорсткими посиланнями
- •5. Управління символічними посиланнями
- •6. Перейменування файлів і каталогів
- •7. Індівідуальні завдання
- •Лабораторна робота №7. Одержання і відображення метаданих файлу.
- •Методичні вказівки
- •1. Механізми управління файлами ос unix
- •2. Отримання даних індексного дескриптору
- •3. Додаткові функції маніпулювання даними індексних дескрипторів
- •4. Отримання даних про відкриті файли
- •5. Індівідуальні завдання
- •Лабораторна робота №8. Керування процесами
- •Методичні вказівки
- •1. Загальні поняття
- •2. Створення поцесу
- •4. Перезавантаження програми процесу
- •5. Завершення виконання процесу
- •6. Системні виклики wait, waitpid
- •7. Індівідуальні завдання
- •Лабораторна робота №9. Використання каналів
- •Методичні вказівки
- •1. Заганьні відомості
- •2. Використання каналів
- •3. Індівідуальні завдання
- •Варіанти завдань
- •Лабораторна робота №10 Використання повідомлень
- •Методичні вказівки
- •1. Загальні відомості
- •2. Використання повідомлень
- •3. Індівідуальні завдання
- •Література
- •Системне програмування Посібник до виконання лабораторних та самостійних робіт
- •65082, Одеса, вул. Дворянська, 1/3
2. Функції обробки значення errno
У бібліотеці UNIX є зручні функції обробки значення errno
Функція strerror() - повертає строковий еквівалент коду помилки. Ці рядки можна включати в повідомлення про помилки. Оголошення функції перебуває у файлі <string. h>.
У наступному фрагменті програми робиться спроба відкрити файл. Якщо це не виходить, виводиться повідомлення про помилку й програма завершує свою роботу. У випадку успіху операції функція open() повертає дескриптор відкритого файлу, інакше - -1.
fd = open("inputfile.txt",O_RDONLY);
if(fd == -1){
fprintf(stderr,"error opening file: %s\n", strerror(errno)); exit (1);
}
У наступному фрагменті оголошена struct stat statbuf. Відкривається деякий файл, змінної fd привласнюється номер файлового дескриптора. C допомогою fstat робиться спроба зчитувати інформацію про файл(за значенням fd) у структуру statbuf
if (fstat ( fd, &statbuf)==-1)
{ printf("Fstat failed; %s\n",strerror(errno)); }
Функція perror() - за значенням errno бере з таблиці sys_errlist відповідне значення й записує його безпосередньо в потік stderr. (оголошена у файлі <stdio.h>). Перед властиво повідомленням варто розміщати строковий префікс, що містить ім'я функції або модуля, що стали причиною збою.
Приклади
1.
# Include <stdio.h>
int main (void)
{chars [] = "Hello, World!";
If (printf ("% s \ n", s)> 0)
{perror("Can ' t print ");
return -1;}
return 0;}
2.
# Include <stdio.h>
int main (void)
{FILE * fp;
fp = fopen ("perror.dat", "r");
if (! Fp)
perror ("Не можу відкрити файл для читання. \ n ");
return 0;}
3.
# Include <unistd.h>
# include <fcntl.h>
# include <stdio.h>
int main (void)
{int fn1, fn2;
fn1 = open ("data1", O_RDONLY);
if (fn1 == -1)
perror ("спроба відкрити вступної файл невдала");
fn2=open("data2",O_WRONLY|O_TRUNC | O_CREAT,
S_IREAD | S_IWRITE);
if (fn2 == -1)
perror ("спроба відкрити вивідний файл невдала");}
Залежно від особливостей програми й використовуваного системного виклику конкретні дії, що вживаються у разі помилки, можуть бути різними: поява повідомлення про помилку, скасування операції, аварійне завершення програми, повторна тортури і навіть ігнорування помилки. Тим не менш, важливо включити в програму код, що обробляє всі можливі варіанти помилок.
3. Функція atexit()
У програмі, написаній на C або C + + код повернення вказується у операторі return у функції main або при виконанні виклику функції exit (). Процес може бути завершений і з незалежних від неї обставин, наприклад, внаслідок отримання сигналу. У цьому випадку функція exit () буде викликана ядром від імені процесу.
Системний виклик exit () виглядає наступним чином:
# include <unistd.h>
void exit (int status);
Аргумент status - код повернення програми - повертається батьківському процесові.
Наявність коду повернення дозволяє програмам взаємодіяти один з одним.
При успішному завершенні програми крім передачі коду повернення, функція exit (0) виробляє ряд додаткових дій, зокрема виводить буферизованная дані і закриває потоки введення-виведення.
Такі дії називаються обробкою виходу. Завдання може зареєструвати до 32 обробників виходу (exit handler), - функції, які викликаються після виклику exit (), але до остаточного завершення процесу. Викликаються ці обробники за принципом LIFO і реєструються за допомогою функції atexit ():
ATEXIT - реєстрова процедура, яка реєструє функцію, адреса якої передається їй як параметр, тобто через регістр (E) AX, як функцію завершення програми. При успішній реєстрації ATEXIT повертає 0. Завершальні функції не повинні мати параметрів і повернення.
# Include <stdlib.h>
int atexit (void (* func) (void);
Приклад:
# include <stdio.h>
# include <stdlib.h>
void handler1 ()
{printf
("handler1 \
n");}
void handler2 ()
{printf
("handler2 \
n");}
void handler3 ()
{printf
("handler2 \
n");}
int main ()
{atexit
(& handler1);
atexit (& handler2);
atexit (& handler3);
return
(0);}