[英]IPC using Signals on linux
可以使用信號捕獲和信號提升來進行IPC (inter process communication)
嗎?
我做了兩個程序。 在第一個程序中我處理了信號,在另一個程序中我只是提出了我想在另一個程序中處理的信號。 我對我來說工作得很好,但我想使用信號在這兩個程序之間進行通信,並且還想用這個 raise 信號發送一些字節的數據。 我怎樣才能做到這一點?
我也想用這個信號傳遞消息。 我可以做嗎? 有可能的?
另外,使用信號的 IPC 機制的優缺點是什么?
以下是我的兩個程序的工作代碼。 這樣一來,我只能發出信號並捕獲信號,但我想將數據從一個程序傳遞到另一個程序。
在第二個程序中,我使用了第一個程序的進程 ID。 我怎樣才能使它動態。?
第一個程序:
/* Example of using sigaction() to setup a signal handler with 3 arguments
* including siginfo_t.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
static void hdl (int sig, siginfo_t *siginfo, void *context)
{
printf("sig no = %d \n", sig);
if(sig == SIGINT)
exit(0);
printf ("Sending PID: %ld, UID: %ld\n",
(long)siginfo->si_pid, (long)siginfo->si_uid);
}
int main (int argc, char *argv[])
{
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_sigaction = &hdl;
act.sa_flags = SA_SIGINFO;
if (sigaction(SIGUSR1, &act, NULL) < 0) {
perror ("sigaction SIGUSR1");
return 1;
}
if (sigaction(SIGINT, &act, NULL) < 0) {
perror ("sigaction SIGINT");
return 1;
}
while (1)
{
sleep(1);
}
return 0;
}
第二個節目
#include <stdio.h>
#include <signal.h>
void main(void)
{
while (1)
{
sleep(1);
kill(11558, SIGUSR1);
}
}
信號旨在提供對進程的基本控制形式,而不是作為 IPC 機制。 當用作其他任何東西時,信號有幾個問題:
很多系統調用都會被一個信號打斷,需要特殊處理。
因此,很多在野外的代碼都不是信號安全的。
信號除了自身之外沒有任何類型的數據內容。 這使得它們作為消息傳遞方法幾乎毫無用處。
在信號處理程序中您只能做這么多。
最重要的是,相同類型的后續信號不會排隊——它們被合並到一個實例中。
更重要的是,無法保證信號的傳遞順序與它們生成的順序相同。 從手冊頁:
相比之下,如果一個進程有多個標准信號待處理,則它們的傳遞順序是未指定的。
從理論上講,您可以使用多個信號來回設置某種通道,其中一些信號就像某種確認,但沒有一個理智的人願意嘗試這樣的事情。 您不妨改用煙霧信號...
可以使用信號捕獲和信號提升來進行 IPC(進程間通信)嗎?
是和不是。 僅考慮信號,您可以向另一個進程發送信號,但不能發送信號以外的任何東西。
我也想用這個信號傳遞消息。 我可以做嗎? 有可能的?
不,不是你想要的方式。 您可以使用套接字、文件、管道或命名管道來執行此操作。 如果您想了解有關 UNIX IPC 的更多信息,請閱讀UNIX 環境中的高級編程。
不,不要嘗試為此使用信號。 您不能使用 siginfo 結構以外的信號附加額外數據。 但是使用信號的主要問題是信號安全的太少了。 您必須避免幾乎所有的 C 運行時例程,並確保接收程序對其所有內核調用進行 EINTR 檢查。 關於信號何時出現,您唯一可以說的是它不會在您期望的時候出現(有點像西班牙宗教裁判所)。
我建議您研究其他 IPC 機制,例如共享內存、消息隊列、fifos(命名管道)和套接字。
除了在一種特定情況下,我遇到過信號通常不用作 IPC 機制。
我唯一一次使用信號是作為 IPC 機制的一部分,當您需要中斷信號進程的正常操作流程以處理某些事情時,例如定時器中斷。 signal( 已經使用 signals 和 boost shared memory 一起實現進程間事件管理。共享內存包含需要處理的事件列表,signal 用於讓進程處理這些事件。這些事件是 out-of-band並且不可預測,所以使用信號是理想的。我進行了大量測試來驗證實現(並且很難讓它全部穩定)。
這在使用 glibc 的 Linux 環境中將 sigqueue 與信號 SIGRTMIN+1 一起使用,並在 sigaction 上使用 SA_RESTART 將避免直接處理 EINTR 的需要,請參閱glibc: Primitives Interrupted by Signals 。 BSD 有一個類似的方案,所以我的系統不需要 EINTR 處理。 考慮和處理(並測試)了其他答案提出的所有要點。
但是,如果您只想在進程的正常操作中來回傳遞值,那么另一個 IPC(例如套接字、文件、管道或命名管道)會更好。 如果你可以使用ZeroMQ ,那就更好了,因為它以一種非常優雅的方式為你做了很多艱苦的工作。
我目前正在閱讀man 7 signal
:
實時信號有以下區別:
- 如果使用 sigqueue(3) 發送信號,則可以隨信號一起發送伴隨值(整數或指針)。 ...
注意:實時信號從SIGRTMIN
到SIGRTMAX
開始。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.