воскресенье, 20 апреля 2014 г.

Лаба "Средства межпроцессного взаимодействия"

Написать программу, которая порождает дочерний процесс, и общается с ним через средства взаимодействия согласно варианту (Общие файлы), передавая и получая информацию согласно варианту (Родитель передает 5 случайных чисел, потомок возвращает их сумму и  произведение). Передачу и получение информации каждым из процессов сопровождать
выводом на экран информации типа "процесс такой-то передал/получил такую-то информацию".
Дочерние процессы начинают операции после получения сигнала  SIGUSR1 от родительского процесса.

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <signal.h>

#include <unistd.h>

void *my_handler(int nsig)
{
  /* обработка сигнала */
}

int main(){
    int summ=0,mult=1;
    int num;
    int x;
    int i;
    int fd;
    int *buffer;
    if((fd = open("data", O_RDWR | O_TRUNC,0666)) < 0){
        printf("Can\'t open file\n");
        return -1;
    }
    char c=0;
    write(fd,&c,sizeof(char));
    (void) signal(SIGUSR1, (__sighandler_t)my_handler);
    buffer=(int*)mmap(0,10,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0);
    x=fork();
    if(x!=0){
        srand(time(NULL));
        pause();
        for(i=0;i<5;i++){
            num=random()%10;
            buffer[0]=num;
            printf("Предок отправил %d\n",buffer[0]);
            kill(x, SIGUSR1);
            pause();
        }
        num=buffer[0];
        printf("Предок получил сумму %d\n",num);
        kill(x, SIGUSR1);
        pause();
        num=buffer[0];
        printf("Предок получил произведение %d\n",num);
        printf("Предок завершился\n");
       
    }else{
        kill(getppid(), SIGUSR1);
        for(i=0;i<5;i++){
            pause();
            num=buffer[0];
            summ+=num;
            mult*=num;
            printf("Потомок получил %d\n",num);
            kill(getppid(), SIGUSR1);
        }
        buffer[0]=summ;
        printf("Потомок отправил сумму %d\n",summ);
        kill(getppid(), SIGUSR1);
        pause();
        buffer[0]=mult;
        printf("Потомок отправил произведение %d\n",mult);
        kill(getppid(), SIGUSR1);
        printf("Потомок завершился\n");       
    }
    return 0;
}


Алёнки =)
Текст задания. Вариант 18.
Написать программу, которая порождает дочерний процесс, и общается с ним через средства взаимодействия согласно варианту (Очереди сообщений), передавая и получая информацию согласно варианту (Родитель передает величины катетов прямоугольного треугольника, назад получает величины острых углов). Передачу и получение
информации каждым из процессов сопровождать выводом на экран информации типа "процесс такой-то передал/получил такую-то информацию". Дочерние процессы начинают операции после получения сигнала SIGUSR1 от родительского процесса.
Текст программы

 #include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <mqueue.h>
#include <signal.h>
#include <unistd.h>
#include <math.h>

#define QUEUE_PARENT  "/triangle_parent"
#define QUEUE_CHILD  "/triangle_child"
#define MAX_SIZE    255
#define MSG_STOP    "exit"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

void CHECK(x){
    do {
        if (!(x)) {
            fprintf(stderr, "%s:%d: ", __func__, __LINE__);
            exit(-1);
        }
    } while (0); }


void parent_proc(mqd_t, mqd_t, pid_t);
void child_proc();

void chld_handler(int ign, siginfo_t *siginfo, void *ign2) {
    /* дочерний процесс завершился */
    waitpid(siginfo->si_pid, NULL, 0);

    exit(siginfo->si_status); /* выходим со статусом дочернего процесса */
}

int main(int argc, char *argv[]) {
    mqd_t req, resp;

    struct mq_attr attr;
    pid_t pid;
    struct sigaction act;
    sigset_t set;


    /* установим обработчик SIGCHLD */
    memset(&act, 0, sizeof(struct sigaction));
    act.sa_sigaction = chld_handler;
    /* не будем блокировать никаких сигналов */
    sigemptyset(&set);//sigemptyset инициализирует набор сигналов, указанный в set, и "очищает" его от всех сигналов.
    act.sa_mask = set;//sa_mask — маска сигналов, которыe будут блокированы пока выполняется наш обработчик
    /* используем расширенный обработчик и не будем получать сигналы */
    /* об остановке и возобновлении процесса, только о завершении */
    act.sa_flags = SA_SIGINFO | SA_NOCLDSTOP;//sa_flags — позволяет задать дополнительные действия при обработке сигнала
    sigaction(SIGCHLD, &act, NULL);

/*инициализация очереди атрибутов*/
    attr.mq_flags = 0;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = MAX_SIZE;
    attr.mq_curmsgs = 0;

    resp = mq_open(QUEUE_PARENT, O_CREAT|O_RDONLY, 0644, &attr);
    CHECK((mqd_t)-1 != resp);
    req = mq_open(QUEUE_CHILD, O_CREAT|O_WRONLY, 0644, &attr);
    CHECK((mqd_t)-1 != req);

/// Порождение процесса  
    pid = fork();

    if (pid < 0) {
        printf("Не удалось создать процесс!\n");
        exit(-1);
    } else if (pid > 0) {
        parent_proc(resp, req, pid);
    } else {
        mq_close(resp);
        mq_close(req);
        child_proc();
    }

    return 0;
}

void parent_proc(mqd_t resp, mqd_t req, pid_t pid) {
    ssize_t bytes_read;//тип ssize_t используется для подсчёта байт и выявления ошибки
    char buffer[MAX_SIZE];
    double k1=0, k2=0, a1=0, a2=0;
    char *p1;
    int res;
printf("Введите пары катетов прямоугольного треугольника в формате \"k1, k2\" (Введите \"exit\" для завершения):\n");
    do {
       printf("> ");
        fflush(stdout);
        memset(buffer, 0, MAX_SIZE);
        fgets(buffer, MAX_SIZE, stdin);

/* Отправляем сообщение - катеты. В это время дочерний процесс ожидает сигнала от родительского процесса*/
        CHECK(0 <= mq_send(req, buffer, MAX_SIZE, 0));
        if(strncmp(buffer, MSG_STOP, strlen(MSG_STOP)))
    printf("Родительский процесс передал катеты прямоугольного треугольника: %s", buffer);
        kill(pid, SIGUSR1);
/*Получение углов*/
        bytes_read = mq_receive(resp, buffer, MAX_SIZE, NULL);
        CHECK(bytes_read >= 0);
        buffer[bytes_read] = '\0';
        printf("Родительский процесс получил величины острых углов прямоугольного треугольника: %s\n", buffer);
        fflush(stdout);
    } while (strncmp(buffer, MSG_STOP, strlen(MSG_STOP)));

    kill(pid, SIGTERM);//SIGTERM — сигнал для запроса завершения процесса.
/// Очистка
    CHECK((mqd_t)-1 != mq_close(req));
    CHECK((mqd_t)-1 != mq_close(resp));
    CHECK((mqd_t)-1 != mq_unlink(QUEUE_PARENT));//удаляет из системы имя, которое использовалось в качестве аргумента при вызове mq_open
    CHECK((mqd_t)-1 != mq_unlink(QUEUE_CHILD));

    exit(0);
}

void child_proc() {
    mqd_t req, resp;
    char buffer[MAX_SIZE+1];
    ssize_t bytes_read;
    double k1=0, k2=0, a1=0, a2=0;
    char *p1;
    sigset_t set;
    int sig;
    int must_stop =0;
    /* заблокируем SIGUSR1 */
    sigemptyset(&set);
    sigaddset(&set, SIGUSR1);
    CHECK(-1 != sigprocmask(SIG_BLOCK, &set, NULL));//sigprocmask используется, чтобы изменить список блокированных в данный момент сигналов
//SIG_BLOCK- Набор блокируемых сигналов - объединение текущего набора и аргумента set.
    resp = mq_open(QUEUE_PARENT, O_WRONLY);
    CHECK((mqd_t)-1 != resp);
    req = mq_open(QUEUE_CHILD, O_RDONLY);
    CHECK((mqd_t)-1 != req);

    do {
        sigwait(&set, &sig);//позволяет приостановить выполнении процесса до получения нужного сигнала(или одного из маски сигналов)
/*Получение катетов*/
        bytes_read = mq_receive(req, buffer, MAX_SIZE, NULL);
        CHECK(bytes_read >= 0);

        buffer[bytes_read] = '\0';
        if (! strncmp(buffer, MSG_STOP, strlen(MSG_STOP)))
        {
            must_stop = 1;
        }
        else
        {
        p1=strstr(buffer,", ");
        k1=atof(buffer);
        k2=atof(p1+1);
        printf("Дочерний процесс принял катеты прямоугольного треугольника: %.2f   %.2f\n", k1, k2);
        if(k1<=0 || k2<=0) {
        printf("Дочерний процесс обнаружил ошибку!\n");
        CHECK(0 <= mq_send(resp, "Ошибка! Введены неверные значения катетов!", MAX_SIZE , 0));
        fflush(stdout);}
        else{
        a1=atan(k1/k2);
        a1*=180/M_PI;
        a2=90-a1;
        sprintf(buffer, "%.2f, %.2f", a1, a2);
        printf("Дочерний процесс вернул величины острых углов прямоугольного треугольника: %s\n", buffer);
        CHECK(0 <= mq_send(resp, buffer, strlen(buffer), 0));
        fflush(stdout);}
        }
     } while (!must_stop);
}

Компилирование:
$ gcc mq.c -lrt -lm

Комментариев нет:

Отправить комментарий