Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define MAX_AMOUNT_OP_PROCESSES 500
- #include <unistd.h>
- #include <signal.h>
- #include <sys/wait.h>
- #include <termios.h>
- #include <ncurses.h>
- #include <vector>
- #include <iostream>
- using namespace std;
- vector<pid_t> procInfo; // Вектор идентификаторов процессов
- struct sigaction printSignal; // Указатель на структуру Sigaction, обработчика сигналов
- bool Print = true; // Переменная для проверки разрешения на печать
- char parentPID[256]; // Переменная для заполнения идентификатором родителя
- int counter= 0; // Счетчик процессов
- int myGetch() // Реализация функции getch() для *nix систем
- {
- struct termios oldattr, newattr;
- int ch;
- tcgetattr(STDIN_FILENO, &oldattr);
- newattr = oldattr;
- newattr.c_lflag &= ~(ICANON | ECHO);
- tcsetattr(STDIN_FILENO, TCSANOW, &newattr);
- ch = getchar();
- tcsetattr(STDIN_FILENO, TCSANOW, &oldattr);
- return ch;
- }
- void setPrint(int sig) // Проверка на возможность печати
- {
- if (procInfo.size()) // Проверка есть ли содержимое в векторе
- {
- if (++counter >= procInfo.size()) // Если counter выходит за рамки количества процессов
- counter = 0; // то обнуляем его
- napms(150); // приостановить процесс вызова
- kill(procInfo[counter], SIGUSR1); // вызов процессов
- }
- else {
- Print = true;
- }
- }
- void initSignalHandlers() // Установка значений структуры sigaction
- {
- printSignal.sa_handler = setPrint; // Обработчик сигнала старого стиля устанавливается в разрешенное для печати состояние
- printSignal.sa_flags = SA_RESTART; // Флаг восстановление прерванных системных вызовов после выхода из обработчика
- sigaction(SIGUSR1, // Номер сигнала
- &printSignal, // Указатель на структуру Sigaction
- NULL); // если null то будет вызывать старый обработчик сигналов, без установки нового
- }
- void addOneProcess()
- {
- procInfo.push_back(fork()); // Создаем дубликат родительского процесса и добавляем новый pid в вектор
- if (procInfo.back() == 0) { // Проверка на пустоту вектора
- char instanceID[10]; // Сюда помещается текущее количество процессов
- sprintf(instanceID, "%d", procInfo.size()); // Заполнение буфера текущим значением кол-ва процессов
- if (execlp("./child", instanceID, parentPID, NULL) == -1) { // Попытка вызвать новый процесс с переданными значениями командной строки в виде pid parent и кол-ва процессов
- procInfo.pop_back(); // Если не удалось то удалить значение из вектора
- cout << "Error in execlp." << endl;
- }
- }
- }
- void removeOneProcess()
- {
- kill(procInfo.back(), SIGUSR2); // Передача сигнала на закрытие процесса
- waitpid(procInfo.back(), NULL, 0); // Приостанавливает выполнение текущего процесса до тех пор, пока дочерний процесс, указанный в параметре pid, не завершит выполнение
- procInfo.pop_back(); // Удаление последнего значения из вектора
- }
- void showOptionList()
- {
- system("clear");
- cout << "Press..\n";
- cout << " '+' to create new child;" << endl;
- cout << " '-' to delete last child;" << endl;
- cout << " 'q' to quit;\n" << endl;
- }
- int main()
- {
- showOptionList();
- initSignalHandlers();
- sprintf(parentPID, "%d", getpid()); // Получение pid родительского процесса
- while (true) {
- switch(myGetch()) {
- case '+':
- if(procInfo.size() < MAX_AMOUNT_OP_PROCESSES)
- {
- addOneProcess(); // Добавление нового процесса
- if (Print == true) {
- napms(150);
- kill(procInfo.back(), SIGUSR1); // Вызов сигнала SIGUSR1 для нового процесса
- Print = false;
- }
- }
- break;
- case '-':
- if (!procInfo.empty())
- {
- if (counter == procInfo.size() - 1) {
- removeOneProcess();
- raise(SIGUSR1); // Отправляет сигнал вызывающему процессу или потоку
- }
- else
- {
- removeOneProcess();
- }
- }
- break;
- case 'q':
- while (!procInfo.empty()) { // Очистка системы от процессов
- removeOneProcess();
- }
- return 0;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement