БЕЛОРУССКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
ИНФОРМАТИКИ И РАДИОЭЛЕКТРОНИКИ
Кафедра программного обеспечения информационных технологий
Факультет ФКСиС
Специальность ПОИТ
Индивидуальная практическая работа №2
по дисциплине «Операционные системы и системное программирование.
Часть 1»
Выполнил студент: Бордон Е.С.
группа 991051
Зачетная книжка № 99105004
Минск 2021
Расчёт выбора варианта:
Номер паспорта :
Тк в первой таблице первого задания всего 16 вариантов
Значения табл.1 по заданию mod 16 = 3
Тк во второй таблице первого задания всего 14 вариантов
Значения табл.2 по заданию 1: mod 14 = 11
Во втором задании второй работы всего 19 вариантов:
Вариант задания 2: mod 19 = 12
Задание 1:
Создать дерево процессов согласно варианта индивидуального задания.
Процессы непрерывно обмениваются сигналами согласно табл. 2. Запись в таблице 1 вида: 1-> (2,3,4,5) означает, что исходный процесс 0 создаёт дочерний процесс 1, который, в свою очередь, создаёт дочерние процессы 2,3,4,5. Запись в таблице 2 вида: 1-> (2,3,4) SIGUSR1 означает, что процесс 1 посылает дочерним процессам 2,3,4 одновременно (т.е. за один вызов kill ()) сигнал SIGUSR1. После передачи 101–го по счету сигнала SIGUSR родительский процесс посылает сыновьям сигнал SIGTERM и ожидает завершения всех сыновей, после чего завершается. Сыновья, получив сигнал SIGTERM завершают работу с выводом на консоль сообщения вида:
Pid ppid завершил работу после X-го сигналаSIGUSR1 и Y-го сигналаSIGUSR2
где X, Y – количество посланных за все время работы данным сыном сигналов SIGUSR1 и SIGUSR2
Каждый процесс в процессе работы выводит на консоль информацию в следующем виде:
Npidppid послал/получил USR1/USR2 текущее время (мксек)
где N-номер сына по табл. 1
Дерево процессов:
1->(2,3) 2->(4,5) 5->6 6->(7,8)
Последовательность обмена сигналами:
1->(8,7,6,5)SIGUSR1 8->3 SIGUSR17->3 SIGUSR2
6->3 SIGUSR1 5->3 SIGUSR1 3->2 SIGUSR2 2->1 SIGUSR2
Решение:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/wait.h>
#include "sys/ipc.h"
#include <libgen.h>
#include "sys/shm.h"
#define TREE_COUNT 8
#define PERM S_IRUSR|S_IWUSR
char *exe_name;
int sig1 = 0, sig2 = 0;
pid_t gID, ppID;
struct sigaction sact;
size_t m_size;
key_t shmid_Tree;
pid_t *process_ID;
struct timeval curr_Time, start_Time, elapsed_Time;
void treeDo(int index);
void forestDo(int pID);
int getOrdForTree(int pid) {
for (int i = TREE_COUNT;; i--) if (process_ID[i] == pid) return i;
return -1;
}
void treeDo(int index) {
if (fork() == 0) {
process_ID = shmat(shmid_Tree, 0, 0);
process_ID[index] = getpid();
forestDo(process_ID[index]);
}
}
void forestDo(int pID) {
gID = getpgid(pID);
ppID = getppid();
int treeOrd = getOrdForTree(pID);
switch(treeOrd) {
case 1:
treeDo(2);
treeDo(3);
break;
case 2:
treeDo(4);
treeDo(5);
break;
case 3:
break;
case 4:
break;
case 5:
treeDo(6);
break;
case 6:
treeDo(7);
treeDo(8);
break;
case 7:
break;
case 8:
break;
default:
break;
}
while (1) pause();
}
int gettime()
{
gettimeofday(&curr_Time, NULL);
timersub(&curr_Time, &start_Time, &elapsed_Time);
return elapsed_Time.tv_usec/1000;
}
void manageTree1() {
sig1++;
if (sig1 + sig2 > 100) {
kill(process_ID[8], SIGTERM);
}
else {
printf("%d %d %d put SIGUSR1 %3d\n", 1, getpid(), getppid(), gettime());
kill(-getpgid(process_ID[2]), SIGUSR1);
}
}
void manageTree2() {
sig2++;
printf("%d %d %d put SIGUSR2 %3d\n", 2, getpid(), getppid(), gettime());
kill(process_ID[1], SIGUSR2);
}
void manageTree3() {
sig2++;
printf("%d %d %d put SIGUSR2 %3d\n", 3, getpid(), getppid(), gettime());
kill(process_ID[2], SIGUSR2);
}
void manageTree4() {
sig2++;
}
void manageTree5() {
sig1++;
printf("%d %d %d put SIGUSR1 %3d\n", 5, getpid(), getppid(), gettime());
kill(process_ID[3], SIGUSR1);
}
void manageTree6() {
sig1++;
printf("%d %d %d put SIGUSR1 %3d\n", 6, getpid(), getppid(), gettime());
kill(process_ID[3], SIGUSR1);
}
void manageTree7() {
sig1++;
printf("%d %d %d put SIGUSR2 %3d\n", 7, getpid(), getppid(), gettime());
kill(process_ID[3], SIGUSR2);
}
void manageTree8() {
sig1++;
printf("%d %d %d put SIGUSR1 %3d\n", 8, getpid(), getppid(), gettime());
kill(process_ID[3], SIGUSR1);
}
static void manage (int signal) {
int timer = gettime();
int tree_Num = getOrdForTree(getpid());
if (signal == SIGTERM) {
switch (tree_Num) {
case 1: waitpid(process_ID[1], 0, 0);
printf("%d %d %d done SIGUSR1: %3d, SIGUSR2: %3d\n", tree_Num, getpid(), ppID, sig1, sig2);
kill(process_ID[0],SIGTERM);
exit(EXIT_SUCCESS);
break;
case 0:
wait(NULL);
exit(EXIT_SUCCESS);
break;
default: // 2,3,4,5,6,7,8
printf("%d %d %d done SIGUSR1: %3d, SIGUSR2: %3d\n", tree_Num, getpid(), ppID, sig1, sig2);
kill(process_ID[tree_Num-1],SIGTERM);
exit(EXIT_SUCCESS);
break;
}
return;
}
if (signal == SIGUSR1) {
switch (tree_Num) {
case 5:
printf("%d %d %d get SIGUSR1 %3i\n", 5, getpid(), getppid(), timer);
manageTree5();
break;
case 6:
printf("%d %d %d get SIGUSR1 %3i\n", 6, getpid(), getppid(), timer);
manageTree6();
break;
case 7:
printf("%d %d %d get SIGUSR1 %3i\n", 7, getpid(), getppid(), timer);
manageTree7();
break;
case 8:
printf("%d %d %d get SIGUSR1 %3i\n", 8, getpid(), getppid(), timer);
manageTree8();
break;
}
return;
}
if (signal == SIGUSR2) {
switch (tree_Num) {
case 1:
printf("%d %d %d get SIGUSR2 %3i\n", 1, getpid(), getppid(), timer);
manageTree1();
break;
case 2:
printf("%d %d %d get SIGUSR2 %3i\n", 2, getpid(), getppid(), timer);
manageTree2();
break;
case 3:
printf("%d %d %d get SIGUSR2 %3i\n", 3, getpid(), getppid(), timer);
manageTree3();
break;
}
return;
}
return;
}
int main(int argc, char *argv[]) {
exe_name = basename(argv[0]);
m_size = (TREE_COUNT+1) * sizeof(pid_t);
if ((shmid_Tree = shmget(IPC_PRIVATE, m_size , PERM)) == -1 ) {
perror(exe_name);
exit(EXIT_FAILURE);
}
process_ID = shmat(shmid_Tree, 0, 0);
memset(process_ID, 0, m_size);
process_ID[0] = getpid();
sact.sa_handler = manage;
sigemptyset(&sact.sa_mask);
sact.sa_flags = 0;
if (sigaction(SIGUSR1, &sact, 0) != 0) perror(exe_name);
if (sigaction(SIGUSR2, &sact, 0) != 0) perror(exe_name);
if (sigaction(SIGTERM, &sact, 0) != 0) perror(exe_name);
if (fork() == 0) {
process_ID[1] = getpid();
forestDo(process_ID[1]);
} else {
process_ID[1] = process_ID[0]+1;
}
if (setpgid(process_ID[5], process_ID[2]) != 0) perror(exe_name);
if (setpgid(process_ID[6], process_ID[2]) != 0) perror(exe_name);
if (setpgid(process_ID[7], process_ID[2]) != 0) perror(exe_name);
if (setpgid(process_ID[8], process_ID[2]) != 0) perror(exe_name);
int flag = 0;
while (!flag) {
int temp = -1;
for (int i = 1; i <= TREE_COUNT; i++) {
temp = temp && process_ID[i];
}
flag = temp;
}
gettimeofday(&start_Time, NULL);
if (kill(process_ID[1], SIGUSR2) != 0) perror(exe_name);
pid_t wpid;
int status;
while (1) pause();
}
Результаты работы программы:
Рис1. Результат работы программы
Рис2. Результат работы программы
Задание 2:
Для заданного каталога (аргумент 1 командной строки) и всех его
подкаталогов вывести в заданный файл (аргумент 2 командной строки) и на
консоль имена файлов, их размер и дату создания, удовлетворяющих заданным
условиям: 1 – размер файла находится в заданных пределах от N1 до N2
(N1,N2задаются в аргументах командной строки), 2 – дата создания находится в заданных пределах от M1 до M2 (M1,M2задаются в аргументах командной
строки).Процедура поиска для каждого подкаталога должна запускаться в
отдельном процессе. Каждый процесс выводит на экран свой pid, полный путь, имя и размер просмотренного файла, общее число просмотренных файлов в
подкаталоге. Число запущенных процессов в любой момент времени не должно
превышать N (вводится пользователем). Проверить работу программы для каталога /usr/ размер31000 31500 дата с 01.01.1970 по текущую датуN=6. Для
взаимодействия процессов использовать сигналы. То же что и в п.3, но вместо процессов использовать потоки.