Nakładanie obrazu procesu

Załóżmy, że uruchamiamy program i chcemy uruchomić inny program z bieżącego programu. czy to możliwe? Dlaczego nie, jeśli zaimplementujemy koncepcję nakładania obrazu procesu. W porządku, ale co z aktualnie działającym programem, czy można go również uruchomić. Jak to możliwe, skoro na bieżący program nałożyliśmy nowy. Co zrobić, jeśli chcę uruchomić oba programy bez utraty aktualnie uruchomionego programu, czy jest to możliwe? Tak to mozliwe.

Utwórz proces potomny, abyśmy mieli proces nadrzędny i nowo utworzony proces potomny. Już teraz uruchamiamy bieżący program w procesie nadrzędnym, więc uruchom nowo utworzony proces w dziecku. W ten sposób możemy uruchomić inny program z bieżącego programu. Nie tylko jeden program, ale możemy uruchomić dowolną liczbę programów z bieżącego programu, tworząc taką liczbę procesów potomnych.

Jako przykład rozważmy następujący program.

/ * Nazwa pliku: helloworld.c * /

#include<stdio.h>

void main() {
   printf("Hello World\n");
   return;
}

/ * Nazwa pliku: execl_test.c * /

#include<stdio.h>
#include<unistd.h>

void main() {
   execl("./helloworld", "./helloworld", (char *)0);
   printf("This wouldn't print\n");
   return;
}

Powyższy program nakładałby obraz procesu execl_test na helloworld. Z tego powodu kod obrazu procesu funkcji execl_test (printf ()) nie jest wykonywany.

Kroki kompilacji i wykonywania

Hello World

Teraz uruchomimy następujące dwa programy z jednego programu, tj. Execl_run_two_prgms.c.

  • Program Hello World (helloworld.c)

  • Program pętli While do drukowania od 1 do 10 (while_loop.c)

/ * Nazwa pliku: while_loop.c * /

/* Prints numbers from 1 to 10 using while loop */
#include<stdio.h>

void main() {
   int value = 1;
   while (value <= 10) {
      printf("%d\t", value);
      value++;
   }
   printf("\n");
   return;
}

Poniżej znajduje się program do uruchamiania dwóch programów (jeden program od dziecka i drugi program od rodzica).

/ * Nazwa pliku: execl_run_two_prgms.c * /

#include<stdio.h>
#include<unistd.h>

void main() {
   int pid;
   pid = fork();
   
   /* Child process */
   if (pid == 0) {
      printf("Child process: Running Hello World Program\n");
      execl("./helloworld", "./helloworld", (char *)0);
      printf("This wouldn't print\n");
   } else { /* Parent process */
      sleep(3);
      printf("Parent process: Running While loop Program\n");
      execl("./while_loop", "./while_loop", (char *)0);
      printf("Won't reach here\n");
   }
   return;
}

Note - Umieść wywołanie sleep (), aby upewnić się, że procesy potomne i nadrzędne działają sekwencyjnie (nie nakładają się na wynik).

Kroki kompilacji i wykonywania

Child process: Running Hello World Program
This wouldn't print
Parent process: Running While loop Program
Won't reach here

Teraz uruchomilibyśmy dwa programy z jednego programu, tj. Execl_run_two_prgms.c, ten sam program co powyżej, ale z argumentami wiersza poleceń. Tak więc uruchamiamy dwa programy, mianowicie helloworld.c w procesie potomnym i program while_loop.c w procesie nadrzędnym. Jest to następujące -

  • Program Hello World (helloworld.c)

  • Program pętli While do drukowania od 1 do num_times_str zgodnie z argumentami wiersza poleceń (while_loop.c)

Ten program zasadniczo wykonuje następujące czynności -

  • Tworzy proces potomny

  • Proces potomny wykonuje program helloworld.c

  • Proces macierzysty wykonuje program while_loop.c przekazując wartość argumentu wiersza poleceń jako argument do programu. Jeśli argumenty wiersza poleceń nie zostaną przekazane, przyjmowana jest wartość domyślna 10. W przeciwnym razie przyjmuje podaną wartość argumentu. Wartość argumentu powinna być liczbą; kod nie zostałby zweryfikowany, gdyby został podany w alfabecie.

/ * Nazwa pliku: execl_run_two_prgms.c * /

#include<stdio.h>
#include<string.h>
#include<unistd.h>

void main(int argc, char *argv[0]) {
   int pid;
   int err;
   int num_times;
   char num_times_str[5];
   
   /* In no command line arguments are passed, then loop maximum count taken as 10 */
   if (argc == 1) {
      printf("Taken loop maximum as 10\n");
      num_times = 10;
      sprintf(num_times_str, "%d", num_times);
   } else {
      strcpy(num_times_str, argv[1]);
      printf("num_times_str is %s\n", num_times_str);
      pid = fork();
   }
   
   /* Child process */
   if (pid == 0) {
      printf("Child process: Running Hello World Program\n");
      err = execl("./helloworld", "./helloworld", (char *)0);
      printf("Error %d\n", err);
      perror("Execl error: ");
      printf("This wouldn't print\n");
   } else { /* Parent process */
      sleep(3);
      printf("Parent process: Running While loop Program\n");
      execl("./while_loop", "./while_loop", (char *)num_times_str, (char *)0);
      printf("Won't reach here\n");
   }
   return;
}

Poniżej znajduje się program helloworld.c wywołany z procesu potomnego programu, execl_run_two_prgms.c.

/ * Nazwa pliku: helloworld.c * /

#include<stdio.h>

void main() {
   printf("Hello World\n");
   return;
}

Poniżej znajduje się program while_loop.c wywołany z procesu nadrzędnego programu, execl_run_two_prgms.c. Argument do tego programu jest przekazywany z programu, który go uruchamia, tj. Execl_run_two_prgms.c.

/ * Nazwa pliku: while_loop.c * /

#include<stdio.h>

void main(int argc, char *argv[]) {
   int start_value = 1;
   int end_value;
   if (argc == 1)
   end_value = 10;
   else
   end_value = atoi(argv[1]);
   printf("Argv[1] is %s\n", argv[1]);
   while (start_value <= end_value) {
      printf("%d\t", start_value);
      start_value++;
   }
   printf("\n");
   return;
}

Kroki kompilacji i wykonywania

Taken loop maximum as 10
num_times_str is 10
Child process: Running Hello World Program
Hello World
Parent process: Running While loop Program
Argv[1] is 10
1 2 3 4 5 6 7 8 9 10
Taken loop maximum as 15
num_times_str is 15
Child process: Running Hello World Program
Hello World
Parent process: Running While loop Program
Argv[1] is 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Zobaczmy teraz nakładające się funkcje biblioteki związane z obrazami.

#include<unistd.h>

int execl(const char *path, const char *arg, ...);

Ta funkcja nałożyłaby obraz aktualnie działającego procesu na nowy proces, jak wspomniano w argumentach, path i arg. Jeśli jakikolwiek argument musi zostać przekazany do nowego obrazu procesu, zostanie on przesłany przez argumenty „arg”, a ostatni argument powinien mieć wartość NULL.

Ta funkcja zwróci wartość tylko w przypadku błędu. Proces nakładania wywołań związanych z obrazem jest taki, jak wspomniano poniżej -

int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);

Te wywołania dotyczyłyby przekazywanych argumentów wiersza poleceń (argv []), zmiennych środowiskowych (envp []) i innych parametrów.