Лаба "Средства межпроцессного взаимодействия"
Написать программу, которая порождает дочерний процесс, и общается с ним через средства взаимодействия согласно варианту (Общие файлы), передавая и получая информацию согласно варианту (Родитель передает 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
Комментариев нет:
Отправить комментарий