2012-11-14 47 views
5

我想用ptrace檢查什麼系統調用我的計劃催生了一個程序使得使用ptrace的。我從this tutorial開始,因爲它是在對我的previous question的回答中解釋的。我被它適應我使用的平臺修改代碼(SLES 11 64位),並放在一起打印出每一個系統下面的測試代碼中調用產生的進程,使得:從多線程應用程序

#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; 
} 

它工作得很好:它打印由程序進行的系統調用的ID(實際上它打印每個兩次,一次在入口處,一次用於退出,但現在無關緊要)。但是,除了檢查系統調用之外,我的程序還需要做其他事情,所以我決定將檢查移至單獨的線程中(我比C更適合使用C++,所以我使用C++方式,但是我不要以爲重要)。當然,在這個最新的程序中,我只啓動線程然後加入它。

#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; 
} 

這一次,我得到一個錯誤信息:

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

這是爲什麼?我試圖尋找答案,但沒有發現這樣的事情。我發現ptrace不會跟蹤由子進程啓動的線程,但這是另一件事情需要以後處理。這甚至有可能從一個不同的戰場檢查孩子進程嗎?

另一個奇怪的是,我在實際應用中我做的基本上是同樣的事情(但是從一個更復雜的背景:類,互斥等),我也得到一個不同類型的錯誤。而不是ptrace返回一個錯誤,wait甚至不會返回子進程上的系統調用(並且子進程甚至不會停止)。另一方面,當子進程退出時,wait按預期工作。

回答

1

據我所知,ptrace允許每個過程只是一種示蹤劑。這意味着,如果你試圖連接,你可以試着和PTRACE_ATTACH迫使它,您將收到一條錯誤,告訴ptrace是無法連接到指定的進程。

因此,您的錯誤出現是因爲您的線程未附加到子進程,並且這樣,當您嘗試ptrace它時,它會失敗,併發送-ESRCH代碼。

此外,還可以在this post here看看,它可能會回答一些其他問題,你可能有除了這一個。

+0

有一個專門的線程來處理我的幫助。 – petersohn