Студопедия  
Главная страница | Контакты | Случайная страница

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатика
ИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханика
ОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторика
СоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансы
ХимияЧерчениеЭкологияЭкономикаЭлектроника

В результате военной реформы, проведенной Избранной Радой в. Все рассмотренные на этом занятии примеры являются не совсем корректными

Читайте также:
  1. C. которое обязательно наступит в результате испытания.
  2. D) удвоенной площади треугольника, построенного на этих векторах
  3. II. Компетенции, формируемые в результате освоения учебной дисциплины
  4. В результате военной реформы, проведенной Избранной Радой в
  5. В результате изучения дисциплины студент должен
  6. В результате изучения дисциплины студент должен
  7. В результате изучения дисциплины студент должен
  8. В результате изучения дисциплины студент должен
  9. В результате изучения модуля студент должен

Все рассмотренные на этом занятии примеры являются не совсем корректными. В большинстве случаев они работают правильно, однако возможны ситуации, когда совместная деятельность этих процессов или потоков исполнения приводит к неверным и неожиданным результатам. Это связано с тем, что любые неатомарные операции, связанные с изменением содержимого разделяемой памяти, представляют собой критическую секцию процесса или потока исполнения. Вспомните рассмотрение критических секций из лекций.

Вернитесь к рассмотрению программ из раздела "Прогон программ с использованием разделяемой памяти". При одновременном существовании двух процессов в операционной системе может возникнуть следующая последовательность выполнения операций во времени:

...

Процесс 1: array[0] += 1;

Процесс 2: array[1] += 1;

Процесс 1: array[2] += 1;

Процесс 1: printf(

"Program 1 was spawn %d times,

program 2 - %d times, total - %d times\n",

array[0], array[1], array[2]);

...

Тогда печать будет давать неправильные результаты. Естественно, что воспроизвести подобную последовательность действий практически нереально. Почти невозможно подобрать необходимое время старта процессов и степень загруженности вычислительной системы. Но возможно смоделировать эту ситуацию, добавив в обе программы достаточно длительные пустые циклы перед оператором array[2] += 1; Это проделано в следующих программах.

/* Программа 1 (4-3а.с) для иллюстрации

некорректной работы с разделяемой памятью */

/* Мы организуем разделяемую память для массива из трех целых

чисел. Первый элемент массива является счетчиком числа

запусков программы 1, т. е. данной программы, второй элемент

массива – счетчиком числа запусков программы 2, третий

элемент массива – счетчиком числа запусков обеих программ */

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

#include <stdio.h>

#include <errno.h>

int main()

{

int *array; /* Указатель на разделяемую память */

int shmid; /* IPC дескриптор для области

разделяемой памяти */

int new = 1; /* Флаг необходимости инициализации

элементов массива */

char pathname[] = "4-3a.c"; /* Имя файла,

использующееся для генерации ключа. Файл с таким

именем должен существовать в текущей директории */

key_t key; /* IPC ключ */

long i;

/* Генерируем IPC ключ из имени файла 4-3a.c в

текущей директории и номера экземпляра области

разделяемой памяти 0 */

if((key = ftok(pathname,0)) < 0){

printf("Can\'t generate key\n");

exit(-1);

}

/* Пытаемся эксклюзивно создать разделяемую память для

сгенерированного ключа, т.е. если для этого ключа она

уже существует, системный вызов вернет отрицательное

значение. Размер памяти определяем как размер массива

из 3-х целых переменных, права доступа 0666 – чтение и

запись разрешены для всех */

if((shmid = shmget(key, 3*sizeof(int),

0666|IPC_CREAT|IPC_EXCL)) < 0){

/* В случае возникновения ошибки пытаемся определить:

возникла ли она из-за того, что сегмент разделяемой

памяти уже существует или по другой причине */

if(errno!= EEXIST){

/* Если по другой причине – прекращаем работу */

printf("Can\'t create shared memory\n");

exit(-1);

} else {

/* Если из-за того, что разделяемая память уже

существует – пытаемся получить ее IPC дескриптор

и, в случае удачи, сбрасываем флаг необходимости

инициализации элементов массива */

if((shmid = shmget(key, 3*sizeof(int), 0)) < 0){

printf("Can\'t find shared memory\n");

exit(-1);

}

new = 0;

}

}

/* Пытаемся отобразить разделяемую память в адресное

пространство текущего процесса. Обратите внимание на то,

что для правильного сравнения мы явно преобразовываем

значение -1 к указателю на целое.*/

if((array = (int *)shmat(shmid, NULL, 0)) ==

(int *)(-1)){

printf("Can't attach shared memory\n");

exit(-1);

}

/* В зависимости от значения флага new либо

инициализируем массив, либо увеличиваем

соответствующие счетчики */

if(new){

array[0] = 1;

array[1] = 0;

array[2] = 1;

} else {

array[0] += 1;

for(i=0; i<1000000000L; i++);

/* Предельное значение для i может меняться в зависимости

от производительности компьютера */

array[2] += 1;

}

/* Печатаем новые значения счетчиков, удаляем разделяемую

память из адресного пространства текущего процесса и з

авершаем работу */

printf("Program 1 was spawn %d times,

program 2 - %d times, total - %d times\n",

array[0], array[1], array[2]);

if(shmdt(array) < 0){

printf("Can't detach shared memory\n");

exit(-1);

}

return 0;

}

Листинг 4.3a. Программа 1 (4-3а.с) для иллюстрации некорректной работы с разделяемой памятью.

 

/* Программа 2 (4-3b.c) для иллюстрации

некорректной работы с разделяемой памятью */

/* Мы организуем разделяемую память для массива из трех

целых чисел. Первый элемент массива является счетчиком

числа запусков программы 1, т. е. данной программы,

второй элемент массива – счетчиком числа запусков

программы 2, третий элемент массива – счетчиком числа

запусков обеих программ */

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

#include <stdio.h>

#include <errno.h>

int main()

{

int *array; /* Указатель на разделяемую память */

int shmid; /* IPC дескриптор для области

разделяемой памяти */

int new = 1; /* Флаг необходимости инициализации

элементов массива */

char pathname[] = "4-3a.c"; /* Имя файла,

использующееся для генерации ключа. Файл с таким

именем должен существовать в текущей директории */

key_t key; /* IPC ключ */

long i;

/* Генерируем IPC ключ из имени файла 4-3a.c в текущей

директории и номера экземпляра области разделяемой

памяти 0 */

if((key = ftok(pathname,0)) < 0){

printf("Can\'t generate key\n");

exit(-1);

}

/* Пытаемся эксклюзивно создать разделяемую память для

сгенерированного ключа, т.е. если для этого ключа она

уже существует, системный вызов вернет отрицательное

значение. Размер памяти определяем как размер массива

из трех целых переменных, права доступа 0666 – чтение

и запись разрешены для всех */

if((shmid = shmget(key, 3*sizeof(int),

0666|IPC_CREAT|IPC_EXCL)) < 0){

/* В случае ошибки пытаемся определить, возникла ли она

из-за того, что сегмент разделяемой памяти уже существует

или по другой причине */

if(errno!= EEXIST){

/* Если по другой причине – прекращаем работу */

printf("Can\'t create shared memory\n");

exit(-1);

} else {

/* Если из-за того, что разделяемая память уже

существует – пытаемся получить ее IPC дескриптор

и, в случае удачи, сбрасываем флаг необходимости

инициализации элементов массива */

if((shmid = shmget(key,

3*sizeof(int), 0)) < 0){

printf("Can\'t find shared memory\n");

exit(-1);

}

new = 0;

}

}

/* Пытаемся отобразить разделяемую память в адресное

пространство текущего процесса. Обратите внимание на то,

что для правильного сравнения мы явно преобразовываем

значение -1 к указателю на целое.*/

if((array = (int *)shmat(shmid, NULL, 0)) ==

(int *)(-1)){

printf("Can't attach shared memory\n");

exit(-1);

}

/* В зависимости от значения флага new либо

инициализируем массив, либо увеличиваем

соответствующие счетчики */

if(new){

array[0] = 0;

array[1] = 1;

array[2] = 1;

} else {

array[1] += 1;

for(i=0; i<1000000000L; i++);

/* Предельное значение для i может меняться в зависимости

от производительности компьютера */

array[2] += 1;

}

/* Печатаем новые значения счетчиков, удаляем разделяемую

память из адресного пространства текущего процесса и завершаем

работу */

printf("Program 1 was spawn %d times,

program 2 - %d times, total - %d times\n",

array[0], array[1], array[2]);

if(shmdt(array) < 0){

printf("Can't detach shared memory\n");

exit(-1);

}

return 0;

}

Листинг 4.3b. Программа 2 (4-3b.c) для иллюстрации некорректной работы с разделяемой памятью.

Наберите программы, сохраните под именами 4-3а.с и 4-3b.c соответственно, откомпилируйте их и запустите любую из них один раз для создания и инициализации разделяемой памяти. Затем запустите другую и, пока она находится в цикле, запустите, например, с другого виртуального терминала, снова первую программу. Вы получите неожиданный результат: количество запусков по отдельности не будет соответствовать количеству запусков вместе.

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

Задача повышенной сложности: модифицируйте программы из этого раздела для корректной работы с помощью алгоритма Петерсона.

 

В результате военной реформы, проведенной Избранной Радой в

XVI в., появились:

а) рекруты б) стрельцы в) драгуны г) гвардейцы

 

5. К мероприятиям внутренней политики Екатерины П НЕ относится:

а) губернская реформа

б) ликвидация гетманства на Украине

в) издание «Жалованной грамоты дворянству»

г) создание министерств

 

6. Высшее правительственное учреждение, основанное указом Екатерины I в 1726, называлось:

а) Верховный Тайный совет б) Государственный совет

в) Кабинет министров г) Синод

 

7.Русско-турецкие войны второй половины XVШ в. Завершились:

а) получением Россией выхода к Черному морю

б) потерей Россией Причерноморья

в) потерей Россией Крыма

г) вхождением в состав России Правобережной Украины Белоруссии

 

8. В истории России даты 1861 г., 1881-1883 гг., отражают процесс:

а) закрепощения крестьян

б) освобождения крестьян- 1861

в) разрушения крестьянской общины

??г) расширения избирательных прав крестьян

 

9. Петрашевцами были:

а) К.Ф.Рылеев, Н.М.Муравьев

б) Г.В.Плеханов, В.И.Засулич

в) В.И.Ульянов, Ю.О.Мартов

г) Ф.М.Достоевский, М.Е.Салтыков-Щедрин

 

10. Политическим последствием победы большевиков в Гражданской войне было:

?а) образование СССР

б) возрождение многопартийности в стране

в) возвращение эмигрантов из-за рубежа

?г) возвращение политических прав для всех классов и слоев общества

 

11. Второй фронт против нацистских войск в Европе был открыт союзниками в(о):

а) Норвегии б) Франции в) Италии г) Испании

 

12. Людей, ставших на путь сотрудничества с оккупантами в годы Великой Отечественной войны, называют:

а) коллаборационистами б) волонтерами

в) интервентами г) сепаратистами

 

13. Постановления ЦК ВКП(б), критиковавшие представителей творческой интеллигенции, были приняты в... годы:.

а) 1973-1975 б) 1985-1987 в) 1946-1948 г) 1962-1964

 

14.В число современных политических партий НЕ входит партия:

а) КПРФ б) «Яблоко» в) СПС г) РСДРП

 

15.Радикальная экономическая реформа в России начала 1990-х гг. в сфере сельского хозяйства предполагала:

а) запрещение импорта продовольствия

б) создание фермерских хозяйств

в) обновление машинно-тракторного парка за счет государства

г) слияние колхозов и совхозов

 




Дата добавления: 2014-12-19; просмотров: 105 | Поможем написать вашу работу | Нарушение авторских прав




lektsii.net - Лекции.Нет - 2014-2024 год. (0.019 сек.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав