Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Системное программирование часть1

.doc
Скачиваний:
95
Добавлен:
01.04.2014
Размер:
55.3 Кб
Скачать

Министерство образования Республики Беларусь

Учреждение образования Белорусский государственный университет информатики и радиоэлектроники

Факультет непрерывного и дистанционного обучения

Специальность ПОИТ

ОТЧЕТ

По контрольной работе №1

по курсу ОСиСП

«Система команд и файловая структура ОС UNIX/LINUX»

Выполнил: студент группы

Проверил: Алексеев И.Г.

Минск 2010

Задание:

Создать дерево процессов согласно варианта индивидуального задания. Номер варианта индивидуального задания в таблице 1 равен числу букв N1 Вашей фамилии (по паспорту) умноженному на число букв N2 Вашего имени по паспорту умноженному на число букв N3 Вашего отчества по модулю 16:

(N1*N2*N3) mod 16 =(8*8*9)mod16 =0

Номер варианта в таблице 2 равен:

(N1*N3) mod 14 = (8*9) mod 14 =2

кр1 Процессы непрерывно обмениваются сигналами согласно табл. 2 . Запись в таблице 1 вида: 1->(2,3,4,5) означает, что исходный процесс 0 создаёт дочерний процесс 1, который, в свою очередь, создаёт дочерние процессы 2,3,4,5. Запись в таблице 2 вида: 1->(2,3,4) SIGUSR1 означает, что процесс 1 посылает дочерним процессам 2,3,4 одновременно сигнал SIGUSR1. После передачи 101 –го сигнала родительский процесс посылает сыновьям сигнал SIGTERM. Сыновья получив сигнал завершают работу с выводом на консоль сообщения вида:

pid ppid завершил работу после ** сигнала SIGTERM

Каждый процесс выводит на консоль информацию в следующем виде:

pid ppid послал/получил USR1/USR2 текущее время (мксек)

дерево процессов(вариант № 0) 1->2 2->(3,4) 4->5 3->6 6->7 7->8

сигналы(вариант № 2) 1->(2,3,4,5) SIGUSR2 2->6 SIGUSR1 3->7 SIGUSR1 4->8 SIGUSR1 8->1 SIGUSR1

Описание основных функций и алгоритмов:

Родительский процесс создает дерево процессов согласно заданию при помощи функции enter() , которая берет на себя помимо ветвления fork() обработку возможных ошибок. Каждый новый процесс вызывает одноименную функцию (proc0()-proc8()) и далее работает в ней. По неименованным каналам процессы передают друг другу свои PID, необходимые для обмена сигналами и хранят их в глобальных переменных dd0-dd8 . Функция vivod() выводит данные о полученных – отправленных сигналах на монитор. После окончания работы процесс 1 отправляет сигнал SIGTERM процессам пр2-пр8(по получении которого они прекращают работу с выводом сообщения) и завершается сам.

Листинг программы:

#include<sys/wait.h>

#include<stdio.h>

#include<sys/types.h>

#include<stdlib.h>

#include<unistd.h>

#include<signal.h>

#include<time.h>

#include<sys/time.h>

#include<errno.h>

//переменные для хранение pid процессов

pid_t pid0,pid1,dd0,dd1,dd2,dd3,dd4,dd5,dd6,dd7,dd8;

//массивы для файловых дескрипторов неименованых каналов

int pipe31[2],pipe41[2],pipe51[2],pipe62[2],pipe73[2],pipe84[2],status;

int pipe61[2],pipe71[2],pipe81[2];

//прототипы функций

void vivod(int,int);

pid_t enter(void);//ветвление процесса с обработкой ошибок

void proc0();void proc1();void proc2();void proc3();void proc4();

void proc5();void proc6();void proc7();void proc8();

//обработчик сигналов SIGUSR1, SIGUSR2 и SIGTERM

static void handler1(int signo)

{

if(signo==SIGUSR1){vivod(1,0);}

else if(signo==SIGUSR2){ vivod(2,0);}

else if(signo==SIGTERM)

{

vivod(0,0);exit(0);

}

else printf("недопустимый сигнал %d ",signo);

}

//--------------------------main-----------------------------

int main(void)

{

pid0=pid1=dd0=dd1=dd2=dd3=dd4=dd5=dd6=dd7=dd8=-1;

//регистрация обработчика сигнала SIGUSR1

if(signal(SIGUSR1,handler1)==SIG_ERR)

{

perror("Невозможно обработать SIGUSR1");

exit(EXIT_FAILURE);

}

//регистрация обработчика сигнала SIGUSR2

if(signal(SIGUSR2,handler1)==SIG_ERR)

{

perror("Невозможно обработать SIGUSR2");

exit(EXIT_FAILURE);

}

//регистрация обработчика сигнала SIGTERM

if(signal(SIGTERM,handler1)==SIG_ERR)

{

perror("Невозможно обработать SIGTERM");

exit(EXIT_FAILURE);

}

nice(15);//уровень любезности

//Создание неименованых каналов для передачи pid

if(pipe(pipe31)==-1) {perror("Ошибка создания канала");exit(EXIT_FAILURE);}

if(pipe(pipe41)==-1) {perror("Ошибка создания канала");exit(EXIT_FAILURE);}

if(pipe(pipe51)==-1) {perror("Ошибка создания канала");exit(EXIT_FAILURE);}

if(pipe(pipe61)==-1) {perror("Ошибка создания канала");exit(EXIT_FAILURE);}

if(pipe(pipe62)==-1) {perror("Ошибка создания канала");exit(EXIT_FAILURE);}

if(pipe(pipe71)==-1) {perror("Ошибка создания канала");exit(EXIT_FAILURE);}

if(pipe(pipe73)==-1) {perror("Ошибка создания канала");exit(EXIT_FAILURE);}

if(pipe(pipe81)==-1) {perror("Ошибка создания канала");exit(EXIT_FAILURE);}

if(pipe(pipe84)==-1) {perror("Ошибка создания канала");exit(EXIT_FAILURE);}

dd0=getpid();

pid0=enter();//создать процесс1

if(pid0) //если поцесс 0

{

dd1=pid0;proc0();//номер процесса 1 для процесса 0

}

else //если поцесс 1

{

dd1=getpid();//номер процесса 1 для потомков

pid0=enter();//создать процесс2

if(pid0)//если поцесс 1

{

dd1=getpid();

dd2=pid0;proc1();//номер процесса 2 для процесса 1

}

else //если поцесс 2

{

dd2=getpid();//номер процесса 2 для потомков

pid0=enter();//создать процесс3

if(pid0){ //если процесс2

dd3=pid0;

pid1=enter();//создать процесс4

if(pid1)//если процесс2

{

dd4=pid1;proc2();//номер процесса 4 для процесса 2

}

else //если процесс4

{

dd2=getppid();//номер процесса 2 для потомков

dd4=getpid();

pid0=enter();//создать процесс5

if(pid0)//если процесс4

{

//номер процесса 5 для процесса 4

dd5=pid0;proc4();

}

else//если процесс5

{

//номер процесса 4 для потомков

dd5=getpid();proc5();

}

}

}

else//если процесс3

{

dd3=getpid();//номер процесса 3 для потомков

pid0=enter();//создать процесс6

if(pid0)//если процесс3

{

dd6=pid0;proc3();//номер процесса 6 для процесса 3

}

else //если процесс6

{

dd6=getpid();//номер процесса 6 для потомков

pid0=enter();//создать процесс7

if(pid0)//если процесс6

{

//номер процесса 7 для процесса 6

dd7=pid0;proc6();

}

else //если процесс7

{

dd7=getpid();//номер процесса 7 для потомков

pid0=enter();//создать процесс8

if(pid0)

{

dd8=pid0;proc7();//если процесс7

}

else //если процесс8

{

dd8=getpid();proc8();

}

}

}

}

}

}

return(0);

}

//------------------------------------------

pid_t enter()

{

pid_t pidd=fork();

if(pidd==-1){perror("Ошибка создания процесса");exit(1);}

else return(pidd);

}

//-------------------------------------------

void proc0()

{

while(waitpid(dd1,&status,WNOHANG)==0);

}

//----

void proc1()

{

int i;

read(pipe31[0],&dd3,sizeof(pid_t));

read(pipe41[0],&dd4,sizeof(pid_t));

read(pipe51[0],&dd5,sizeof(pid_t));

read(pipe61[0],&dd6,sizeof(pid_t));

read(pipe71[0],&dd7,sizeof(pid_t));

read(pipe81[0],&dd8,sizeof(pid_t));

while(getpgid(dd5)!=dd2);//Ждать перевода пр5 в другую группу

for(i=0;i<=101;i++)

{

kill(-dd2,SIGUSR2);

vivod(2,1);

}

sleep(2);

kill(dd8,SIGTERM);kill(dd7,SIGTERM);kill(dd6,SIGTERM);kill(-dd2,SIGTERM);

while(waitpid(dd2,&status,WNOHANG)==0);

}

//----

void proc2()

{

int i,j;

read(pipe62[0],&dd6,sizeof(pid_t));//pid процесса 6

setpgid(getpid(),getpid());

setpgid(dd3,getpid());

setpgid(dd4,getpid());

for(i=0;i<=101;i++)

{

kill(dd6,SIGUSR1);

vivod(1,1);

}

while(1) pause();

}

//----

void proc3()

{

int i,j;

write(pipe31[1],&dd3,sizeof(pid_t));

read(pipe73[0],&dd7,sizeof(pid_t));

for(i=0;i<=101;i++)

{

kill(dd7,SIGUSR1);

vivod(1,1);

}

while(1) pause();

}

//---------------------------------

void proc4()

{

int i;

write(pipe41[1],&dd4,sizeof(pid_t));

read(pipe84[0],&dd8,sizeof(pid_t));

for(i=0;i<=101;i++)

{

kill(dd8,SIGUSR1);

vivod(1,1);

}

while(1) pause();

}

//----------------------------

void proc5()

{

int j;

dd5=getpid();

write(pipe51[1],&dd5,sizeof(pid_t));//отправка своего pid процессу 1

while(getpgid(dd5)!=dd2)setpgid(dd5,dd2);//Ждать создания группы в пр2

while(1)pause();

}

//----

void proc6()

{

int j;

write(pipe61[1],&dd6,sizeof(pid_t));

write(pipe62[1],&dd6,sizeof(pid_t));

while(1) pause();

}

//----

void proc7()

{

int j;

write(pipe71[1],&dd7,sizeof(pid_t));

write(pipe73[1],&dd7,sizeof(pid_t));

while(1) pause();

}

//----

void proc8()

{

int i,j;

write(pipe81[1],&dd8,sizeof(pid_t));

write(pipe84[1],&dd8,sizeof(pid_t));

for(i=0;i<=101;i++)

{

kill(dd1,SIGUSR1);

vivod(1,1);

}

while(1) pause();

}

//-------------------------------

void vivod(int a,int flag)

{

time_t t;

time(&t);

struct timeval tm1;

gettimeofday(&tm1,NULL);

if(flag==1)

{

if(a==2)

printf("ppid:%d pid:%d послал SIGUSR2 время:%ldмксек %s\n",getppid(),getpid(),tm1.tv_usec,ctime(&t));

if(a==1)

{

printf("ppid:%d pid:%d послал SIGUSR1 время:%ldмксек %s\n",getppid(),getpid(),tm1.tv_usec,ctime(&t));

}

if(a==0)

{

printf("ppid:%d pid:%d послал SIGTERM время:%ldмксек %s\n",getppid(),getpid(),tm1.tv_usec,ctime(&t));

}

}

else

{

if(a==2)

printf("ppid:%d pid:%d принял SIGUSR2 время:%ldмксек %s\n",getppid(),getpid(),tm1.tv_usec,ctime(&t));

if(a==1)

{

printf("ppid:%d pid:%d принял SIGUSR1 время:%ldмксек %s\n",getppid(),getpid(),tm1.tv_usec,ctime(&t));

}

if(a==0)

{

printf("ppid:%d pid:%d завершил работу по сигналу SIGTERM время:%ldмксек %s\n",getppid(),getpid(),tm1.tv_usec,ctime(&t));

}

}

}