4

我的进程作为守护进程运行。我想使用信号重新加载配置。问题是,如果配置错误,它应该以 tty 形式发出错误消息,发送信号。

  1. 有没有办法做到这一点?
  2. 是推荐的方式吗?

如果不是推荐的方式。检查它是否成功的更合适的方法是什么?

4

4 回答 4

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!
~ #
于 2012-07-24T10:26:06.973 回答
2

我猜你喜欢捕捉SIGUSR1然后重新加载配置?

你应该记住,信号处理程序应该尽可能的小而快,而不是做一些可能导致另一个信号的事情。所以基本上你应该尽可能地避免 I/O。最好的方法可能是有一个非常简单的信号处理程序,它只设置一个标志,然后在你的主循环中检查这个标志,然后在你的主线程的上下文中重新加载你的配置。在那里,您可以随心所欲地输出到控制台。

于 2012-07-24T07:46:53.493 回答
1

你可以做到这一点,但没有简单的方法可以做到这一点。您需要为守护进程安排一种机制来反馈给发送信号的进程。

一些可能的方法包括:

  • 将(带时间戳的)结果写入预定位置的文件。
  • 让守护进程维护一个共享内存段,其中包含已知结构中的信息。
  • 让守护进程监听某种命名管道/套接字并以这种方式给出反馈。(您也可以通过该通道发送重新加载命令)。
  • 让发送信号的东西和守护进程链接到一个共享库,这样两者都能够验证配置文件。在发出信号之前验证文件。

在那些命名管道中,我认为我的第一选择是 - 您可以使用正常权限限制对它的访问,并且它最容易变得健壮和正确。

于 2012-07-24T07:47:22.083 回答
0

我怀疑您是否可以确定信号的来源,即使可以,也不必是终端。使用简单的 tcp/ip 协议怎么样?接受特殊端口上的 tcp/ip 连接。读取命令直到第一个新行。如果该命令是“重新配置”,请进行重新配置并通过已建立的 TCP/IP 连接发送消息。

于 2012-07-24T07:48:13.783 回答