СОДЕРЖАНИЕ
ВВЕДЕНИЕ
1 Анализзадания и разработка алгоритма
2 Теоретическиесведения
3 Листингпрограммы
4 Тестирование
ВЫВОДЫ
ЛИТЕРАТУРА
ВВЕДЕНИЕ
Целью выполнения работы является закреплениезнаний умений и навыков в области взаимодействия модулей, использованиясистемных вызовов и библиотечных функций управления процессами и файламисовременных операционных систем для создания системных и пользовательскихпрограмм, процедур и функций на примере ОС семейства UNIX/Linux. В ходевыполнения работы студенту необходимо продемонстрировать знания функций,алгоритмов, механизмов управления процессами, разделяемыми ресурсами, файлами,вводом-выводом.
Процесс — понятие, которое определяетсяпо-разному. Это может быть — “упорядоченный набор команд и принадлежащих емуресурсов”. С точки зрения ОС Unix процесс — это объект, зарегистрированный вспециальной таблице процессов.
Телом процесса называется набор команд и данных,которыми оперирует процесс.
Контекст процесса — атрибут, который присутствуетпрактически во всех ОС, в разных ОС он может называться по-разному. Контекстывсех процессов размещаются в адресном пространстве ОС и содержат оперативнуюинформацию о состоянии процесса и текущую информацию, связанную с процессом иего запуском.
1 АНАЛИЗ ЗАДАНИЯ ИРАЗРАБОТКА АЛГОРИТМА
По заданиюсогласно варианта по списку необходимо организовать копирование содержимого изФайла 1 в остальные файлы (1->2, 1->3, 1->4).
Основныепринципы по которым будет создаваться программа:
· Будутсозданы 4-е процесса, а именно 1-ый процесс породит 2-ый процесс, 1-ый процесс,в свою очередь породит 3-ий процесс, 1-ый процесс породит 4-тый процесс.
· Каждыйпроцесс будет иметь файл с соответствующими именами – file1, file2, file3,file4.
· Процессыбудут обмениваться через разделяемую память и временный файл.
· Обменсодержимым файлов будет происходить по сигналу, семафорам и обмену сообщениями.
Процессы Process1 и Process4 обмениваются пользовательскимисигналами, по которым выполняется запись процессом Process1 во временный файл Tempfile, после чего Process4 считывает из негоданные, удаляет временный файл, затем записывает информацию в File4, ждетзавершения обмена между процессами Process2, Process3, закрывает разделяемуюпамять и уничтожает всю группу процессов.
Процессы Process1 и Process2 взаимодействуют спомощью семафоров. Process1 записывает в разделяемую память содержимое файлаFile1, после этого по семафору Process2 считывает из памятиданные и пишет в File2.
Процессы Process2 иProcess3 взаимодействуют с помощьюочереди сообщений. Когда данные уже записаны процессом Process2 в File2, онотсылает сообщение своему потомку, после чего Process3 считывает из разделяемойпамяти данные, пишет в свой файл File3, отсылает сообщение назад изавершается, после чего закрывается и его родительProcess2.
/>
Рис.1 Схемавзаимодействия процессов
2 ТЕОРЕТИЧЕСКИЕСВЕДЕНИЯ
Сиспользованием функций в языке СИ связаны три понятия — определение функции(описание действий, выполняемых функцией), объявление функции (задание формыобращения к функции) и вызов функции.
Определениефункции задает тип возвращаемого значения, имя функции, типы и число формальныхпараметров, а также объявления переменных и операторы, называемые теломфункции, и определяющие действие функции. В определении функции также можетбыть задан класс памяти.
Функцияfork:
intfork ( )
Вызовfork приводит к созданию нового процесса (порожденного процесса) — точной копиипроцесса, сделавшего вызов (родительского процесса). Точнее, порожденныйпроцесс наследует у родительского процесса следующие характеристики:
· Окружение.
· Флаг «закрыть при выполнении вызова exec»
· Способы обработки сигналов (то есть SIG_DFL, SIG_IGN, SIG_HOLD,адреса функций обработки сигналов).
· Разрешение переустанавливать действующий идентификаторпользователя.
· Разрешение переустанавливать действующий идентификатор группы.
· Состояние профилирования (включено/выключено).
· Значение поправки к приоритету.
· Все присоединенные разделяемые сегменты памяти.
· Идентификатор группы процессов.
· Идентификатор группы терминала.
· Текущий рабочий каталог.
· Корневой каталог.
· Маска режима создания файлов.
· Ограничение на размер файла.
Порожденныйпроцесс отличается от родительского процесса следующим:
· Порожденный процесс имеет свой уникальный идентификатор процесса.
· Порожденный процесс имеет иной идентификатор родительскогопроцесса, равный идентификатору процесса, его породившего.
· Порожденный процесс имеет свои собственные копии родительскихдескрипторов файлов. Каждый дескриптор файла порожденного процесса разделяет ссоответствующим родительским дескриптором файла общий указатель текущей позициив файле.
· Все semadj значения сбрасываются.
· Порожденный процесс не наследует у родительского процессапризнаков удержания в памяти сегмента команд, данных или всего процессацеликом.
· Обнуляются счетчики времени, потраченного для обслуживания этогопроцесса (tms_utime, tms_stime, tms_cutime, tms_cstime). Отменяется запрос кбудильнику.
3 ЛИСТИНГ ПРОГРАММЫ
Программасостоит из главного модуля rgr.c:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SHMKEY5
#define SEMKEY5
#define K32
#define Count4
#define InitVal {1,0,0,0}
#define MSGKEY5
#define InitT3
voidcreat_mem(void);
voidcreat_sem(void);
voidprss1(void);
voidprss2(void);
voidprss3(void);
voidprss4(void);
intpid1; int pid2; int pid3; int pid4; int pid; int ppid;
intfd; int st;
externint p14(int), p41(int);
//mem
intshmid;
int*pint;
char*addr;
//sem
intsemid;
shortinitarray[Count] = InitVal;
structsembuf p, v;
//message:
intprnum;
intmsgid;
longnextT;
struct {
longmtype;
intData;
}Message;
intmain(void)
{
remove(«file2»);
remove(«file3»);
remove(«file4»);
creat_mem();
creat_sem();
pid1= getpid();
pid= fork();
if(!pid) prss2();
elseprss1();
sleep(2);
wait(&st);
}
voidcreat_mem(void)
{
printf("---func creat_mem(): memory creating: %dbytes — pid=%d\n", K, getpid());
shmid= shmget(SHMKEY, 1*K, 0777|IPC_CREAT);
addr= shmat(shmid, 0, 0);
pint= (int *) addr;
}
voidcreat_sem(void)
{
printf("---func creat_sem(): semaphor creating: — pid=%d\n", getpid());
semid= semget(SEMKEY, Count, 0777|IPC_CREAT);
semctl(semid,Count, SETALL, initarray);
p.sem_op= -1;
p.sem_flg= SEM_UNDO;
v.sem_op= 1;
v.sem_flg= SEM_UNDO;
}
voidcreat_mesg(void)
{
msgid= msgget(MSGKEY, 0666|IPC_CREAT);
msgsnd(msgid,(struct msgbuf *) &Message, 8, 0);
}
voidprss1(void)
{
inti;
charbuf[32] = " ";
prnum= 1;
p.sem_num= 0;
v.sem_num= 1;
ppid= getppid();
printf("=I= prss%d, pid = %d, parent: %d\n", prnum, pid1, ppid);
pid= fork();
if(!pid) prss4();
else
{
fd= open(«file1», O_RDONLY);
read(fd,buf,strlen(buf));
close(fd);
printf(«I:reading from FILE1:\t%s\n»,buf);
signal(SIGUSR2,p41);
sleep(1);//ojidaniepriema signala ot prssa4
kill(pid1+2,SIGUSR1);
printf("==================prss1: writing to memory\n");
for(i= 0; i
semop(semid,&p, 1);
semop(semid,&v, 1);
sleep(2);
wait(&st);
wait(&st);
printf("=I= __eto konec prssa%d\n", prnum);
}
}
voidprss2(void)
{
inti;
charbuf_2[32]=" ";
prnum= 2;
p.sem_num= 1;
pid2= getpid();
ppid= getppid();
printf("=II= prss%d, pid = %d, parent: %d\n", prnum, pid2, ppid);
creat(«file2»,fd);
pid= fork();
if(!pid) prss3();
else
{
semop(semid,&p, 1);
printf("==================prss%d: file2 editing /Semaphor/\n", prnum);
fd= open(«file2», O_WRONLY);
for(i= 0; i
write(fd,buf_2,strlen(buf_2));
printf(«II:writing to FILE2:\t%s\n»,buf_2);
printf("---func creat_mesg(): message creating: — pid=%d\n", pid2);
Message.mtype= InitT;
Message.Data=3;
creat_mesg();
printf("=II= __eto konec prssa%d\n", prnum);
fclose(fd);
}
}
voidprss3(void)
{
inti;
charbuf_3[32]=" ";
prnum= 3;
pid3= getpid();
ppid= getppid();
printf("=III= prss%d, pid = %d, parent: %d\n", prnum, pid3, ppid);
creat(«file3»,fd);
msgrcv(msgid,(struct msgbuf *) (&Message), 8, prnum, 0);
if(Message.Data==3)
{
printf("==================prss%d: file3 editing /Message/\n", prnum);
fd= open(«file3», O_WRONLY);
for(i= 0; i
write(fd,buf_3,strlen(buf_3));
printf(«III:writing to FILE3:\t%s\n»,buf_3);
printf("=III= __eto konec prssa%d\n", prnum);
fclose(fd);
}
}
voidprss4(void)
{
inti;
prnum= 4;
pid4= getpid();
ppid= getppid();
printf("=IV= prss%d, pid = %d, parent: %d\n", prnum, pid4, ppid);
creat(«file4»,fd);
signal(SIGUSR1,p14);
kill(pid1,SIGUSR2);
sleep(1);
printf("=IV= __eto konec prssa%d\n", prnum);
shmctl(shmid,IPC_RMID,0);
printf("==================prss4: memory closed\n");
kill(0,SIGKILL);
}
intp14(int signum) //2-oj sig
{
chartemp_buf4[32]=" ";
signal(SIGUSR1,p14);
printf("***SIGUSR1***: prss 4 (%d) has got a signal from prss 1 (%d)\n",pid4,pid1);
fd= open(«temp_file», O_RDONLY);
read(fd,temp_buf4,strlen(temp_buf4));
close(fd);
creat(«file4»,fd);
printf("**SIGUSR1* *: writing from temp_file to file4\n");
fd= open(«file4», O_WRONLY);
write(fd,temp_buf4,strlen(temp_buf4));
close(fd);
printf(«IV:writing to FILE4:\t%s\n»,temp_buf4);
remove(«temp_file»);
printf("**SIGUSR1* *: temp_file was removed\n");
printf("***SIGUSR1***: end\n");
}
intp41(int signum) //1-ij sig
{
chartemp_buf1[32]=" ";
signal(SIGUSR2,p41);
printf("***SIGUSR2***prss 1 (%d) has got a signal from prss 4 (%d)\n",pid1,pid1+2);
fd= open(«file1», O_RDONLY);
read(fd,temp_buf1,strlen(temp_buf1));
close(fd);
creat(«temp_file»,fd);
printf("**SIGUSR2* *: temp_file was created\n");
fd= open(«temp_file», O_WRONLY);
write(fd,temp_buf1,strlen(temp_buf1));
close(fd);
printf("***SIGUSR2***: end\n");
}
4 ТЕСТИРОВАНИЕ
Результатвыполнения программы в консоли:
yuna@YunieHost:/media/8_Gb_hard_ONPU/LINUX/rgr28march$ ./rgr
— func creat_mem(): memory creating: 32bytes — pid=6798
— func creat_sem(): semaphor creating: — pid=6798
=II=prss2, pid = 6799, parent: 6798
=I=prss1, pid = 6798, parent: 6655
=III=prss3, pid = 6801, parent: 6799
=IV=prss4, pid = 6800, parent: 6798
I:reading from FILE1: >
***SIGUSR2***prss 1 (6798) has got a signal from prss 4 (6800)
**SIGUSR2* *: temp_file was created
***SIGUSR2***: end
==================prss1: writing to memory
==================prss2: file2 editing /Semaphor/
II:writing to FILE2: >
— func creat_mesg(): message creating: — pid=6799
=II=__eto konec prssa2
***SIGUSR1***: prss 4 (6800) has got a signal from prss 1 (6798)
==================prss3: file3 editing /Message/
III:writing to FILE3: >
=III=__eto konec prssa3
**SIGUSR1* *: writing from temp_file to file4
IV:writing to FILE4: >
**SIGUSR1* *: temp_file was removed
***SIGUSR1***: end
=IV=__eto konec prssa4
==================prss4: memory closed
Killed
/>
Рис.2 Результат работыпрограммы (содержимое из file1 было скопировано в остальные файлы)
Следовательно,программа работает корректно и поставленная на данную расчетно-графическуюработу задача была решена.
ВЫВОДЫ
В даннойработе частично описана структура системы UNIX, взаимоотношения междупроцессами, выполняющимися в режиме задачи и в режиме ядра. Процессывыполняются в режиме задачи или в режиме ядра, в котором они пользуютсяуслугами системы благодаря наличию набора обращений к операционной системе.
Архитектурасистемы поддерживает такой стиль программирования, при котором из небольшихпрограмм, выполняющих только отдельные функции, но хорошо, составляются болеесложные программы, использующие механизм каналов и переназначение ввода-вывода.
Обращения коперационной системе позволяют процессам производить операции, которые иначе невыполняются. В дополнение к обработке подобных обращений ядро операционнойсистемы осуществляет общие учетные операции, управляет планированием процессов,распределением памяти и защитой процессов в оперативной памяти, обслуживаетпрерывания, управляет файлами и устройствами и обрабатывает особые ситуации, возникающиев системе.
В функцииядра системы UNIX намеренно не включены многие функции, являющиеся частьюдругих операционных систем, поскольку набор обращений к системе позволяетпроцессам выполнять все необходимые операции на пользовательском уровне.
ЛИТЕРАТУРА
1. Дж.Такет (мл.), С.Барнет. Использование Linux/ Специальное издание.: 5-е изд.:Пер. с англ.: Уч.пос. – М.: Издательский дом «Вильямс», 2000. – 784 с.
2. Максимальнаязащита Linux. Искусство настройки.: Пер. с англ./ под.ред. Дж.Рея – СПб.: ООО«ДиаСофтЮП», 2002. – 752 с.
3. БраунС. Операционная система UNIX — М.: Мир, 1986 — 463 с.