我的進程作爲守護進程運行。 我想用信號重新加載配置。 問題是,如果配置錯誤,它應該以tty形式發送信號的錯誤消息。在發送信號的終端顯示一條消息
- 有沒有辦法做到這一點?
- 它是推薦的方式嗎?
如果沒有推薦的方式。什麼是更合適的方法來檢查它是否成功?
我的進程作爲守護進程運行。 我想用信號重新加載配置。 問題是,如果配置錯誤,它應該以tty形式發送信號的錯誤消息。在發送信號的終端顯示一條消息
如果沒有推薦的方式。什麼是更合適的方法來檢查它是否成功?
我猜你的東西像抓住SIGUSR1
,然後重新加載配置?
你應該記住,信號處理程序應儘可能小,見效快的可能,而不是做一些事情,可能會導致另一個信號。所以基本上你應該儘可能避免I/O。可能最好的辦法是設置一個非常簡單的信號處理程序,只設置一個標誌,然後在主循環中檢查此標誌,然後在主線程的上下文中重新加載配置。在那裏你可以輸出到控制檯所有你想要的。
該循環檢查應該有什麼閒置睡眠時間? – 2012-07-24 07:58:34
@VivekGoel這完全取決於你。如果你的程序是事件驅動的,那麼你可以使用適合你所使用的事件框架而不是標誌(例如條件變量,管道)的東西。 – 2012-07-24 08:07:44
你可以這樣做,但沒有瑣碎的方式來做到這一點。您需要爲守護進程安排一種機制來反饋發送信號的進程。
包括做着一些可能的方式:
在那些命名管道將是我的第一選擇,我認爲 - 你可以限制對它的訪問與正常的權限,這是最簡單的做出健全和正確的。
我懷疑,你可以確定信號源,甚至如果可以的話,它不一定是終端。使用簡單的tcp/ip協議怎麼樣?接受特殊端口上的tcp/ip連接。閱讀命令,直到第一個新行。如果該命令是「重新配置」,則執行重新配置並通過建立的TCP/IP連接發送消息。
爲獲得信號源的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!
~ #
我覺得更堅實的做法是寫你的包裝,人們可以用它來做事喜歡重啓,重裝配置等東西就像一個「遙控器」程序Apache Web服務器的「apachectl」。 – 2012-07-24 07:54:07