Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Приклад програми, що використовує файлові системні виклики






А тепер розглянемо просту UNIX-програму, яка копіює один файл з файлу-джерела у файл-приймач. Текст програми показаний в лістингу 1.1. У цієї програми мінімальні функціональні можливості, але вона дає досить чітке уявлення про деякі системні виклики, що відносяться до роботи з файлами.

Лістинг 1.1. Проста програма для копіювання файлів

/* Програма для копіювання файлу. Контроль помилок і повідомлення про їх появу зведені до мінімуму. */

#include < sys/types.h> /* включаємо необхідні заготовочні файли*/

#include < fcntl.h>

#include < stdlib.h>

#include < unistd.h>

int main (int argc, char *argv[]); /* ANSI прототип */

#define BUF_SIZE 4096 /* використання буферу розміром 4096 байт */

#define 0UTPUT_M0DE 0700 /* біти забезпечення безпеки для вихідного файлу */

int main(шnt argc, char *argv[])

{

int in_fd, out_fd, rd_count, wt_count;

char buffer[BUF_SIZE];

if (argc! = 3) exit(l); /* якщо argc не рівний 3, виникає синтаксична пмилка */

/* Відкриття вхідного и створення вихідного файлу */

in_fd = open(argv[l], 0_RDОNLY); /* відкриття вихідного файлу */

if (in_fd < 0) exit(2); /* якщо він не відкривається, вийти */

out_fd = creat(argv[2], 0UTPUT_M0DE); /* створення файлу-приймача */

if (out_fd < 0) exit(3); /* якщо він не створюється, вийти */

/* Цикл копіювання */

while (TRUE) {

rd_count = read(in_fd, buffer, BUF_SIZE); /* читання блоку даних */

if (rd_count < = 0) break; /* в кінці файлу або при помилці - вийти із циклу */

wt_count = write(out_fd, buffer, rd_count); /* записування даних */

if (wt_count < = 0) exit(4); /* при wt_count < = 0 виникає помилка */

}

/* Закриття файлів */

close(in_fd);

close(out_fd);

if (rd_count ==0) /* при останнім читанні помилки не виникло */

exit(0);

else

exit(5); /* помилка при останньому читанні */

}

Ця програма з іменем copyfile може бути викликана, наприклад, з терміналу: copyfile abc xyz щоб скопіювати файл abc в файл xyz. Якщо файл xyz вже існує, то він буде переписаний. Якщо цей файл не існує, то він буде створений. Програма повинна бути викликана з обов'язковим зазначенням двох аргументів, які є допустимими іменами файлів. Перший аргумент повинен бути ім'ям файлу-джерела, а другий - ім'ям вихідного файлу.
Завдяки чотирьом операторам #include на самому початку програми, в неї включається велика кількість визначень і прототипів функцій. Це потрібно для сумісності програми з відповідними міжнародними стандартами, але більше це нас цікавити не буде. Наступний рядок, згідно з вимогою стандарту ANSI С, містить прототип функції main, але зараз це нас теж не цікавить.

Перший оператор #define є макровизначенням рядка BUF_SIZE як макросу, який при компіляції замінюється в тексті програми числом 4096. Програма буде зчитувати і записувати дані блоками по 4096 байт. Створення таких констант і використання їх замість безпосередньої вказівки чисел в програмі вважається хорошим стилем програмування. При цьому програму не тільки зручніше читати, але і простіше змінювати в разі потреби. Другий оператор #define визначає коло користувачів, які можуть отримати доступ до вихідного файлу.

В основної програми, яка називається main, є два аргументи - argc і argv. Значення цих аргументів присвоюються операційною системою при виклику програми. У першому аргументі вказується кількість строкових значень, присутніх в командному рядку, що викликає програму, включаючи ім'я самої програми. Його значення має бути рівним трьом. Другий аргумент являє собою масив покажчиків на аргументи командного рядка. У наведеному вище прикладі, елементи цього масиву будуть містити покажчики на
наступні значення:

argv[0] = " copyfile"

argv[l] = " abc"

argv[2] = " xyz"

Через цей масив програма отримує доступ до своїх аргументів. У програмі оголошуються п'ять змінних. У перших двох змінних, in_fd і out_fd, будуть зберігатися дескриптори файлів, невеликі цілі числа, що повертаються при відкритті файлу. Наступні дві змінні, rd_count і wt_count, є байтовими лічильниками, що повертаються відповідно процедурами read і write. Остання змінна, buffer, використовується для зберігання зчитаних
та надання записуваних даних.

Перший виконуваний оператор перевіряє, чи не рівне значення лічильника аргументів argc трьом. Якщо лічильник argc не дорівнює трьом, програма завершується з кодом 1. Будь-який код завершення програми відмінний від 0 означає, що сталася помилка. Єдиний застосовуваний в цій програмі спосіб повідомлення про помилки - це код завершення програми. Остаточний варіант цієї програми виводив би повідомлення про помилки.

Потім програма намагається відкрити вхідний файл і створити вихідний файл. Якщо відкриття файлу проходить успішно, операційна система привласнює змінній in_fd невелике цілочисельне значення, щоб ідентифікувати файл. Це ціле число може включатися в наступні виклики, щоб система знала, який файл їм потрібен. Аналогічно цьому, якщо успішно створюється вихідний файл, змінній out_fd також присвоюється значення, що його ідентифікує. Другий аргумент процедури creat встановлює код захисту створюваного файлу. Якщо не вдається відкрити файл або не вдається його створити, то значення відповідного дескриптора файлу встановлюється в -1 і здійснюється вихід з програми з відповідним кодом помилки.

Потім настає черга циклу копіювання, який починається з спроби
зчитати в буфер buffer 4 Кбайт даних. Це робиться шляхом виклику бібліотечної процедури read, яка насправді здійснює системний виклик read. Перший параметр ідентифікує файл, другий вказує буфер, а третій повідомляє, скільки байтів потрібно зчитати. Значення, присвоєне rd_count, дає кількість реально зчитаних байтів. Зазвичай це значення дорівнює 4096, за винятком того випадку, коли у файлі залишиться менше байтів. При досягненні кінця файлу це значення дорівнюватиме 0. Як тільки значення rd_count стане нульовим або
негативним, копіювання не зможе продовжуватися, тому для припинення циклу (Який в іншому випадку був би нескінченним) виконується оператор break. Звернення до процедури write приводить до виводу вмісту буфера в вихідний файл. Перший параметр ідентифікує файл, другий вказує буфер, а третій повідомляє, скільки байтів потрібно записати, аналогічно параметрам процедури read. Слід зауважити, що лічильник байтів містить кількість реально
зчитаних байтів, а не значення BUF_SIZE. Це важливо, оскільки при останньому зчитуванні не буде повернуте число 4096, якщо тільки довжина файлу не виявиться кратній 4 Кбайт.

Після обробки всього файлу при першому ж виклику, що виходить за межі
файлу, в rd_count буде повернуто значення 0, яке і змусить програму вийти з циклу. Після цього обидва файли закриваються, і виконається вихід з програми зі статусом, що свідчить про її нормальне завершення.

Незважаючи на те що системні виклики Windows відрізняються від системних
викликів UNIX, загальна структура програми Windows, призначеної для
копіювання файлів і запускається з командного рядка, приблизно така ж, як
у програми, показаної в лістингу 1.1.

 

Завдань

Створити три файли з кодом на мові С. Два файли з вихідним кодом на мові С, перший повинен містити процедури, що реалізують задане варіантом завдання, а другий функцію main. Третій файл – заголовний (.h). Створити Make-файл, що міститиме правила для створення виконавчого файлу, а також правила clean, install і uninstall.

Варіанти завдань

  1. За допомогою системних викликів отримати інформацію про файлову систему, створити новий файл та записати в нього цю інформацію. Закрити файл та реалізувати обробку помилок, які можуть виникнути в ході роботи програми.
  2. За допомогою системних викликів отримати назву ядра та інформацію про нього, створити новий файл та записати в нього цю інформацію. Закрити файл та реалізувати обробку помилок, які можуть виникнути в ході роботи програми.
  3. За допомогою системних викликів відкрити файл, прочитати з нього перші 512 біт та вивести їх на екран, реалізувати запит на введення повідомлення в термінал та записати його у файл. Закрити файл та реалізувати обробку помилок, які можуть виникнути в ході роботи програми.
  4. За допомогою системних викликів відкрити файл, який вже містить довільну текстову інформацію та реалізувати запит на введення повідомлення в термінал, введене повідомлення дописати у середину файлу (в позицію, що відповідає середині файлу). Закрити файл та реалізувати обробку помилок, які можуть виникнути в ході роботи програми.
  5. За допомогою системних викликів відкрити файл, заборонити членам групи до якої належить власник та усім іншим користувачам право модифікувати документ. Права змінити, використовуючи шлях до файлу. Реалізувати запит на введення повідомлення в термінал, введене повідомлення дописати у файл. Закрити файл та реалізувати обробку помилок, які можуть виникнути в ході роботи програми.
  6. За допомогою системних викликів відкрити файл, заборонити членам групи до якої належить власник та усім іншим користувачам право модифікувати документ. Права змінити, використовуючи дескриптор файлу. Реалізувати запит на введення повідомлення в термінал, введене повідомлення дописати у файл. Закрити файл та реалізувати обробку помилок, які можуть виникнути в ході роботи програми.
  7. За допомогою системних викликів відкрити файл, перевірити права доступу до цього файлу, якщо файл дозволено читати та модифікувати членам групи до якої належить користувач то заборонити їх. Закрити файл та реалізувати обробку помилок, які можуть виникнути в ході роботи програми.
  8. За допомогою системних викликів створити дворівневу структуру директорій. В директорії 2-го рівня створити файли file1 і file2. Встановити на них наступні права доступу: file1: -rwsr-xr-x file2: -rwsr-s---. Закрити файл та реалізувати обробку помилок, які можуть виникнути в ході роботи програми.
  9. За допомогою системних викликів створити 2 файли, реалізувати запит на введення повідомлення в термінал, введене повідомлення записати у перший файл, встановити права доступу до цього файлу, а саме заборонити групі читати його, скопіювати вміст першого файлу в другий. Закрити файли та реалізувати обробку помилок, які можуть виникнути в ході роботи програми.
  10. За допомогою системних викликів у своїй домашній директорії створити дворівневу структуру директорій. У директорії другого рівня створити 2 файли та перемістити їх у директорію першого рівня. Видалити пусту папку. Реалізувати обробку помилок, які можуть виникнути в ході роботи програми.
  11. За допомогою системних викликів у своїй домашній директорії створити дворівневу структуру директорій. У директорії другого рівня створити 2 файли та виконати їх копіювання у директорію першого рівня. Видалити пусту папку. Реалізувати обробку помилок, які можуть виникнути в ході роботи програми.
  12. За допомогою системних викликів перевірити права доступу до реалізованого в 2-гій роботі bash-скрипту, та викликати його на виконання з середини c-програми. Реалізувати обробку помилок, які можуть виникнути в ході роботи програми.
  13. За допомогою системних викликів змонтувати гостьову файлову систему, створити в ній файл, записати в цей файл довільний текст, та розмонтувати гостьову файлову систему.
  14. Використовуючи системні виклики вивести повний вміст поточного каталогу. Використовуючи аргументи передані процедурі здійснити вивід файлів лише певного формату, а також вивід файлів з певними правами доступу (заздалегідь перевіривши за допомогою відповідного системного виклику права доступу до файлів). Реалізувати обробку помилок, які можуть виникнути в ході роботи програми.
  15. Використовуючи системні виклики вивести список активних процесів. Використовуючи аргументи передані процедурі здійснити вивід процесів одного користувача, процесів у певному діапазоні ідентифікаторів процесів. Реалізувати обробку помилок, які можуть виникнути в ході роботи програми.





© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.