Главная Учебники - Разные Лекции (разные) - часть 33
СОДЕРЖАНИЕ
ВВЕДЕНИЕ 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. · Процессы будут обмениваться через разделяемую память и временный файл. · Обмен содержимым файлов будет происходить по сигналу, семафорам и обмену сообщениями. Процессы Process
1
и Process
4
обмениваются пользовательскими сигналами, по которым выполняется запись процессом Process
1
во временный файл Temp
f
ile
, после чего Process
4
считывает из него данные, удаляет временный файл, затем записывает информацию в File4,
ждет завершения обмена между процессами Process
2,
Process
3,
закрывает разделяемую память и уничтожает всю группу процессов. Процессы Process
1
и Process
2
взаимодействуют с помощью семафоров. Process
1
записывает в разделяемую память содержимое файла File1
, после этого по семафору Process
2
считывает из памяти данные и пишет в File2
. Процессы Process
2
иProcess
3
взаимодействуют с помощью очереди сообщений. Когда данные уже записаны процессом Process
2
в File2
, он отсылает сообщение своему потомку, после чего Process
3
считывает из разделяемой памяти данные, пишет в свой файл File3,
отсылает сообщение назад и завершается,
после чего закрывается и его родительProcess
2
.
Рис.1 Схема взаимодействия процессов
2
ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ
С использованием функций в языке СИ связаны три понятия - определение функции (описание действий, выполняемых функцией), объявление функции (задание формы обращения к функции) и вызов функции. Определение функции задает тип возвращаемого значения, имя функции, типы и число формальных параметров, а также объявления переменных и операторы, называемые телом функции, и определяющие действие функции. В определении функции также может быть задан класс памяти. Функция fork: int fork ( ) Вызов fork приводит к созданию нового процесса (порожденного процесса) - точной копии процесса, сделавшего вызов (родительского процесса). Точнее, порожденный процесс наследует у родительского процесса следующие характеристики: · Окружение. · Флаг "закрыть при выполнении вызова exec" · Способы обработки сигналов (то есть SIG_DFL, SIG_IGN, SIG_HOLD, адреса функций обработки сигналов). · Разрешение переустанавливать действующий идентификатор пользователя. · Разрешение переустанавливать действующий идентификатор группы. · Состояние профилирования (включено/выключено). · Значение поправки к приоритету. · Все присоединенные разделяемые сегменты памяти. · Идентификатор группы процессов. · Идентификатор группы терминала. · Текущий рабочий каталог. · Корневой каталог. · Маска режима создания файлов. · Ограничение на размер файла. Порожденный процесс отличается от родительского процесса следующим: · Порожденный процесс имеет свой уникальный идентификатор процесса. · Порожденный процесс имеет иной идентификатор родительского процесса, равный идентификатору процесса, его породившего. · Порожденный процесс имеет свои собственные копии родительских дескрипторов файлов. Каждый дескриптор файла порожденного процесса разделяет с соответствующим родительским дескриптором файла общий указатель текущей позиции в файле. · Все semadj значения сбрасываются. · Порожденный процесс не наследует у родительского процесса признаков удержания в памяти сегмента команд, данных или всего процесса целиком. · Обнуляются счетчики времени, потраченного для обслуживания этого процесса (tms_utime, tms_stime, tms_cutime, tms_cstime). Отменяется запрос к будильнику. 3 ЛИСТИНГ ПРОГРАММЫ
Программа состоит из главного модуля rgr.c: #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/sem.h> #include <unistd.h> #include <signal.h> #include <fcntl.h> #include <stdio.h> #include <errno.h> #define SHMKEY 5 #define SEMKEY 5 #define K 32 #define Count 4 #define InitVal {1,0,0,0} #define MSGKEY 5 #define InitT 3 void creat_mem(void); void creat_sem(void); void prss1(void); void prss2(void); void prss3(void); void prss4(void); int pid1; int pid2; int pid3; int pid4; int pid; int ppid; int fd; int st; extern int p14(int), p41(int); //mem int shmid; int *pint; char *addr; //sem int semid; short initarray[Count] = InitVal; struct sembuf p, v; //message: int prnum; int msgid; long nextT; struct { long mtype; int Data; } Message; int main(void) { remove("file2"); remove("file3"); remove("file4"); creat_mem(); creat_sem(); pid1 = getpid(); pid = fork(); if (!pid) prss2(); else prss1(); sleep(2); wait(&st); } void creat_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; } void creat_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; } void creat_mesg(void) { msgid = msgget(MSGKEY, 0666|IPC_CREAT); msgsnd(msgid, (struct msgbuf *) &Message, 8, 0); } void prss1(void) { int i; char buf[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);//ojidanie priema signala ot prssa4 kill(pid1+2,SIGUSR1); printf("================== prss1: writing to memory\n"); for(i = 0; i <= 31; ++i) pint[i] = buf[i]; semop(semid, &p, 1); semop(semid, &v, 1); sleep(2); wait(&st); wait(&st); printf(" =I= __eto konec prssa%d\n", prnum); } } void prss2(void) { int i; char buf_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 <= 31; ++i) buf_2[i] = pint[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); } } void prss3(void) { int i; char buf_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 <= 31; ++i) buf_3[i] = pint[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); } } void prss4(void) { int i; 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); } int p14(int signum) //2-oj sig { char temp_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"); } int p41(int signum) //1-ij sig { char temp_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/rgr 28march$ ./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: << RGR sPO by yuna 18.05.2008 >> ***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: << RGR sPO by yuna 18.05.2008 >> --- 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: << RGR sPO by yuna 18.05.2008 >> =III= __eto konec prssa3 * *SIGUSR1* * : writing from temp_file to file4 IV: writing to FILE4: << RGR sPO by yuna 18.05.2008 >> * *SIGUSR1* * : temp_file was removed ***SIGUSR1*** : end =IV= __eto konec prssa4 ================== prss4: memory closed Killed
Рис.2 Результат работы программы (содержимое из
file
1 было скопировано в остальные файлы)
Следовательно, программа работает корректно и поставленная на данную расчетно-графическую работу задача была решена. ВЫВОДЫ
В данной работе частично описана структура системы UNIX, взаимоотношения между процессами, выполняющимися в режиме задачи и в режиме ядра. Процессы выполняются в режиме задачи или в режиме ядра, в котором они пользуются услугами системы благодаря наличию набора обращений к операционной системе. Архитектура системы поддерживает такой стиль программирования, при котором из небольших программ, выполняющих только отдельные функции, но хорошо, составляются более сложные программы, использующие механизм каналов и переназначение ввода-вывода. Обращения к операционной системе позволяют процессам производить операции, которые иначе не выполняются. В дополнение к обработке подобных обращений ядро операционной системы осуществляет общие учетные операции, управляет планированием процессов, распределением памяти и защитой процессов в оперативной памяти, обслуживает прерывания, управляет файлами и устройствами и обрабатывает особые ситуации, возникающие в системе. В функции ядра системы UNIX намеренно не включены многие функции, являющиеся частью других операционных систем, поскольку набор обращений к системе позволяет процессам выполнять все необходимые операции на пользовательском уровне. ЛИТЕРАТУРА
1. Дж. Такет (мл.), С.Барнет. Использование Linux/ Специальное издание.: 5-е изд.: Пер. с англ.: Уч.пос. – М.: Издательский дом «Вильямс», 2000. – 784 с. 2. Максимальная защита Linux. Искусство настройки.: Пер. с англ./ под.ред. Дж.Рея – СПб.: ООО «ДиаСофтЮП», 2002. – 752 с. 3. Браун С. Операционная система UNIX - М.: Мир, 1986 - 463 с.
|