我作为守护进程运行的进程。 我想使用信号重新加载配置。 问题是,如果配置错误,它应该以tty形式发出错误信息。
如果不推荐的话。什么是更合适的方法来检查它是否成功?
答案 0 :(得分:6)
要获取信号源的pid,设置信号处理程序时需要使用sa_sigaction
而不是sa_handler
:
static pid_t g_killer_pid = 0;
static void signal_handler( int num, siginfo_t *info, void* blabla )
{
g_killer_pid = info->si_pid;
}
int main(void)
{
struct sigaction sa;
memset( &sa, 0, sizeof(sa) );
sa.sa_sigaction = &signal_handler;
sa.sa_flags = SA_SIGINFO;
sigaction( SIGTERM, &sa, NULL );
sigaction( SIGINT, &sa, NULL );
pause();
hello_killer( g_killer_pid );
return 0;
}
现在你有源进程的pid了。
获取源进程的终端ID并不是那么简单。
一种方法是从proc/<pid>/stat
文件中读取它。文件中的一个数字是tty_nr
。
tty_nr
对我来说有点奇怪,所以我不知道这是不是便携式的东西。
但它包含次要数字,可用于打开正确的写作终端:
static void hello_killer( pid_t killer )
{
char filename[200];
FILE* fil;
FILE* out;
int tty_nr;
sprintf( filename, "/proc/%ld/stat", (long int)killer );
fil = fopen( filename, "r" );
if( fil )
{
if( fscanf( fil, "%*s %*s %*s %*s %*s %*s %d ", &tty_nr ) == 1 )
{
sprintf( filename, "/dev/pts/%d", (tty_nr & 0xF) | ((tty_nr >> 20) & 0xFFF) );
out = fopen( filename, "a" );
if( out )
{
fprintf( out, "Hello!\n" );
fclose( out );
}
}
fclose( fil );
}
}
我不确定/dev/pts
是否正确/最佳方式。但它似乎在我的Linux机箱中工作:
~ # killall temp_test
Hello!
~ #
答案 1 :(得分:2)
我猜你喜欢捕捉SIGUSR1
,然后重新加载配置?
您应该记住,信号处理程序应该尽可能小而且快速,而不是做可能导致其他信号的事情。所以基本上你应该尽可能地避免I / O.可能最好的方法是使用一个非常简单的信号处理程序,只设置一个标志,然后在主循环中检查这个标志,然后在主线程的上下文中重新加载你的配置。在那里,您可以输出所需的一切。
答案 2 :(得分:1)
你可以做到这一点,但没有琐碎的方法可以做到这一点。您需要为守护程序安排一种机制,以反馈发送信号的进程。
一些可行的方法包括:
在那些命名管道中我认为是我的第一选择 - 您可以使用正常权限限制对它的访问,并且最容易做出健壮和正确。
答案 3 :(得分:0)
我怀疑,您可以确定信号的来源,如果可以的话,它甚至不必是终端。使用简单的tcp / ip协议怎么样?接受特殊端口上的tcp / ip连接。读取命令直到第一个新行。如果该命令是“重新配置”,请执行重新配置并通过已建立的TCP / IP连接发送消息。