我正在尝试编写一个可以追踪系统调用的程序。但是我在让它正常工作方面遇到了困难。我尝试使用fork()来创建一个实例(即代码),然后监视生成的子进程。
目标是让父进程返回子进程执行的每个系统调用的索引并将其输出到屏幕上。但不知道为什么计划没有按照预期进行。
以下是代码:
这个的输出结果是:
我理解的方式是每当用户程序调用系统调用时,内核将首先检查进程是否正在被跟踪,然后执行系统调用例程并使用信号暂停该进程并返回控制权给父进程。这难道不已经导致状态改变了吗?
目标是让父进程返回子进程执行的每个系统调用的索引并将其输出到屏幕上。但不知道为什么计划没有按照预期进行。
以下是代码:
#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;
}
这段代码基于以下代码:
#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;
}
这个的输出结果是:
The child made a system call 11
这是exec系统调用的索引。
根据wait()的man页面:
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.
我理解的方式是每当用户程序调用系统调用时,内核将首先检查进程是否正在被跟踪,然后执行系统调用例程并使用信号暂停该进程并返回控制权给父进程。这难道不已经导致状态改变了吗?
wait
函数。该函数会一直等待,直到子进程结束,这意味着ptrace
调用试图跟踪一个已经不存在的进程。 - Some programmer dude