Скачиваний:
27
Добавлен:
01.04.2014
Размер:
237.06 Кб
Скачать

Белорусский государственный университет

информатики и радиоэлектроники

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

Специальность “Программное обеспечение информационных технологий”

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

по дисциплине «Теория вычислительных процессов и структур»

Бондаренко Александра Леонидовича

Группа 701021с

Зачетная книжка 701021с-06

Электронный адрес AlexBond2@tut.by

Минск – 2009

СРЕДСТВА МЕЖПРОЦЕССНОГО ВЗАИМОДЕЙСТВИЯ ОС

Цель работы – изучить методы и средства взаимодействия процессов в ОС Linux.

Задание.

Cоздать два дочерних процесса. Родительский процесс создаёт семафор (сем1) и общий файл отображенный в память. Оба дочерних процесса непрерывно записывают в файл по 100 строк вида: номер_строки pid_процесса текущее_время (мсек). Всего процессы должны записать 1000 строк. Семафор сем1 используется процессами для разрешения кому из процессов получить доступ к файлу. Родительский процесс читает из файла по 75 строк и выводит их на экран. Дочерние процессы начинают операции с файлом после получения сигнала SIGUSR1 от родительского процесса.

Решение.

Описание алгоритма: создается/очищается общий файл temp и отображается в память функцией mmap(). Создаются семафоры. Будем использовать 4 семафора, два для потока, один для блокирования записи/чтения и один для передачи номера строки. После создания семафоров, выставляем значение с помощью функции semctl(), тем самым организуем корректную работу. Далее создается два дочерних процесса, каждый дочерний процесс привязывается сигналом к функции c_action() которая разрешает начало выполнение операции. После создания процессов родительский процесс посылает сигнал SIGUSR1 каждому дочернему процессу.

Дочерний процессы, получив сигнал и разрешение на запись, записывает свои 100 строк и переключает семафоры, ожидая пока выполнит свою запись другой процесс.

Родительский процесс проверяет, есть ли строки для чтения через 4-й семафор и после чего считывает 75 строк и выводит на экран, блокируя доступ к файлу через 3-й семафор.

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

#include <linux/sem.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <sys/time.h>

#include <sys/mman.h>

#include <stdlib.h>

#include <errno.h>

#include <fcntl.h>

#include <stdio.h>

#include <signal.h>

int start = 0;

#define LEN 20

pid_t chpid [2];

int main (int argc, char *argv [])

{

struct timeval c_time;

void c_action (int);

static struct sigaction pact, cact;

char str [LEN];

id_t pid;

// создаем общий файл

unlink("temp");

int fd = open("temp",O_CREAT|O_RDWR);

char* map = mmap(0,1000*LEN,PROT_READ | PROT_WRITE, MAP_SHARED, fd,0);

if(map == MAP_FAILED){

perror("mmap");

return 1;}

// создаем семафор

int j,n,i=0;

key_t key;

if((key = ftok("temp",3)) < 0){

perror("Can\'t generate key");

return 1;

}

int semid = semget(key, 4, 0666 | IPC_CREAT );

if (semid < 0){

perror("semget");

return 1;}

struct sembuf s_red[2] = {0, -1, IPC_NOWAIT, 1, 1, IPC_NOWAIT};

struct sembuf s_green[2] = {0, 1, IPC_NOWAIT, 1, -1, IPC_NOWAIT};

struct sembuf s_wait[2] = {0, 0, 0, 1, 0, 0};

struct sembuf s_readed = {2, 0, 0};

struct sembuf s_lock = {2, 1, IPC_NOWAIT};

struct sembuf s_unlock = {2, -1, IPC_NOWAIT};

union semun arg;

arg.val = 0;

semctl(semid, 0, SETVAL, arg);

arg.val = 1;

semctl(semid, 1, SETVAL, arg);

arg.val = 0;

semctl(semid, 2, SETVAL, arg);

// создаем два процесса

for (j=0; j<2; j++) {

switch (chpid [j] = fork ()) {

case -1:

printf ("Fork call error\n");

return 1;

case 0:

//child

cact.sa_flags = SA_SIGINFO;

cact.sa_sigaction = (void *) c_action;

sigaction (SIGUSR1, &cact, NULL);

printf("child #%d\n",getpid());

while (i <= 1000) {

// ожидаем разрешения

if ((start)&&

(semop( semid, &s_readed, 1)==0)&&

(semop( semid, &s_wait[j], 1)==0))

{

lseek (fd, 0, SEEK_END);

i = semctl(semid, 3, GETVAL);

if (i==1000)break;

for (n=0;n<100;n++){

gettimeofday(&c_time,NULL);

sprintf (str,"%4d #%5d :%6d\n", i+n+1,

getpid (), c_time.tv_usec);

write(fd,str,LEN);

}

i+=n;

arg.val = i;

semctl(semid, 3, SETVAL, arg);

// переключаем поток

if (j==0) semop( semid, &s_green, 2);

else semop( semid, &s_red, 2);

}

}

return 0;

}

}

printf("father #%d\n",getpid());

//father

kill (chpid [0], SIGUSR1);

kill (chpid [1], SIGUSR1);

i=0;

while (i < 1000) {

sleep(1);

// ожидаем разрешения

j=semctl(semid, 3, GETVAL);

if( (j>i+75)||(j==1000))

{

// блокируем

semop( semid, &s_lock, 1);

// читаем

lseek (fd, i*LEN, SEEK_SET);

for (n=0;n<75;n++){

if (i+n ==1000) break;

read(fd,str,LEN);

printf ("%s", str);

}

i+=n;

// разблокируем

semop( semid, &s_unlock, 1);

}

}

close(fd);

semctl(semid, 0, IPC_RMID);

return 0;

}

void c_action (int sig)

{

start = 1;

printf("action #%d\n",getpid());

}

Скриншоты выполнения программы: