我尝试在我的信号处理程序中使用SIGSEGV
收到ececl()
时重置我的程序。但是,我当前的程序需要命令行参数才能启动,我可以通过execl()
+ 1额外参数"RESTART"
来通知程序它刚刚重新启动而不是重新开始。
但是如何通过exec()传递我的argv []?
目标:
execl("./myprog","./myprog",argv[1],argv[2],...,argv[argc],"RESTART");
要么
execl("./myprog","./myprog","RESTART",argv[1],argv[2],...,argv[argc]);
答案 0 :(得分:3)
<强>概要强>
#include <unistd.h>
...
int execv(const char *path, char *const argv[]);
...
execv()
,execvp()
和execvpe()
函数提供了一个数组 指向以null结尾的字符串的指针,表示参数列表 可用于新计划。第一个论点,按照惯例, 应指向与正在执行的文件关联的文件名。 指针数组必须以空指针终止。
也许是这样:
int main( int argc, char **argv )
{
...
int rc = execv( "./myprog", argv );
}
您可能需要修改argv
中的特定值或创建一个全新的参数数组以满足您的需要。
答案 1 :(得分:2)
您需要在main中保存argv:
static char **Argv;
int main(int c, char **v) { Argv = v; //...
或来自gcc构造函数:
static char **Argv;
__attribute__((constructor))
static void ctor(int c, char **v) { Argv = v; }
然后你可以做你想做的事:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
static char **Argv;
static void hndlr(int s)
{
execv("/proc/self/exe", Argv);
_exit(127);
}
int main(int argc, char **argv)
{
Argv = argv;
struct sigaction sa = { .sa_handler = hndlr, .sa_flags = SA_NODEFER };
sigaction(SIGSEGV, &sa, 0);
sleep(1);
fputs("start\n", stderr);
//keep re-executing the same program
raise(SIGSEGV);
}
请注意,如果没有SA_NODEFER,您将只看到该消息两次,因为在第二次运行可执行文件期间将阻止SIGSEGV。
虽然这应该被定义(特别是如果你添加一个信号堆栈以便你也可以处理堆栈溢出),包装脚本/程序是一种更安全,更健壮的方法。使用SISEGV处理程序方法,您实际上并不是从头开始 - 您继承信号掩码,有效的uid / gids,工作目录,打开文件描述符等等,而使用包装器脚本则从定义良好的开始状态。