2012-11-14 14 views
5

Chcę użyć ptrace, aby sprawdzić, jakie wywołania systemowe program zrodził się w moim programie. Zacząłem od this tutorial, jak to wyjaśniono w odpowiedzi na moją previous question. I zmodyfikowany kod poprzez dostosowanie go do platformy używam (SLES 11 64 bit) i umieścić razem następujący kod testowy, który wypisuje każdy system nazywamy zrodził proces sprawia:Korzystanie z ptrace z aplikacji wielowątkowych

#include <sys/ptrace.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <sys/reg.h> 
#include <sys/syscall.h> /* For SYS_write etc */ 

pid_t child; 

void run() 
{ 
    long orig_eax; 
    int status; 

    while(1) { 
      int pid = wait(&status); 
      if (pid == -1) { 
       perror("wait"); 
       kill(child, SIGKILL); 
       return; 
      } 
      printf("Got event from %d.\n", pid); 
      if(WIFEXITED(status)) 
       break; 
      orig_eax = ptrace(PTRACE_PEEKUSER, 
        pid, 8 * ORIG_RAX, NULL); 
      if (orig_eax == -1) { 
       perror("ptrace"); 
       kill(child, SIGKILL); 
       return; 
      } else { 
       printf("Syscall %ld called.\n", orig_eax); 
      } 
      ptrace(PTRACE_SYSCALL, 
        pid, NULL, NULL); 
    } 
} 

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

    child = fork(); 
    if(child == 0) { 
     ptrace(PTRACE_TRACEME, 0, NULL, NULL); 
     execl(argv[1], argv[1], NULL); 
    } 
    else { 
     printf("Child process id = %d.\n", child); 
     run(); 

    } 
    return 0; 
} 

To działa bardzo dobrze : wypisuje identyfikator wywołań systemowych tworzonych przez program (w rzeczywistości wypisuje je dwa razy, raz przy wejściu i raz dla wyjścia, ale teraz to nie ma znaczenia). Jednak mój program musi wykonywać inne czynności poza sprawdzaniem wywołań systemowych, dlatego postanowiłem przenieść sprawdzanie do osobnego wątku (bardziej mi odpowiada C++ niż C, więc zrobiłem to w C++, ale ja nie myśl, że to ma znaczenie). Oczywiście w tym najstarszym programie, rozpoczynam tylko wątek, a następnie dołączam do niego.

#include <sys/ptrace.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <sys/reg.h> 
#include <sys/syscall.h> /* For SYS_write etc */ 

#include <boost/thread.hpp> 


pid_t child; 

void run() 
{ 
    long orig_eax; 
    int status; 

    while(1) { 
      int pid = wait(&status); 
      if (pid == -1) { 
       perror("wait"); 
       kill(child, SIGKILL); 
       return; 
      } 
      printf("Got event from %d.\n", pid); 
      if(WIFEXITED(status)) 
       break; 
      orig_eax = ptrace(PTRACE_PEEKUSER, 
        pid, 8 * ORIG_RAX, NULL); 
      if (orig_eax == -1) { 
       perror("ptrace"); 
       kill(child, SIGKILL); 
       return; 
      } else { 
       printf("Syscall %ld called.\n", orig_eax); 
      } 
      ptrace(PTRACE_SYSCALL, 
        pid, NULL, NULL); 
    } 
} 

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

    child = fork(); 
    if(child == 0) { 
     ptrace(PTRACE_TRACEME, 0, NULL, NULL); 
     execl(argv[1], argv[1], NULL); 
    } 
    else { 
     printf("Child process id = %d.\n", child); 
     boost::thread t(run); 
     t.join(); 
    } 
    return 0; 
} 

Tym razem pojawia się komunikat o błędzie:

Child process id = 24682. 
Got event from 24682. 
ptrace: No such process 

dlaczego tak jest? Próbowałem szukać odpowiedzi, ale niczego takiego nie znalazłem. Zauważyłem, że ptrace nie będzie śledzić wątków rozpoczętych przez proces potomny, ale jest to kolejna rzecz, z którą należy sobie poradzić później. Czy to możliwe, aby sprawdzić proces potomny z innego termo?

Inną dziwną rzeczą jest to, że w mojej prawdziwej aplikacji robię zasadniczo to samo (ale z dużo bardziej skomplikowanego kontekstu: klasy, muteksy itp.) I otrzymuję inny rodzaj błędu. Zamiast ptrace powraca z błędem, wait nie zwraca nawet dla wywołań systemowych w procesie potomnym (a proces potomny nawet się nie zatrzymuje). Z drugiej strony, wait działa zgodnie z oczekiwaniami, gdy proces potomny zostanie zakończony.

Odpowiedz

1

O ile mogę powiedzieć, ptrace pozwala tylko jeden znacznik na proces. Oznacza to, że jeśli chcesz dołączyć, które można spróbować i zmusić go PTRACE_ATTACH, otrzymasz błąd, mówiąc, że ptrace nie był w stanie dołączyć do określonego procesu.

W ten sposób pojawia się błąd, ponieważ wątek nie jest dołączony do procesu podrzędnego, a w ten sposób, gdy próbujesz wykonać ptrace, nie powiedzie się, wysyłając kod -ESRCH.

Co więcej, możesz rzucić okiem na this post here, to może odpowiedzieć na kilka innych pytań, które możesz mieć poza tym.

+0

Posiadanie dedykowanego wątku mój proces pomógł. – petersohn