Ich möchte ptrace
verwenden, um zu überprüfen, welches System ein von meinem Programm erzeugtes Programm aufruft. Ich begann von this tutorial, wie es in einer Antwort auf meine previous question erklärt wurde. Ich den Code modifiziert, indem sie auf die Plattform anzupassen ich verwende (SLES 11 64-Bit), und zusammen den folgenden Testcode, der erzeugte Prozess jedes System aufrufen druckt macht:Verwenden von ptrace aus Multithread-Anwendungen
#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;
}
Es funktioniert ziemlich gut : Es druckt die ID der Systemaufrufe, die vom Programm gemacht werden (tatsächlich druckt es jedes zweimal, einmal beim Eintritt und einmal beim Verlassen, aber das ist jetzt egal). Allerdings muss mein Programm andere Dinge tun, als die Systemaufrufe zu überprüfen, also entschied ich, die Überprüfung in einen separaten Thread zu verschieben (ich bin wohler mit C++ als C, also habe ich es C++ gemacht, aber ich glaube nicht, dass das wichtig ist). Natürlich starte ich in diesem Thest Programm nur den Thread und schließe mich dann an.
#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;
}
Dieses Mal habe ich eine Fehlermeldung erhalten:
Child process id = 24682.
Got event from 24682.
ptrace: No such process
Warum ist das? Ich habe versucht, nach einer Antwort zu suchen, fand aber nichts dergleichen. Ich habe festgestellt, dass ptrace
keine vom Kindprozess gestarteten Threads zurückverfolgen kann, aber das ist eine andere Sache, mit der später umgegangen werden muss. Ist das überhaupt möglich, um den Kindprozess von einem anderen Therad aus zu überprüfen?
Die andere seltsame Sache ist, dass ich in meiner realen Anwendung im Grunde dasselbe (aber aus einem viel komplizierteren Kontext: Klassen, Mutexe usw.), und ich bekomme eine andere Art von Fehler. Anstatt ptrace
mit einem Fehler zurückzukehren, kehrt wait
nicht einmal für Systemaufrufe auf dem untergeordneten Prozess zurück (und der untergeordnete Prozess wird nicht einmal beendet). Auf der anderen Seite funktioniert wait
wie erwartet, wenn der untergeordnete Prozess beendet wird.
Mit einem eigenen Thread zu meinem Prozess geholfen. – petersohn