Цель работы:
Изучение механизма межпроцессных коммуникаций, предоставляемых ОС Linux, использующего общую память. Знакомство с функциями IPC для создания и управления сегментами общей памяти.
Описание программы:
Главный процесс (main) создает потоки, количество которых вводится в командной строке до максимального значения (100) Каждый поток создает процесс, являющийся дочерним по отношению к главному процессу. Родительский процесс создает по два неименованных канала для каждого дочернего процесса и ожидает завершения всех запущенных процессов, а также потоков, в которых они выполняются. Кроме того, через случайный интервал времени от 1 до 5 секунд главный процесс отправляет каждому дочернему процессу по очереди случайное число от 0 до 30. На основании принятого числа дочерний процесс вычисляет случайное число от 1 до 31 (т.е. максимальное число на единицу больше максимального числа, передаваемого из главного процесса) и прибавляет его к уже вычисленным числам. Как только сумма становится больше 44 (число выбрано в знак уважения к панк - группе SUM 44), дочерний процесс оповещает родительский процесс, за что тот убивает его сигналом SIGKILL. Сам же родительский процесс нечувствителен к сигналу прерывания SIGINT (комбинации Ctrl+C). После убийства всех дочерних процессов и завершения потоков, в которых они выполнялись, родительский процесс завершается. Графическое описание программы приведено на рисунке
Листинг программы
#include <sys/wait.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
const SIZE=1000;
char buf1[1000], buf2[1000], msg[1000];
int n, i, pid[100], sum[100], k[100], status[100], fd1[100][2], fd2[100][2];
pthread_t thr[100];
time_t T;
pthread_mutex_t syn;
void snd(int p1, int p2, char buf[SIZE], int fd[2], char msg[SIZE])
{
close(fd[0]);
strcpy(buf, msg);
write(fd[1], buf, strlen(buf) + 1);
}
void get(int p1, int p2, char buf[SIZE], int fd[2])
{
close(fd[1]);
read(fd[0], buf, SIZE);
}
void *thread(void *p)
{
int i = (int)p;
if ((pid[i] = fork()) < 0)
{
perror("fork error\n"); exit(1);
}
if (!pid[i])
{
pthread_mutex_lock (&syn);
time(&T);
printf("|%d\t|%d\t|start\t|\t|%s\n", i, getpid(), ctime(&T));
pthread_mutex_unlock (&syn);
sum[i] = k[i] = 0;
while(1)
{
time(&T);
snd(i, 0, buf1, fd1[i], "info");
get (i, 0, buf2, fd2[i]);
int b = atoi(buf2);
sum[i] += abs(b*(rand()/(RAND_MAX + 1.0))) + 1;
printf("|%d\t|%d\t|\t|%d\t|%s\n", i, getpid(), sum[i], ctime(&T));
if (sum[i] >44) snd(i, 0, buf1, fd1[i], "end");
usleep(100000*(abs(40*(rand()/(RAND_MAX +1.0))) + 10));
}
}
}
int main(int argc, char *argv[])
{
printf(" ________________________________________________________\n");
printf("|no.\t|pid\t|status\t|sum\t|time \n");
printf(" ________________________________________________________\n");
signal(SIGINT, SIG_IGN);
pthread_mutex_init (&syn, NULL);
n = atoi(argv[1]);
for (i = 1; i <= n; i++)
{
if ((pipe(fd1[i]) == -1)||(pipe(fd2[i]) == -1))
{
perror("pipe error");
exit(1);
}
pthread_create(&thr[i], NULL, thread, (void *)i);
}
while(1)
{
for (i = 1; i <= n; i++)
{
double t = abs((30*(rand()/(RAND_MAX + 1.0)))) + 2.0;
char b[SIZE];
gcvt(t, 2, b);
if (!k[i])
{
snd(0, i, buf2, fd2[i], b);
get(i, 0, buf1, fd1[i]);
if (strcmp(buf1, "end") == 0)
{
time(&T);
kill(pid[i], SIGKILL);
printf("|%d\t|%d\t|stopped|\t|%s\n", i, getpid(), ctime(&T));
k[i] = 1;
}
}
usleep(100000*(abs(40*(rand()/(RAND_MAX +1.0))) + 10));
}
int a = 0;
for (i = 1; i <= n; i++)
if (!k[i]) a = 1;
if (!a) break;
}
for (i = 1; i <= n; i++)
{
waitpid(pid[i], &status[i], WUNTRACED);
pthread_join(thr[i], NULL);
}
printf("|________________________________________________________\n");
return 0;
}
Результаты выполнения программы
Вывод:
В работе мы ознакомились с принципом организации канала, а так же методами защиты кода от доступа других приложений или процессов.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.