Создание 3 дочерних процессов и выход из них через указанное количество секунд - PullRequest
0 голосов
/ 12 февраля 2019

образ для того, какой вывод должен выглядеть: Моя проблема в том, что мне нужно написать программу, которая будет принимать имена трех процессов в качестве аргументов командной строки.Каждый из этих процессов будет работать столько же секунд, сколько: (PID% 10) * 3 + 5 и завершится.После того, как эти 3 дочерних элемента были прекращены, родительский процесс перенесет каждого дочернего элемента.Когда все дети будут перенесены 3 раза, родитель будет прерван.Я использовал fork, чтобы создать троих детей, но пытаюсь заставить их выйти по определенным критериям?

using namespace std;

int main(){
    int i;
    int pid;
    for(i=0;i<3;i++) // loop will run n times (n=3)
    {
        if(fork() == 0)
        {
            pid = getpid();
            cout << "Process p" << i+1 << " pid:" << pid << " Started..." << endl;
            exit(0);
        }
    }
    for(int i=0;i<5;i++) // loop will run n times (n=3)
    wait(NULL);

  }

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

Вы можете использовать sigtimedwait для ожидания SIGCHLD или тайм-аута.

Рабочий пример:

#include <cstdio>
#include <cstdlib>
#include <signal.h>
#include <unistd.h>

template<class... Args>
void start_child(unsigned max_runtime_sec, Args... args) {
    // Block SIGCHLD.
    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, SIGCHLD);
    sigprocmask(SIG_BLOCK, &set, nullptr);
    // Enable SIGCHLD.
    signal(SIGCHLD, [](int){});

    pid_t child_pid = fork();
    switch(child_pid) {
    case -1:
        std::abort();
    case 0: {
        // Child process.
        execl(args..., nullptr);
        abort(); // never get here.
    }
    default: {
        // paren process.
        timespec timeout = {};
        timeout.tv_sec = max_runtime_sec;
        siginfo_t info = {};
        int rc = sigtimedwait(&set, nullptr, &timeout);
        if(SIGCHLD == rc) {
            std::printf("child %u terminated in time with return code %d.\n", static_cast<unsigned>(child_pid), info.si_status);
        }
        else {
            kill(child_pid, SIGTERM);
            sigwaitinfo(&set, &info);
            std::printf("child %u terminated on timeout with return code %d.\n", static_cast<unsigned>(child_pid), info.si_status);
        }
    }
    }
}

int main() {
    start_child(2, "/bin/sleep", "/bin/sleep", "10");
    start_child(2, "/bin/sleep", "/bin/sleep", "1");
}

Вывод:

child 31548 terminated on timeout with return code 15.
child 31549 terminated in time with return code 0.
0 голосов
/ 13 февраля 2019

С этими изменениями ваша программа выдает желаемый результат:

#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <iostream>
using namespace std;

int main()
{
    for (int round = 0; ++round <= 4; )
    {
        int i;
        cout << "*** ROUND: " << round << " ***\n";
        for (i=0; i<3; i++) // loop will run n times (n=3)
        {
            if (fork() == 0)
            {
                int pid = getpid();
                cout << "Process p" << i+1 << " pid:" << pid << " started...\n";
                unsigned int seconds = pid%10*3+5;
                cout << "Process " << pid << " exiting after "
                     << seconds-sleep(seconds) << " seconds\n";
                exit(0);
            }
        }
        while (i--) // loop will run n times (n=3)
        {
            int status;
            cout << "Process " << wait(&status);
            cout << " exited with status: " << status << endl;
        }
    }
}
  • Как предположил Серж, мы используем sleep() для каждого ребенка перед его выходом.это приостановит процесс на несколько секунд .
  • Чтобы получить актуальную информацию о состоянии, мы вызываем wait(&status) вместо wait(NULL).
  • Мы делаем все этодля первого раунда планирования плюс желаемое 3 раза перепланирования.
...