Programowanie w unix, funcja fork, problem z zadaniem


(rafalski) #1

Witam. Nie mogę zrozumieć poniższego zadania, czy ktoś mógłby pomóc?

Napisać program run_cmd pozwalający na uruchomienie innego programu przekazanego w linii poleceń wra z argumetami. Program taki powinien najpierw utworzyć proces potomny, a następnie przy pomocy jednej z funkcji exec uruchomić program odczytany z linii poleceń, przy czym przy poszukiwaniu takiego programu powinny być uwzględniane katalogi znajdujące się w zmiennej środowiskowej PATH. Proces macierzysty ma wypisać na ekranie najpierw swój PID, PID procesu potomnego, a następnie kod wyjścia procesu potomnego. Proces potomny przed wywołaniem funkcji exec wypisuje na ekranie swój PID oraz PID procesu macierzystego.


Przykład: wywołanie

./run_cmd ls -l -a

Napisałem taki kod:

#include 

#include 


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

{

  int pid;

  pid=fork();

  printf("PID prosesu macierzystego %d\n", pid);

  if (pid<0)

  {

    fprintf(stderr, "Fork Failed");

    exit(-1);

  }

  else

    if (pid==0)

    {

      execlp("/bin/ls","ls",NULL);

      printf("PID prosesu potomnego %d\n", pid);

    }


    else

    {

      wait(NULL);

      printf("Child Complete");

      exit(0);

    }

};

(Xds) #2

W czym problem. Połowę już masz. Teraz tylko dopisać resztę :), UMK?


(rafalski) #3

Nie mam pojęcia jak zrobić by uruchamiało program z wiersza poleceń wraz z argumentami, czy może jakoś tak?

int execv(const char *path, char *argv[]);

Nie wiem, też czy mi ten pid wyświetla prawidłowy, bo coś mi się wydaje, że te funkcje trzeba ulokować w innym miejscu i użyć tych getpid i getppid. Tak wogle, to czym one się różnią?


(Xds) #4

Pamiętam, że jest kilka funkcji z rodziny exec. Myślę że, execv winno załatwić sprawę.

Z tym pid masz racje fork zwraca ci pid procesu dziecka. A ty wyświetlasz :slight_smile: go również

jako pid procesu ojca. Funkcje getpid i getppid różnią się tym, że pierwsza zwraca pid procesu

druga pid procesu rodzica to drugie "p" jest od parent.

#include 

    #include 


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

    {

      int pid;

      pid=fork();


      if (pid<0)

      {

        fprintf(stderr, "Fork Failed");

        exit(-1);

      }

      else

        if (pid==0)

        {

          execlp("/bin/ls","ls",NULL);

        }


        else

        {

          printf("PID prosesu rodzica %d\n", getpid());

          printf("PID prosesu dziecka %d\n", pid);

          wait(NULL);

          printf("Child Complete");

          exit(0);

        }

    };

(rafalski) #5

... nie rozumiem też tego polecenia "Proces macierzysty ma wypisać na ekranie najpierw swój PID, PID procesu potomnego, a następnie kod wyjścia procesu potomnego. Proces potomny przed wywołaniem funkcji exec wypisuje na ekranie swój PID oraz PID procesu macierzystego". To ile tych PID powinno być?

-- Dodane 20.11.2009 (Pt) 17:13 --

Napisałem coś takiegom tylko nie wiem jak zrobić, by ls uruchamiało mi z wiersza poleceń, tzn. by działało polecenie ./run_cmd ls -l -a (w programie niżej działa ./run_cmd -l -a)

#include 

#include 


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

{

  int pid, mojpid;


  pid=fork();

  mojpid=getpid();

  if (pid<0)

  {

    perror("Błąd utworzenia procesu potomnego");

    exit(1);

  }

  if (pid==0)

  {

    printf("%u: potomny\n", mojpid);

    execvp("ls", argv);

    perror("Błąd uruchomienia programu");

    exit(1);

  }

  else

  {

    printf("%u: macierzysty\n%u: potomny\n",mojpid, pid);

    wait(NULL);

    perror("Błąd w oczekiwaniu na zakończenie potomka");

    exit(0);

  }

};

(Marcin 110) #6
#include 

#include 

#include 

#include 


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

{

  int pid, mojpid, status;


  pid = fork();

  mojpid = getpid();


  if (pid < 0)

    {

      perror("Błąd utworzenia procesu potomnego");

      exit(1);

    }

  if (pid == 0)

    {

      printf("%u: potomny\n", mojpid);

      execvp(argv[1], argv + 1);

      perror("Błąd uruchomienia programu");

      exit(1);

    }

  else

    {

      printf("%u: macierzysty\n%u: potomny\n",mojpid, pid);

      if ((pid_t) -1 == waitpid(pid, &status, 0))

        perror("Błąd w oczekiwaniu na zakończenie potomka");

      else

        printf("%d: status potomka\n", WEXITSTATUS(status));

      exit(0);

    }

}

Mam tylko wątpliwości, czy argv[argc] w main jest zawsze NULLem, bo jest to wymagane przez execvp, ale na linuxie działa. Jeśli tego nie określa POSIX, to chyba lepiej skopiować tablicę argv i dorzucić NULL na koniec.