在发送信号的终端中显示消息

时间:2012-07-24 07:42:31

标签: c++ linux tty

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

  1. 有办法吗?
  2. 是推荐的方式吗?
  3. 如果不推荐的话。什么是更合适的方法来检查它是否成功?

4 个答案:

答案 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_nrtty_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连接发送消息。

相关问题