2268

Синхронизация процессов. Обмен данными между процессами

Лабораторная работа

Информатика, кибернетика и программирование

Цель работы: получить представление о сигналах в операционной системе UNIX и способах их перехвата и обработки, а также о синхронизации процессов при помощи сигналов и обмене данными между процессами с использованием разделяемой памяти.

Русский

2013-01-06

56 KB

12 чел.

Министерство образования РФ

Костромской Государственный Технологический Университет

Кафедра АМТ

Курс «Управляющие системы реального времени»

Лабораторная работа №2

Синхронизация процессов. Обмен данными между процессами

Выполнил:  Швайко А.В.

Группа:       99-А-18 «а»

Проверил:   Ершов В.Н.

Кострома 2003

Цель работы: получить представление о сигналах в операционной системе UNIX и способах их перехвата и обработки, а также о синхронизации процессов при помощи сигналов и обмене данными между процессами с использованием разделяемой памяти.

 

Иcпользуемые средства: ОС Linux, графическая оболочка KDE, среда разработки Anjuta, терминал.

 

1. Составить программу, содержащую бесконечный цикл с вызовом sleep и выводом на экран. Заблокировать сигнал SIGINT при помощи

а. Функции signal

б. Критической секции

Убедиться, что программа не реагирует на Control-C.

а)

#include <stdio.h>
#include <signal.h>
int main()
{
 
int c;
 c=
0;
 signal(SIGINT, SIG_IGN);
 
while(1)
 {
   sleep(
1);
   fprintf(stderr,
"We want to write programs on C++ %d\n",c++);
 }
 
return 0;
}

б)

#include <stdio.h>
#include <signal.h>
int main()
{
 
int c;
 sigset_t mysig;
 c=
0;
 sigaddset(&mysig, SIGINT);
 sigprocmask(SIG_SETMASK, &mysig, NULL);
 
while(1)
 {
   sleep(
1);
   fprintf(stderr,
"We want to write programs on C++ %d\n",c++);
 }
 sigprocmask(SIG_UNBLOCK, &mysig, NULL);
 
return 0;
}

2. Модифицировать программу, установив обработчик сигнала SIGINT, выводящий на экран запрос на подтверждение завершения программы и по получении положительного ответа вызывающий функцию exit. Убедиться, что нажатие на Control C досрочно завершает сон процесса.

#include <stdio.h>
#include <signal.h>
void obrab(int key)
{
 printf(
"Are you ready to stop process. Yes-1, No-0\n");
 scanf(
"%d",&key);
 
if (key == 1) exit(0);
}
int main()
{
 
int c;
 c=
0;
 signal(SIGINT, obrab);
 
while(1)
 {
   sleep(
1);
   fprintf(stderr,
"We want to write programs on C++ %d\n",c++);
 }
 
return 0;
}

3. Модифицировать обработчик сигнала SIGINT таким образом, чтобы он вызывал exit после получения третьего сигнала.

#include <stdio.h>
#include <signal.h>
int n=0;
int obrab()
{
 n++;
 printf(
"Control-C number=%d\n",n);
 
if (n==3) exit (0);
}
int main()
{
 
int c;
 c=
0;
 signal(SIGINT, obrab);
 
while(1)
 {
   sleep(
1);
   fprintf(stderr,
"We want to write programs on C++ %d\n",c++);
 }
 
return 0;
}

4. Модифицировать бесконечный цикл основной программы таким образом, чтобы вызов sleep и вывод на экран находились внутри критической секции (но не весь цикл). Убедиться, что пока процесс «спит» внутри критической секции, для него откладывается только один сигнал SIGINT, независимо от числа нажатий на Control C.

#include <stdio.h>
#include <signal.h>
int n=0;
int obrab()
{
 n++;
 printf(
"Control-C number=%d\n",n);
 
if (n==3) exit (0);
}
int main()
{
 
int c;
 sigset_t mysig;
 sigaddset(&mysig,SIGINT);
 c=
0;
 signal(SIGINT, obrab);
 
while(1)
 {
   sigprocmask(SIG_SETMASK, &mysig, NULL);
   fprintf(stderr,
"In critical part%d\n",c++);
   sleep(
3);
   sigprocmask(SIG_UNBLOCK, &mysig, NULL);
 }
 
return 0;
}

5. Составить программу, устанавливающую обработчик сигнала от таймера реального времени и устанавливающую интервал между сигналами в 1,5 сек. Для контроля работы программы поместить в обработчик сигнала вывод на экран кода 0х07 (звуковой сигнал) или какой-либо строки. Перевести основную программу в

неактивное состояние

а. Вызовом pause()

б. Циклом while(1) pause()

Сравнить результаты.

#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
int c;
void obrab()
{
 
char sig=0x07;
 c+=
1;
 fprintf(stderr,
"%cSignal number\t%d\n",sig,c);
}
int main()
{
 
struct itimerval tm;
    tm.it_value.tv_sec=
0;
    tm.it_value.tv_usec=
500000;
    tm.it_interval.tv_sec=
1;
    tm.it_interval.tv_usec=
500000;
   setitimer(ITIMER_REAL,&tm,NULL);
   signal(SIGALRM, obrab);
 
while(1) pause();
 
//pause();
 
return (0);
}

6.Составить 2 программы, обменивающиеся информацией через разделяемую память. Достаточно использовать одну переменную целого типа для обмена информацией и одну переменную целого типа для синхронизации. Оба процесса устанавливают обработчики от таймера реального времени. Первый с интервалом 0.2 сек, второй – 1 сек. Обработчик сигнала от таймера в первом процессе инкрементирует переменную в разделяемой памяти, а второй – выводит значение этой переменной на экран. Оба процесса должны завершиться после срабатывания обработчика сигнала от таймера во втором процессе 15-20 раз.

Передатчик:

#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/stat.h>
#define mem 0xAAAA

int* c;
int dmem;
char* pmem;
int* start;
int* end;

void obrab()
{
 fprintf(stderr,
"%d\n",*c);
 *c+=
1;
}
int main()
{
 
struct itimerval tm;
  tm.it_value.tv_sec=
0;
  tm.it_value.tv_usec=
500000;
  tm.it_interval.tv_sec=
0;
  tm.it_interval.tv_usec=
200000;
 setitimer(ITIMER_REAL,&tm,NULL);
 signal(SIGALRM, SIG_IGN);
 dmem=shmget(mem,getpagesize(),IPC_CREAT|S_IRUSR|S_IWUSR);
 pmem=(
char*)shmat(dmem,0,0);
 start=(
int*)pmem;
 c=(
int*)(pmem+sizeof(int));
 end=(
int*)(pmem+sizeof(int)+sizeof(int));

 signal(SIGALRM,obrab);
 *start=
0;

 
while(!*end) pause();
 *c=
0; *end=0;
 shmdt(pmem);
 
return 0;
}

Приемник:

#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/stat.h>
#define mem 0xAAAA
int* c;
int dmem;
char* pmem;
int* start;
int* end;
int ch;

void obrab()
{
 ch+=
1;
 fprintf(stderr,
"%d\t%d\n",*c,ch);
}
int main()
{
 
struct itimerval tm;
  tm.it_value.tv_sec=
0;
  tm.it_value.tv_usec=
200000;
  tm.it_interval.tv_sec=
1;
  tm.it_interval.tv_usec=
0;
 setitimer(ITIMER_REAL,&tm,NULL);
 signal(SIGALRM, SIG_IGN);
 dmem=shmget(mem,getpagesize(),IPC_CREAT|S_IRUSR|S_IWUSR);
 pmem=(
char*)shmat(dmem,0,0);
 start=(
int*)pmem;
 c=(
int*)(pmem+sizeof(int));
 end=(
int*)(pmem+sizeof(int)+sizeof(int));

 *end=
0;
 *start=
1;
 
while(*start);
 signal(SIGALRM, obrab);

 
while(ch<15) pause();
 *end=
1;
 
return 0;
}

7. Переработать схему взаимодействия «модели» и «регулятора». Для этого заменить сигналы от таймера пользовательскими сигналами. А источником пользовательских сигналов сделать третий процесс «диспетчер», который будет в цикле, исполняемом 15-20 раз, посылать 5 сигналов «модели» и 1 сигнал «регулятору».

    а) выполнить посылку сигналов от «диспетчера» к «модели» и «регулятору» без подтверждения приема:

for(i=0; i< 20; i++){
   kill(*p_reg, SIGUSR2); 

   for(j=0; j<5; j++)kill(*p_mod, SIGUSR1);
}

убедиться, что схема не работает. Объяснить почему.

    б) выполнить посылку сигналов от «диспетчера» к «модели» и «регулятору» с подтверждением приема:

for(i=0; i< N; i++){
    kill(*p_reg, SIGUSR2); if(!gotcha2) pause(); gotcha2=0;
    for(j=0; j<M; j++){

      kill(*p_mod, SIGUSR1); 

      if(!gotcha1) pause(); gotcha1=0;

   }
}

Диспетчер:

#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/stat.h>
#define mem 0xABCD
int* c;
int dmem;
char* pmem;
int* end;
int i;
int* pid1;
int* pid2;
int* ch;
int j;
int* flag1;
int* flag2;

int main()
{
 dmem=shmget(mem,getpagesize(),IPC_CREAT|S_IRUSR|S_IWUSR);
 pmem=(
char*)shmat(dmem,0,0);
    pid1=(
int*)pmem;
    pid2=(
int*)(pmem+sizeof(int));
       c=(
int*)(pmem+sizeof(int)+sizeof(int));
     end=(
int*)(pmem+sizeof(int)+sizeof(int)+sizeof(int));
      ch=(
int*)(pmem+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int));
   flag1=(
int*)(pmem+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int));
   flag2=(
int*)(pmem+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int));

 *end=
0;
 j=
0;
 printf(
"\tGo!!!\n");

 
for(i=0;i<20;i++)
   {
   kill(*pid2, SIGUSR2);
   
if(!*flag2) pause();
   *flag2=
0;
   
for(j=0;j<5;j++)
     {
     kill(*pid1, SIGUSR1);
     
if(!*flag1) pause();
     *flag1=
0;
     fprintf(stderr,
"\t| %d\t| %d\t|\n",*c,*ch);
     }
   }

 kill(*pid1, SIGTERM);
 kill(*pid2, SIGTERM);
 
if(!shmdt(pmem)) fprintf(stderr,"\tMEMORY ALL RIGHT\n");
   
else fprintf(stderr,"ERROR!!!\n");

 
return 0;
}

Передатчик:

#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/stat.h>
#define mem 0xABCD

int* c;
int dmem;
char* pmem;
int* pid1;
int* pid2;
int* end;
int* ch;
int* flag1;
int* flag2;

void obrab()
{
 *c+=
1;
 fprintf(stderr,
"%d\n",*c);
 *flag1=
1;
}
int main()
{
 dmem=shmget(mem,getpagesize(),IPC_CREAT|S_IRUSR|S_IWUSR);
 pmem=(
char*)shmat(dmem,0,0);
    pid1=(
int*)pmem;        *pid1=getpid();
    pid2=(
int*)(pmem+sizeof(int));
       c=(
int*)(pmem+sizeof(int)+sizeof(int));
     end=(
int*)(pmem+sizeof(int)+sizeof(int)+sizeof(int));
      ch=(
int*)(pmem+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int));
   flag1=(
int*)(pmem+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int));
   flag2=(
int*)(pmem+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int));

 *c=
0;
 signal(SIGUSR1,obrab);
 printf(
"Peredatchic on start\n");

 
while(!*end) pause();

 
return 0;
}

Приемник:

#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/stat.h>
#define mem 0xABCD

int dmem;
char* pmem;
int* ch;
int* pid1;
int* pid2;
int* end;
int* c;
int* flag1;
int* flag2;

void obrab()
{
 (*ch)++;
 fprintf(stderr,
"%d\t%d\n",*c,*ch);
 *flag2=
1;
}

int main()
{
 dmem=shmget(mem,getpagesize(),IPC_CREAT|S_IRUSR|S_IWUSR);
 pmem=(
char*)shmat(dmem,0,0);
    pid1=(
int*)pmem;
    pid2=(
int*)(pmem+sizeof(int));      *pid2=getpid();
       c=(
int*)(pmem+sizeof(int)+sizeof(int));
     end=(
int*)(pmem+sizeof(int)+sizeof(int)+sizeof(int));
    ch=(
int*)(pmem+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int));
   flag1=(
int*)(pmem+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int));
   flag2=(
int*)(pmem+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int)+sizeof(int));

 *ch=
0;
 signal(SIGUSR2, obrab);
 printf(
"Priemnic on start\n");

 
while(!*end) pause();

 
return 0;
}


 

А также другие работы, которые могут Вас заинтересовать

53488. Процедура вставки вершин в AVL дерева и ее особенности 19.29 KB
  Показатель сбалансированности в дальнейшем будем интерпретировать как разность между высотой левого и правого поддерева, а алгоритм будет основаться на типе TAVLTree, описанном выше. Непосредственно при вставке (листу) присваивается нулевой баланс
53489. УРОКИ МАТЕМАТИКИ В НАЧАЛЬНОЙ ШКОЛЕ 415 KB
  Издание содержит основные требования к урокам математики в начальной школе нормы оценок устных и письменных работ учащихся схемы анализа уроков и контрольных работ. Предложены типы уроков математики раскрыты особенности их построения приведены типичные причины затруднений практикантов на уроках. Содержание Введение 4 Этапы планирования и подготовки урока студентом 5 Действия практиканта при планировании и конкретизации задач урока. 9 Примерное содержание комбинированного урока 11 Образцы оформления конспектов...
53492. Построение таблицы по бинарному дереву поиска 22.96 KB
  Уровень узла в бинарном дереве определяется следующим образом: уровень корня всегда равен нулю, а далее номера уровней при движении по дереву от корня увеличиваются на 1 по отношению к своему непосредственному предку
53493. Расчет козлового крана по заданным параметрам 799 KB
  Повышение качества создаваемого механического оборудования и конструкций необходимо связывать, прежде всего, с уменьшением их веса и стоимости, повышением надежности и улучшением ряда других характеристик
53494. Особенности и результат левого поворота поддерева AVL дерева 131.17 KB
  После добавления нового элемента необходимо обновить коэффициенты сбалансированности родительских узлов. Если любой родительский узел принял значение -2 или 2, то необходимо выполнить балансировку поддерева путем поворота
53495. Алгоритм вставки вершины AVL дерево. Случай одного (левого) поворота 129.41 KB
  Следовать по пути поиска, пока не окажется, что узла нет в дереве. Включить новый узел и определить показатель сбалансированности. Пройти обратно по пути поиска, определяя сбалансированность.
53496. Каким должен быть урок русского языка и литературы? 26 KB
  Учители русского языка и литературы играют важную роль в жизни человека. Так же важную роль в этом играет урок русского языка. В этом нам помогают учители русского языка.