Как правильно использовать системный вызов exec() после форка?

#c #exec #fork

#c #exec #форк

Вопрос:

У меня возникли проблемы с моей программой, я хочу, чтобы моя функция run_uptime отображала выходные данные функции uptime каждые 5 секунд в stdout. Тем не менее, я не знаю, что я делаю неправильно в своем коде, я просмотрел различные другие вопросы, связанные с exec() и fork(), но, похоже, я все еще не могу найти решение. Еще одна вещь, как я могу переписать вызов fork без оператора switch , но это скорее эстетическая причина, но я все равно хочу знать, как это сделать. Я был бы признателен за любую помощь. Пожалуйста, объясните, почему, потому что я новичок.

Постановка проблемы, что должна делать программа:

Вы должны создать программу, которая выполняет следующее:

o При запуске считайте общее время выполнения (в секундах), в течение которого пользователь хочет запустить программу. Значение по умолчанию 10 секунд будет использоваться, если пользователь не указывает время при запуске программы (т.Е. rohan> a3 30 заставляет программу работать в течение 30 секунд, rohan> a3 вы бы запустили программу в течение 10 секунд).

o Программа должна создать три дочерних процесса, затем busy-подождите, пока все дочерние процессы не будут завершены, а затем завершите работу.

o Первый дочерний процесс должен реализовать часы, которые печатают час, минуту и секунду раз в секунду (в удобочитаемом локальном времени)

o Второй дочерний процесс должен запускать программу времени безотказной работы (/usr/bin/ uptime) каждые 5 секунд

o Третий дочерний процесс должен реализовать таймер обратного отсчета, который печатает оставшиеся минуты и секунды раз в секунду до достижения 00:00.

o Третий дочерний процесс, по достижении 00:00, должен уведомить (сигнализировать, или передавать, или … и т. Д., Ваш выбор механизма IPC) первый и второй дочерние процессы ’ (т. Е. Это процессы-братья), сообщающие им о завершении, а затем завершают себя.

o После завершения всех дочерних процессов родительский должен напечатать дружественное сообщение, а затем выйти.

Вот мой код, он компилируется, но мне нужен другой вывод.

 /* Include Files */
#include <stdio.h>
#include <time.h> /* for local time functions */
#include <unistd.h> /* for fork */
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h> /* for wait function */
#include <sys/types.h> /* for pid_t */

/* remember 0 means program finished correctly, by unix convention */

/* Definitions */
#define TIME_QUANTUM 5 //Default time for program to run!

/* Functions */
void system_clock(void); //function to display human readable time.
void time_to_kill(int timequota); //prints out the time in a countdown fashion, till program ends.
void run_uptime(void);

/* Variables */
int procpipe1[2]; //Allocate Pipe Set 1
int procpipe2[2]; //Allocate Pipe Set 2
char bufkill[12]; //Buffer to hold kill signal, to tell other processes to end.


    int main(int argc, const char * argv[])
{
    int time=TIME_QUANTUM;
    if(argc==2)
    {
        time=atoi(argv[1]); //looking to see if user wants a custom running time.
    }

   //Creating pipes before creating child processes, so they could communicate.
   pipe(procpipe1);
   pipe(procpipe2);

   printf("Pipes opened, now creating child process!n");

    //Create Child Processes and run associated functions in them.
    //Creating the the 1st child process!

    switch (fork())
    {
        case -1:
            printf("Error: couldn't create 1st Child!n");
            exit(1);

        case 0: //If no error in creating child process then create process!
            printf("nChild 1 process: time_to_kill executing...n");
            system_clock();
            exit(1);

        default:
            break;
    }

    //Creating the 2nd child process!
    switch (fork())
    {
        case -1:
            printf("Error: couldn't create 3rd Child!n");
        case 0: //If no error in creating child process then create process!
            printf("nChild 2 process: time_to_kill executing...n");
            run_uptime();
            exit(1);

        default:
            break;
    }

    //Creating the 3rd child process!
    switch (fork())
    {
        case -1:
            printf("Error: couldn't create 2nd Child!n");
            exit(1);
        case 0: //If no error in creating child process then create process!
            printf("nChild 3 process: time_to_kill executing...n");
            time_to_kill(time); 
            exit(1);

        default:
            break;
    }

    printf("Parent closing pipesn");

    //Need to close the pipes after using them, close communications between processes.
    //pipe close error checking

    close(procpipe1[0]);
    close(procpipe1[1]);
    close(procpipe2[0]);
    close(procpipe1[1]);

    printf("Parent waiting for children completion...n");

    //Wait for child processes to end before ending Main, the overall process 
    //that spawned the child processes.

    wait(NULL);
    wait(NULL);
    wait(NULL);

    printf("Time to print out a Friendly Message!n");
    printf("Parent process finishing, bye!n");
    exit(EXIT_SUCCESS);   
}//end main

//This is the 1st Child Process
void system_clock(void) 
{
    /* variable of system_clock()*/
    //temp buffer to get termination string
    char str1[12];
    time_t now;
    struct tm *lcltime;

    strcpy(str1, "time to die"); //store this string into str1 local variable

    close(procpipe1[0]);
    close(procpipe1[1]);
    close(procpipe2[1]);

    //show current time
    for(;;)
    {
        now = time ( NULL );
        lcltime = localtime ( amp;now );

        //read message from child 2 process
        int status = read(procpipe2[0], bufkill, 12);

        if ((strcmp(str1, bufkill)) != 0)
        {
            //printf("Read status: %d, Buffer= %sn", status, bufkill);
            printf ("The time is %d:%d:%dn", lcltime->tm_hour, lcltime->tm_min, lcltime->tm_sec );
            //show ever second
            sleep(1);
        }


        //if end signal came in
        //if(ret == 0)
        if ((strcmp(str1, bufkill)) == 0)
        {
            //close reading end
            close(procpipe2[0]);

            //return back to parent
            printf("Child 1 process: system_clock ending...n");
            exit(1);
        }
    }  
}//end system_clock

//This is the 2nd Child Process
void run_uptime() 
{
    // variable of run_uptime
    //temp buffer to get termination string
    char str1[12];

    strcpy(str1, "time to die"); //store this string into str1 local variable

    close(procpipe1[0]);
    close(procpipe1[1]);
    close(procpipe2[1]);    

    for(;;)
    {
        //read message from child 2 process
        int status = read(procpipe2[0], bufkill, 12);

        if ((strcmp(str1, bufkill)) != 0)
        {
            //printf("Read status: %d, Buffer= %sn", status, bufkill);
            execl("/usr/bin/uptime","uptime",NULL);
            //show ever 5 seconds
            sleep(1);
        }


        //if end signal came in
        if ((strcmp(str1, bufkill)) == 0)
        {
            //close reading end of pipe.
            close(procpipe2[0]);

            //return back to parent
            printf("Child 2 process: run_uptime ending...n");
            exit(1);
        }
    }  
}//end run_uptime

//This is the 3rd Child Process
void time_to_kill(int timequota) //This process signals the other processes to stop.
{
    /* Need to change this signal */
    //string signal to end process 
    strcpy(bufkill, "time to die");

    //Pipes that aren't being used close them.
    close(procpipe1[0]);
    close(procpipe1[1]);
    close(procpipe2[0]);

    for( ;timequota>0; timequota--)
    {
        printf("Count Down: 00:0%dn", timequota);
        //send signal to child 1 process and child 2 process not to end
        write(procpipe2[1], "not die yet",12); //write into pipe2 statement that doesn't signal stopping process.
        //count down every second
        sleep(1);
    }

    //send signal to child 1 process and child 2 process to be terminate itself.
    write(procpipe2[1], bufkill, sizeof(bufkill)); //write into pipe2 the kill statement stored in bufkill

    //close pipe 2 writing end
    close(procpipe2[1]); 

    //back to main
    printf("Count Down: 0n");
    printf("Child 3 process: time_to_kill ending...n");
    exit(1);
}//end time_to_kill
 

Комментарии:

1. Из кода, который вы показываете, вы не хотите exec*() , но system() или popen() или posix_spawn() , если доступно. exec*() Функции не возвращаются. Возможно, вам захочется внимательно прочитать man 3 exec .

2. Я добавил в свой вопрос формулировку проблемы и то, что должна делать моя программа.

3. Мне не разрешено использовать system, и мне разрешено использовать только exec() и его производные.

4. При обработке ошибок для второго форка пропускается «выход». «man wait» не говорит, что «wait (NULL)» разрешено. execl в thread2 заменит дочерний процесс программой времени безотказной работы, поэтому вашего run_uptime больше не будет. Ваши три функции никогда не возвращаются, поэтому нет необходимости завершать () после них. Если вы получаете сигнал во время чтения, может быть прочитана только часть сообщения, и вы не распознаете сообщение правильно.

5. Я предложил альтернативы exec*() в своем первом комментарии.