Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лабы, Разумовский / 3_laba / ООПЛинукс_3л

.docx
Скачиваний:
0
Добавлен:
30.09.2026
Размер:
172 Кб
Скачать
☆

МИНОБРНАУКИ РОССИИ

Санкт-Петербургский государственный

электротехнический университет

«ЛЭТИ» им. В.И. Ульянова (Ленина)

Кафедра ВТ

отчет

по лабораторной работе №3

по дисциплине «Организация процессов и программирование в среде Linux»

Тема: Создание и идентификация процессов

Студент гр.

Преподаватель

Разумовский Г.В.

Санкт-Петербург

2026

Цель работы

Изучение и использование системных функций, обеспечивающих порождение и идентификацию процессов

Задание

Разработать программу, которая порождает 2 потомка. Первый потомок порождается с помощью fork, второй - с помощью vfork с последующей заменой на другую программу. Все 3 процесса должны вывести в один файл свои атрибуты с предварительным указанием имён процесса. Имя выходного файла задаётся при запуске программы. Порядок вывода атрибутов в файл должен определяться задержками процессов, которые задаются в качестве параметров программы и выводятся в начало файла. Откомпилировать программу и запустить ее 3 раза с различными сочетаниями задержек.

Распечатка тестовой программы

own_prog.cpp

#include <iostream>

#include <fstream>

#include <unistd.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <cstdlib>

using namespace std;

void writeAttributes(const char* procName, const char* filename, int delay) {

    sleep(delay);

    ofstream out(filename, ios::app);

    out << "❤️❤️❤️❤️❤️ " << procName << " ❤️❤️❤️❤️❤️\n";

    out << "Идентификатор процесса (PID): " << getpid() << "\n";

    out << "Идентификатор предка (PPID): " << getppid() << "\n";

    out << "Идентификатор сессии процесса (SID): " << getsid(0) << "\n";

    out << "Идентификатор группы процессов (PGID): " << getpgid(0) << "\n";

    out << "Реальный идентификатор пользователя (UID): " << getuid() << "\n";

    out << "Эффективный  идентификатор пользователя (EUID): " << geteuid() << "\n";

    out << "Реальный групповой идентификатор (GID): " << getgid() << "\n";

    out << "Эффективный групповой идентификатор (EGID): " << getegid() << "\n";

    out << "+++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n";

    out.close();

}

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

    if (argc != 5) {

        cerr << "Usage: " << argv[0] << " <file> <delay_parent> <delay_child1> <delay_child2>\n";

        return 1;

    }

   

    const char* filename = argv[1];

    int delayParent = atoi(argv[2]);

    int delayChild1 = atoi(argv[3]);

    int delayChild2 = atoi(argv[4]);

   

    // Записываем параметры

    ofstream out(filename);

    out << "Параметры:\nЗадержка предка: " << delayParent << "\nЗадержка первого потомка: " << delayChild1 << "\nЗадержка второго потомка " << delayChild2 << "\n\n";

    out.close();

   

    // Первый потомок через fork

    pid_t pid1 = fork();

    if (pid1 == 0) {

        writeAttributes("Первый потомок", filename, delayChild1);

        exit(0);

    }

   

    // Второй потомок через vfork

    pid_t pid2 = vfork();

    if (pid2 == 0) {

        // Заменяем на другую программу

        execl("./child", "child", filename, argv[4], NULL);

        _exit(1);

    }

   

    // Пишем атрибуты родителя

    writeAttributes("Предок", filename, delayParent);

   

    cout << "Done! Check " << filename << "\n";

    return 0;

}

child.cpp

#include <iostream>

#include <fstream>

#include <unistd.h>

#include <sys/types.h>

using namespace std;

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

    if (argc != 3) return 1;

   

    const char* filename = argv[1];

    int delay = atoi(argv[2]);

   

    sleep(delay);

   

    ofstream out(filename, ios::app);

    out << "❤️❤️❤️❤️❤️ Второй потомок ❤️❤️❤️❤️❤️\n";

    out << "Идентификатор процесса (PID): " << getpid() << "\n";

    out << "Идентификатор предка (PPID): " << getppid() << "\n";

    out << "Идентификатор сессии процесса (SID): " << getsid(0) << "\n";

    out << "Идентификатор группы процессов (PGID): " << getpgid(0) << "\n";

    out << "Реальный идентификатор пользователя (UID): " << getuid() << "\n";

    out << "Эффективный  идентификатор пользователя (EUID): " << geteuid() << "\n";

    out << "Реальный групповой идентификатор (GID): " << getgid() << "\n";

    out << "Эффективный групповой идентификатор (EGID): " << getegid() << "\n";

    out << "+++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n";

    out.close();

   

    return 0;

}

Результат выполнения программы с разными сочетаниями задержек

При сочетании задержек 1, 2, 3 секунды (предок, потомок 1, потомок 2 соответственно) первым завершает работу процесс-предок. В результате в выходной файл для обоих потомков записывается PID субрепера, а не исходного предка

При сочетании задержек 3, 2, 1 порядок завершения обратный: сначала 2 потомок, затем потомок 1, и в конце - предок. Поскольку на момент завершения потомков родитель всё ещё активен, в файл для них корректно записывается PID исходного предка.

При сочетании задержек 2, 1, 3 секунды потомок 1 завершается первым и успевает записать PID живого предка. Потом завершается сам предок, а потомок 2 к моменту завершения остаётся без предка, усыновляется субрепером и записывает его PID.

Рисунок 1 - Результат выполнения для сочетания задержек 1, 2, 3 секунд

Рисунок 2 - Результат выполнения для сочетания задержек 3, 2, 1 секунд

Рисунок 3 - Результат выполнения с сочетанием задержек 2, 1, 3 секунд

Вывод

В рамках лабораторной работы были рассмотрены механизмы создания процессов в ОС Linux, изучены их атрибуты и особенности взаимодействия в системе отношений «родитель -потомок».

Была реализована программа, создающая два дочерних процесса: первый - с помощью системного вызова fork(), второй - посредством vfork() с последующей заменой образа выполняемой программы через execl(). Все три процесса записывали свои атрибуты в общий текстовый файл, имя которого передавалось в качестве аргумента при запуске. Последовательность записи регулировалась временными задержками, также задаваемыми через параметры командной строки.

В ходе экспериментов было подтверждено, что порядок завершения процессов напрямую зависит от величины заданных задержек: процесс с наименьшей задержкой первым выполняет запись атрибутов и завершает работу. Выявлено, что при отсутствии вызова waitpid() родительский процесс не ожидает завершения дочерних, из-за чего при определённых комбинациях задержек потомки теряют родителя и передаются на обслуживание процессу -субреперу. Данный факт находит отражение в изменении значения, возвращаемого функцией getppid(): вместо PID исходного родителя потомки получают PID процесса -усыновителя.

Кроме того, установлено, что при усыновлении идентификаторы группы процессов (PGID) и сессии (SID) остаются неизменными: дочерние процессы сохраняют значения, унаследованные от исходного родителя, на всём протяжении своего существования.

10

Соседние файлы в папке 3_laba