我有一个C的插入程序库。不可能插入vfork(),因为vfork() (插入函数)在调用真正的vfork()之后不能返回到调用函数。但是我插入了_exit(),因为我需要知道流程什么时候结束。当然,我还插入了exec*()函数。我的问题是,当插入_exit()时,当_exit()被一个正常的进程调用时,有一些事情我想要做,而不是当进程是受限的vfork()'ed进程时。
当我的进程是vfork()'ed进程时,以及当我无法访问vfork()返回的进程id时,我如何在C程序中知道
接口库:
/* COMPILE: gcc -shared -ldl -fPIC -o libso_interposer.so so_interposer.c -std=c99 */
/* RUN: LD_PRELOAD=./libso_interposer.so so_interposer_test */
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
#include <unistd.h>
static void (*_exit_R)(int) = (void *) 0;
static pid_t (*fork_R)(void) = (void *) 0;
static void teardown_interposer() {
fprintf(stderr, "Destructing so_interposer.\n");
/* Concurrency protected code to be executed only once
* when the process finishes! */
/* Must not be executed if/when vfork() process finishes. */
}
pid_t fork(void) {
*(pid_t **) (&fork_R) = dlsym(RTLD_NEXT, "fork");
/* Code to prepare for a new process.
* More preparation in exec* interposing functions.*/
pid_t pid = fork_R();
return pid;
}
__attribute__((noreturn)) void _exit(int status) {
*(void **) (&_exit_R) = dlsym(RTLD_NEXT, "_exit");
fprintf(stderr, "Process '%lld' called _exit(%i).\n", (signed long long int) getpid(), status);
teardown_interposer();
_exit_R(status);
}测试二进制:
/* COMPILE: gcc -std=c99 -D FORK=vfork -o so_interposer_test so_interposer_test.c */
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#if !defined(FORK)
#error "Define FORK: 'fork' or 'vfork'!"
#endif
int main(void) {
pid_t pid = FORK();
if(pid == 0) {
_exit(EXIT_SUCCESS);
} else if(pid > 0) {
_exit(EXIT_SUCCESS);
}
return EXIT_SUCCESS;
}发布于 2019-09-20 00:00:01
对于gcc的最新版本,您应该能够将vfork包装为:
typedef pid_t (*vfork_t)(void);
extern vfork_t wrap_vfork();
pid_t vfork(void) {
vfork_t f = wrap_vfork();
return f();
}在其中,wrap_vfork执行所有v叉包装工作,并返回一个指向实际v叉的指针(而不调用它)。Gcc 6.3.0 (-O3)将此编译为:
.globl vfork
.type vfork, @function
vfork:
.LFB11:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
xorl %eax, %eax
call wrap_vfork
addq $8, %rsp
.cfi_def_cfa_offset 8
jmp *%rax
.cfi_endproc
.LFE11:
.size vfork, .-vfork需要注意的是,它直接跳转到实际的v叉函数,而不是调用它,因此它本身不需要返回(真正的v叉将直接返回到该函数的调用方)。
如果您不习惯于依赖编译器来为您进行尾调用优化,则可以直接用asm编写这个小例程,而不是用C。
https://stackoverflow.com/questions/57993622
复制相似问题