Estoy intentando codificar un programa que se rastrea a sí mismo para las llamadas al sistema. Estoy teniendo un momento difícil para hacer este trabajo. Intenté llamar a un tenedor() para crear una instancia de sí mismo (el código) y luego supervisar el proceso hijo resultante.¿Cómo rastrear un proceso para llamadas al sistema?
El objetivo es que el proceso principal devuelva el índice de cada llamada al sistema realizada por el proceso hijo y lo muestre en la pantalla. De alguna manera, no está funcionando según lo planeado.
Aquí está el código:
#include <unistd.h> /* for read(), write(), close(), fork() */
#include <fcntl.h> /* for open() */
#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/reg.h>
#include <sys/wait.h>
#include <sys/types.h>
int main(int argc, char *argv[]) {
pid_t child;
long orig_eax;
child = fork();
if (0 == child)
{
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
if (argc != 3) {
fprintf(stderr, "Usage: copy <filefrom> <fileto>\n");
return 1;
}
int c;
size_t file1_fd, file2_fd;
if ((file1_fd = open(argv[1], O_RDONLY)) < 0) {
fprintf(stderr, "copy: can't open %s\n", argv[1]);
return 1;
}
if ((file2_fd = open(argv[2], O_WRONLY | O_CREAT)) < 0) {
fprintf(stderr, "copy: can't open %s\n", argv[2]);
return 1;
}
while (read(file1_fd, &c, 1) > 0)
write(file2_fd, &c, 1);
}
else
{
wait(NULL);
orig_eax = ptrace (PTRACE_PEEKUSER, child, 4 * ORIG_EAX, NULL);
printf("copy made a system call %ld\n", orig_eax);
ptrace(PTRACE_CONT, child, NULL, NULL);
}
return 0;
}
Este código se basa en este código:
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <linux/user.h> /* For constants
ORIG_EAX etc */
int main()
{
pid_t child;
long orig_eax;
child = fork();
if(child == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
execl("/bin/ls", "ls", NULL);
}
else {
wait(NULL);
orig_eax = ptrace(PTRACE_PEEKUSER,
child, 4 * ORIG_EAX,
NULL);
printf("The child made a "
"system call %ld\n", orig_eax);
ptrace(PTRACE_CONT, child, NULL, NULL);
}
return 0;
}
La salida de éste es:
The child made a system call 11
que es el índice de la llamada al sistema ejecutivo.
De acuerdo con las páginas man de espera():
All of these system calls are used to wait for state changes in a child
of the calling process, and obtain information about the child whose
state has changed. A state change is considered to be: the child terminated;
the child was stopped by a signal; or the child was resumed by
a signal.
La manera en que yo entiendo es que cada vez que una llamada al sistema es invocado por un programa de usuario, el kernel primera inspeccionará si el proceso está siendo rastreado antes de ejecutar la rutina de llamada del sistema y pausa ese proceso con una señal y devuelve el control al padre. ¿No sería eso un cambio de estado?
"De alguna manera no funciona según lo previsto." ¿Cuidado para elaborar? ¿Qué espera que suceda, y qué sucede en realidad? Por favor edita la pregunta para agregarla, no como un comentario. –
Además, lo primero que haces en el proceso principal es llamar a 'esperar'. Esta función hace exactamente eso, espere hasta que el proceso hijo haya finalizado, lo que significa que la llamada 'ptrace' intenta rastrear un proceso que ya no existe. –
[Refiérase a esto] [1] Creo que puede ser útil. [1]: http://stackoverflow.com/questions/6468896/why-is-orig-eax-provided-in-addition-to-eax –