[英]Systemcall child-parent execution problem (fork execve) Linux
我是系統調用的新手。 我在孩子內部使用 execve,因此父級應該正常運行並且不會被 execve 覆蓋。 問題是孩子在execve之后執行並停止了整個事情。 我的目標是計算 execve 執行的 bash 命令(參數)中執行的克隆數。
我讀過這個人,我還是有點困惑。 我只能使用 ptrace、fork、wait/waitpid。
爭論:
/bin/bash -c "echo 'first test' | wc -c"
int main(int argc, char *argv[]) {
pid_t child_pid = fork();
int status;
int counter = 0;
wait(&status);
if (child_pid == -1) {
exit(1);
} else {
while(status != child_pid){
if (child_pid == 0) {
ptrace(PTRACE_TRACEME, child_pid, 0, 0);
raise(SIGSTOP);
execve(argv[1], &argv[1], NULL);
ptrace(PTRACE_SETOPTIONS, child_pid, 0, PTRACE_O_TRACECLONE);
ptrace(PTRACE_CONT, child_pid, 0L, 0L);
if(status>>8 == (SIGTRAP | (PTRACE_EVENT_CLONE<<8)))
counter++;
}
}
}
printf("# of clone executions: %d", counter);
return 0;
}
execve
會覆蓋子進程,所以execve
之后的任何指令都不會被執行,除非調用execve
失敗。 您應該改為運行父進程中execve
之后出現的ptrace
跟蹤
編輯:這是一個計算克隆系統調用數量的注釋解決方案:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <sys/reg.h> // ORIG_RAX
int main(int argc, char *argv[]) {
pid_t child_pid = fork();
int counter = 0;
int entering_syscall = 1;
if(child_pid == -1) {
perror("fork failed");
exit(1);
} else if(child_pid != 0) {
// parent
u_int64_t rax;
int status;
while(1) {
// wait for the next signal by the child
if(wait(&status) != child_pid)
continue;
if(WIFEXITED(status)) {
puts("child exited");
break;
}
// read the USER area, defined in sys/user.h, which contains the registers information
// in linux, rax contains the syscall number
rax = ptrace(PTRACE_PEEKUSER, child_pid, 8 * ORIG_RAX, NULL);
if(rax == SYS_clone /* 56 */) {
// PTRACE_SYSCALL generates a signal both when entering and exiting a syscall
// only count the syscall during enter
if(entering_syscall)
counter++;
entering_syscall = !entering_syscall;
}
//printf("syscall %ld\n", rax);
// continue the child process until the next syscall enter/exit
ptrace(PTRACE_SYSCALL, child_pid, NULL, NULL);
}
} else {
// child
// turns the calling thread into a tracee
ptrace(PTRACE_TRACEME, child_pid, 0, 0);
// signal and wait for the parent. This ensures that PTRACE_SYSCALL
// will not miss any child syscall
raise(SIGSTOP);
execve(argv[1], &argv[1], NULL);
// should be never reached
perror("execve failed");
exit(1);
}
printf("Num clone: %d\n", counter);
}
您可以對照 strace 交叉檢查strace 2>&1 your_command | grep clone | wc -l
strace 2>&1 your_command | grep clone | wc -l
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.