Циклический обмен содержимым файлов

Содержание
Введение
1.   Анализзадания и разработка алгоритма
2.   Функции,используемые в работе
3.   Листингпрограммы
4.   Тестирование
Выводы
Литература

Введение
Целью выполнения работы является закрепление знаний умений инавыков в области взаимодействия модулей, использования системных вызовов ибиблиотечных функций управления процессами и файлами современных операционныхсистем для создания системных и пользовательских программ, процедур и функцийна примере ОС семейства UNIX/Linux. В ходе выполнения работы студентунеобходимо продемонстрировать знания функций, алгоритмов, механизмов управленияпроцессами, разделяемыми ресурсами, файлами, вводом-выводом.
Файловая система Unix, это иерархическая, многопользовательскаяфайловая система. Ее можно представить в виде дерева. В корне дерева находится“корневой каталог”, узлами, отличными от листьев дерева являются каталоги.Листьями могут являться: файлы (в традиционном понимании — именованные наборыданных), пустые каталоги (каталоги, с которыми не ассоциировано ни одногофайла). В системе определено понятие имени файла — это имя, котороеассоциировано с набором данных в рамках каталога, которому принадлежит этотфайл.
Процесс — понятие, которое определяется по-разному. Это может быть— “упорядоченный набор команд и принадлежащих ему ресурсов”. С точки зрения ОСUnix процесс — это объект, зарегистрированный в специальной таблице процессов.
Телом процесса называется набор команд и данных, которымиоперирует процесс.
Контекст процесса — атрибут, который присутствует практически вовсех ОС, в разных ОС он может называться по-разному. Контексты всех процессовразмещаются в адресном пространстве ОС и содержат оперативную информацию осостоянии процесса и текущую информацию, связанную с процессом и его запуском.

1. Анализзадания и разработка алгоритма
По заданиюсогласно варианта 5 по списку необходимо организовать циклический обменсодержимым всех файлов (1->2->3->4->1).
Рассмотримосновные принципы по которым будет создаваться программа:
·         Будутсозданы 4-е процесса, а именно 4-ый процесс породит 1-ый процесс, 1-ый процесс,в свою очередь породит 2-ой процесс, 2-ой процесс породит 3-тий процесс.
·         Каждыйпроцесс будет иметь файл с соответствующими именами – 1, 2, 3, 4.
·         Процессымежду собой будут обмениваться через разделяемую память и временный (буферный)файл.
·         Обменсодержимым файлов будет происходить циклически.
Общая схемавзаимодействия процессов показана на рис. 1.
/>
Рис.1 Схема взаимодействияпроцессов.
 

2. Функции,используемые в работе
Директива#include включает в текст программы содержимое указанного файла. Эта директиваимеет две формы:
#include«имя файла»
#include
Имя файладолжно соответствовать соглашениям операционной системы и может состоять либотолько из имени файла, либо из имени файла с предшествующим ему маршрутом. Еслиимя файла указано в кавычках, то поиск файла осуществляется в соответствии сзаданным маршрутом, а при его отсутствии в текущем каталоге. Если имя файлазадано в угловых скобках, то поиск файла производится в стандартных директорияхоперационной системы, задаваемых командой PATH.
Директива#include может быть вложенной, т.е. во включаемом файле тоже может содержатьсядиректива #include, которая замещается после включения файла, содержащего этудирективу.
Директива#include широко используется для включения в программу так называемыхзаголовочных файлов, содержащих прототипы библиотечных функций, и поэтомубольшинство программ на СИ начинаются с этой директивы.
При написаниипрограммы согласно заданию, будем использовать функции различного вида.
Функция — этосовокупность объявлений и операторов, обычно предназначенная для решенияопределенной задачи. Каждая функция должна иметь имя, которое используется дляее объявления, определения и вызова. В любой программе на СИ должна бытьфункция с именем main (главная функция), именно с этой функции, в каком быместе программы она не находилась, начинается выполнение программы.
При вызовефункции ей при помощи аргументов (формальных параметров) могут быть переданынекоторые значения (фактические параметры), используемые во время выполненияфункции. Функция может возвращать некоторое (одно!) значение. Это возвращаемоезначение и есть результат выполнения функции, который при выполнении программыподставляется в точку вызова функции, где бы этот вызов ни встретился.Допускается также использовать функции не имеющие аргументов и функции невозвращающие никаких значений. Действие таких функций может состоять, например,в изменении значений некоторых переменных, выводе на печать некоторых текстов ит.п…
Сиспользованием функций в языке СИ связаны три понятия — определение функции(описание действий, выполняемых функцией), объявление функции (задание формыобращения к функции) и вызов функции.
Определениефункции задает тип возвращаемого значения, имя функции, типы и число формальныхпараметров, а также объявления переменных и операторы, называемые теломфункции, и определяющие действие функции. В определении функции также можетбыть задан класс памяти.
 
Функцияfork:
int fork ()
Вызов forkприводит к созданию нового процесса (порожденного процесса) — точной копиипроцесса, сделавшего вызов (родительского процесса). Точнее, порожденныйпроцесс наследует у родительского процесса следующие характеристики:
·       Окружение.
·       Флаг«закрыть при выполнении вызова exec»
·       Способыобработки сигналов (то есть SIG_DFL, SIG_IGN, SIG_HOLD, адреса функцийобработки сигналов).
·       Разрешениепереустанавливать действующий идентификатор пользователя.
·       Разрешениепереустанавливать действующий идентификатор группы.
·       Состояниепрофилирования (включено/выключено).
·       Значениепоправки к приоритету.
·       Всеприсоединенные разделяемые сегменты памяти.
·       Идентификаторгруппы процессов.
·       Идентификаторгруппы терминала.
·       Текущийрабочий каталог.
·       Корневойкаталог.
·       Маскарежима создания файлов.
·       Ограничениена размер файла.
Порожденныйпроцесс отличается от родительского процесса следующим:
·       Порожденныйпроцесс имеет свой уникальный идентификатор процесса.
·       Порожденныйпроцесс имеет иной идентификатор родительского процесса, равный идентификаторупроцесса, его породившего.
·       Порожденныйпроцесс имеет свои собственные копии родительских дескрипторов файлов. Каждыйдескриптор файла порожденного процесса разделяет с соответствующим родительскимдескриптором файла общий указатель текущей позиции в файле.
·       Всеsemadj значения сбрасываются.
·       Порожденныйпроцесс не наследует у родительского процесса признаков удержания в памятисегмента команд, данных или всего процесса целиком.
·       Обнуляютсясчетчики времени, потраченного для обслуживания этого процесса (tms_utime,tms_stime, tms_cutime, tms_cstime). Отменяется запрос к будильнику.
Системныйвызов fork завершается неудачей и новый процесс не порождается, если выполненохотя бы одно из следующих условий:
·       Создатьпроцесс запрещает системное ограничение на общее количество процессов.
·       Создатьпроцесс запрещает системное ограничение на количество процессов у одного пользователя.
·       Общееколичество системной памяти, предоставленной для физического ввода/вывода,временно оказалось недостаточным.
Функцияfopen:
#include
FILE *fopen(filename, type)
char*filename, *type;
Функция fopenоткрывает файл с именем filename, ассоциирует с ним поток и возвращаетуказатель на структуру типа FILE, соответствующую этому потоку.
Аргументfilename является указателем на цепочку символов — имя открываемого файла.
Аргумент type- это указатель на цепочку символов, которая может принимать одно из следующихзначений: r    Открыть на чтение.
w       Опустошитьили создать для записи.
a        Добавлять;открыть для записи в конец файла или создать для записи.
r+      Открытьдля изменения (чтения и записи).
w+    Опустошитьили создать для изменения.
a+     Добавлять;открыть или создать для изменения в конце файла.
Функцияfclose:
#include
int fclose(stream)
FILE *stream;
Функцияfclose записывает в файл всю информацию, буферизованную в потоке stream(выталкивает буфера), и закрывает этот поток.
Функцияfclose вызывается автоматически для всех открытых файлов при выполнениисистемного вызова exit(2).
Функцияfflush выталкивает буфера потока stream в файл. Поток остается открытым.
Функцияfputc:
#include
int fputc (c,stream)
char c;
FILE *stream;
Запись впоток символа или машинного слова. Макрос putc записывает символ c в поток вывода stream (впозицию, задаваемую указателем файла, если он определен). Макрос putchar (c)определяется как putc (c, stdout).
Функция fputcвыполняет те же действия, что и макрос putc; она работает медленнее, чем putc,но занимает меньше пространства на каждое использование. Кроме того, функциюможно передавать в качестве аргумента.
Функцияfgetc:
#include
int fgetc(stream)
FILE *stream;
Считываниесимвола или слова из потока. Макрос getc выдает в виде целого числа следующийсимвол (байт) из указанного потока ввода stream и перемещает текущую позицию(если она определена) на один символ вперед. Макрос getchar эквивалентен getc(stdin).
Функция fgetcдействует аналогично getc, но реализована именно как функция, а не макрос.Функция fgetc выполняется медленнее, чем getc, но обращение к ней требуетменьше памяти, и ее имя может передаваться в качестве аргумента функции.
Функцияfeof:
#include
int feof(stream)
FILE *stream;
Опроссостояния потока. Функция feof возвращает ненулевое значение, если ранее причтении из потока steram фиксировался конец файла; в противном случае результатравен 0.
Функцияmalloc:
#include
char *malloc(size)
unsignedsize;
Быстроевыделение оперативной памяти.
Функцииmalloc и free предоставляют простой универсальный механизм выделения иосвобождения памяти, работающий значительно быстрее пакета malloc(3C).Описываемые функции находятся в библиотеке malloc и подключаются прииспользовании опции -lmalloc команд cc(1) и ld(1).
Функцияmalloc возвращает указатель на блок размером не менее size байт, который можноиспользовать в произвольных целях.
Аргументомфункции free является указатель на блок, предварительно выделенный с помощьюmalloc; после выполнения free блок может быть выделен вновь, а хранящаяся в неминформация теряется.
В случаевыхода за границы блока, выделенного функцией malloc, а также при вызовефункции free с аргументом, не являвшимся результатом malloc, эффект будетнепредсказуем.
Каждая изфункций выделения возвращает указатель на область памяти, подходящую (послевозможного преобразования типа указателя) для хранения произвольных данных.
Структура определенаво включаемом файле .
 
3. Листингпрограммы
Программасостоит из главного модуля rgr.c, который использует подключаемый файл сфункцией обмена file_obmen.h.
 
Файлrgr.c:
#include
#include
#include
#include«file_obmen.h»
int main()
{
char *a4 =«4», *a3 = «3», *a2 = «2», *a1 = «1»;
int p1, p2,p3, p4;
printf(«Cozdanie vseh processov:\n»);
printf(“\n”);
printf(«Cozdanie processa 4 \n»);
printf(«Porozhdenie processa 1 processom 4\n»);
printf(«Porozhdenie processa 2 processom 1\n»);
printf(«Porozhdenie processa 3 processom 2\n»);
p4 = fork();
if(p4)
{
p1 = fork();
exit(0);
}
if(p1)
{
file_obmen(a4,a3);
printf(«Writefile 4 >>> file 3\n»);
p2 = fork();
}
sleep(1);
if(p2)
{
file_obmen(a3,a2);
printf(«Writefile 3 >>> file 2\n»);
p3 = fork();
exit(0);
}
sleep(1);
if(p3)
{
file_obmen(a2,a1);
printf(«Writefile 2 >>> file 1\n»);
printf(“\n”);
printf(«Obmen zachonchen!\n»);
exit(0);
}
sleep(1);
exit(0);
}
Файлfile_obmen.h:
voidfile_obmen(char *a4, char *a3)
{
FILE *f[3];
char*c=(char*)malloc(sizeof(char));
int p1, p2;
f[1] =fopen(a3, «rb»);
f[0] =fopen(a4, «rb»);
f[2] =fopen(«buf», «wb»);
while(!feof(f[0]))
{
c[0] =fgetc(f[0]);
fputc(c[0],f[2]);
}
fclose(f[0]);
f[0] =fopen(a4, «wb»);
while(!feof(f[1]))
{
c[0] =fgetc(f[1]);
fputc(c[0],f[0]);
}
fclose(f[0]);
fclose(f[2]);
f[2] =fopen(«buf», «rb»);
f[1] =fopen(a3, «wb»);
while(!feof(f[2]))
{
c[0] =fgetc(f[2]);
fputc(c[0],f[1]);
}
fclose(f[2]);
fclose(f[1]);
}
4. Тестирование
Результатвыполнения программы в консоле:
/>
Содержимоефайлов при первом проходе:
/>
/>
/>
/>

Содержимоефайлов при втором проходе:
/>
/>
/>
/>
Программапроверена и работает корректно.
 

Выводы
В даннойработе частично описана структура системы UNIX, взаимоотношения междупроцессами, выполняющимися в режиме задачи и в режиме ядра. Процессывыполняются в режиме задачи или в режиме ядра, в котором они пользуютсяуслугами системы благодаря наличию набора обращений к операционной системе.Архитектура системы поддерживает такой стиль программирования, при котором изнебольших программ, выполняющих только отдельные функции, но хорошо,составляются более сложные программы, использующие механизм каналов ипереназначение ввода-вывода.
Обращения коперационной системе позволяют процессам производить операции, которые иначе невыполняются. В дополнение к обработке подобных обращений ядро операционнойсистемы осуществляет общие учетные операции, управляет планированием процессов,распределением памяти и защитой процессов в оперативной памяти, обслуживаетпрерывания, управляет файлами и устройствами и обрабатывает особые ситуации,возникающие в системе. В функции ядра системы UNIX намеренно не включены многиефункции, являющиеся частью других операционных систем, поскольку наборобращений к системе позволяет процессам выполнять все необходимые операции напользовательском уровне.

Литература
1.   Дж.Такет (мл.), С.Барнет. Использование Linux/ Специальное издание.: 5-е изд.:Пер. с англ.: Уч.пос. – М.: Издательский дом «Вильямс», 2000. – 784 с.
2.   Максимальнаязащита Linux. Искусство настройки.: Пер. с англ./ под.ред. Дж.Рея – СПб.: ООО«ДиаСофтЮП», 2002. – 752 с.
3.   БраунС. Операционная система UNIX — М.: Мир, 1986 — 463 с.