linux的signal
⑴ linux環境下使用signal函數進行進程間通信的問題
測試了一下,三個進程都會收到SIGINT信號。
原程序中,child1, child2都收到SIGINT信號,調用stop(), 之後被喚醒,列印"child process ... is killed by parent!",事實上kill這兩個child的不是parent,是它們自己的SIGINT。
放到①處,child1收到SIGINT信號,默認的行為是把自己殺了,當然也來不及列印任何東西了。child2收到SIGINT信號,打斷waiting(),列印"child process 2 ...",然後退出。殺死它的也不是SIGUSR2信號。
放到②處,child1, child2收到SIGINT信號,默認的行為是立即把自己殺了,也來不及列印任何東西了。
測試方法:
// 列印誰執行、被什麼信號打斷
static void stop(int signal) {
printf("stop %d by signal %d\n", getpid(), signal);
wait_mark=0;
}
// 在parent進程中,列印各進程id
printf("parent %d, child1 %d, child2 %d\n",getpid(),p1,p2);
如果讓parent成為殺死child的兇手,可以在child1,child2中加入:
signal(SIGINT, keep_me_alive);
// 不理睬SIGINT信號
static void keep_me_alive(int signal) {
}
這時列印結果就一樣了
⑵ linux 中的signal 函數
這是個函數指針,
void ( *func )( int )是一個接受一個int型參數,不返回的函數的指針;
比如:
void F( int a ) { print( "%d", a ); }
void ( *func )( int ) = F;
func( 3 ); // 調用F函數輸出3
作為函數參數的函數指針有一個專門的名稱叫做回調,你可以把任意滿足回調函數參數特徵標的函數地址作為參數傳給signal。
在這里因為signal對於sig參數可以指定用戶自定義的信號處理函數,所以你可以把你要處理的這個sig的函數地址作為參數傳給signal,那麼系統接收到對應sig的時候就會通過你傳進去的地址調用你的這個函數。
⑶ 怎麼查看 linux signal
有個current指針指向當前正在運行的進程,你一個ctrl+c後由產生一個信號,主要是current ,看看linux內核中的進程調度
⑷ linux下進程通信中signal和message queue的區別
信號一般是發送給一個正在執行中的進程的系統級別的中斷。但是有些系統級別的調用不會被信號中斷。所以,你可以從一個進程給另一個進程發送一個信號(比如Kill
進程號,讀取man
page)去實現進程間的通信;
消息對列是由操作系統提供的機制,負責進程之間消息類型化通信;
使用信號量,如果信號自己沒有足夠容量包含信息,需要其他共享資源去保存信息。如果想發送一個字元串消息,你需要將一個字元串保存到另外一個進程能夠獲取到字元串地方,然後發送信號告訴該進程這個消息已經准備好了。
如果通過消息隊列發送消息,系統不會中斷進程讓進程知道,進程必須主動檢查給自己的消息。如果你不使用select()系統去檢查自己的消息,你就必須一直等待。
這是使用消息對列最大的問題。
消息隊列是類型化的,你可以使用這種類型去發送/接收的消息。
信號不會被計數,僅僅會做個簡單的標記。
當多個信號到達並被阻塞時,系統僅僅標記有信號到達,不會告訴進程有多少個信號到,所以在編程時要留意這個問題。
⑸ 關於linux signal的問題
也就是說,當GPS數據准備好後會發送signal給你們自己寫的平台軟體,相當於請求刷屏幕,然後平台軟體執行刷屏幕操作,這兩個之間需要一個同步關系就是說,當有請求後我才去刷屏幕操作。
這種情況不是因為平台進程接受不到signal,而是收到了signal信號而且正確執行了sem_post操作(你可以在signal handler中加入列印調試語句看看),因為你的刷屏幕操作線程執行時間太長了,導致連續執行好幾次屏幕操作,這是種惡性循環(因為gps軟體每次數據准備好就發送個signal,而你的 signal在每次捕捉到signal後就執行一次sem_post,然而你的刷屏幕操作時間太長了當執行完一次刷屏幕操作後再次調用sem_wait的時候已經有多個信號量資源了也就是消費跟不上生產,信號量post次數比wait次數多)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
sem_t lock;
int gps_data = 0;
/* fflush screen thread */
void *gps_data_process (void *arg)
{
while (1)
{
/* wait gps data is ready */
/* second run sem_wait will by more semaphore it will not block */
sem_wait(&lock);
/* ok data is ready */
printf("Data is [%d]\n", gps_data);
/* simulate a long procees time */
sleep(100);
}
}
/* SIGUSR1 handler */
void gps_data_request(int sig)
{
if (sig == SIGUSR1)
{
/* ok gps data is ready so request process */
sem_post(&lock);
}
}
int main(int argc, char **argv)
{
pthread_t tid;
struct sigaction action;
/* initialize semaphore */
if (sem_init(&lock, 0, 0) == -1)
{
perror("sem_init");
exit(1);
}
action.sa_handler = gps_data_request;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
/* caught signal SIGUSR1 */
if (sigaction(SIGUSR1, &action, NULL))
{
perror("sigaction");
exit(1);
}
/* create a thread */
if (pthread_create(&tid, NULL, gps_data_process, NULL) == -1)
{
perror("pthread_create");
exit(1);
}
while (1)
{
printf("[GPS]>>>");
/* gps get data ready */
scanf("%d", &gps_data);
if (gps_data)
{
/* simulate gps program send signal to platform process */
raise(SIGUSR1);
}
sleep(1);
}
return 0;
}
⑹ linux c signal函數
是第二次調用的時候輸出的,第一次調用只是綁定了SIGUSR1的信號處理函數,不會進入該處理函數
為什麼會有這樣的輸出呢?
signal函數是將信號與處理函數進行綁定,成功綁定則返回綁定之前的信號處理函數。那麼來看看你的代碼,第一次調用將sig_fun1綁定,無輸出;第二次調用將sig_fun2綁定,也就是把sig_fun1替換下來,並且你還調用了它,參數為30,所以會有那樣的輸出。
該如何改呢?
其實你並沒有涉及到linux的信號處理機制,光綁定是不夠的,還需要發信號給它,才能真正進入信號處理過程。給你一個示例代碼吧
#include<signal.h>
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
void sig_fun2(int signo)
{
printf("in sig_fun2:%d\n", signo);
}
void sig_fun1(int signo)
{
printf("in sig_fun1:%d\n", signo);
}
int main()
{
unsigned long i;
if (signal(SIGUSR1, sig_fun1) == SIG_ERR)
{
printf("signal fun1 error\n");
exit(1);
}
sleep(15);
(signal(SIGUSR1, sig_fun2))(30);
sleep(15);
printf("done\n");
return 0;
}
/****************************C 代碼完,下面是如何運行***************************/
首先編譯,假設生成可執行程序為test
然後運行,我用的是後台運行: nohup ./test>output.txt &
注意,這種方法要將輸出重定向到文件output.txt(名字無所謂),然後你會看到一個數字,就是pid進程號
最後,在15秒之內發送信號:kill -SIGUSR1 進程號
現在你就可以打開output.txt看輸出結果了。如果用sleep的話會被打斷,所以只有兩個輸出加上替換處理函數時的輸出共3個,也可以換成 int n=15;while(n--)sleep(1);
-------------------------------------------------------------
怎麼樣,加分吧
-------------------------------------------------------------
1.我就是想問第二次綁定sig_fun2的時候,調用了第一次綁定的sig_fun1么?
調用了, (signal(SIGUSR1, sig_fun2))(30);就是這一句, signal(SIGUSR1, sig_fun2)是個函數指針,你這樣寫就是調用它了,但是這和信號處理沒關系,寫成signal(SIGUSR1, sig_fun2);就可以了
這就是你所說的成功則返回綁定之前的函數???
對
那當時綁定sig_fun1的時候,返回之前的處理函數是什麼??
這個就是系統默認的了,比如SIGINT就是你ctrl+c取消程序執行發送的信號,它的處理函數就是結束程序的一系列動作,不過SIGUSR1是留給用戶自定義的信號,系統默認應該是啥也不做的一個函數,例如void fun(int signo){},你也可以第一次綁定的時候就調用試試看對不對
2.還有我在看signal函數定義的時候,void(//...)(int) 最後傳入的這個int整形參數就是我們自定義sig_fun()中所接收的30么??我看例子裡面有的signal(SIGINT,myfunc);也沒有帶參數啊,搞不懂
是你理解錯了,signal函數只是綁定,沒涉及到調用綁定函數,不用帶參數,信號處理函數不是像你這樣調用的。callback回調你知道吧,就是先做好一個函數或過程放著,事件觸發的時候才調用。那個30是你用普通函數調用的方式時的參數,跟信號處理一點關系也沒有,你用60,70也沒半毛錢關系。我猜你是想要調用信號處理函數,然後迷糊了,其實我上面說的「kill -SIGUSR1 進程號」就是觸發程序調用該處理函數的信號,這和kill -9 殺死進程一個道理,只不過處理函數不同,結果不一樣。ctrl+c也可以用信號的方式發送,kill -2 進程號,或者 kill -SIGINT 進程號
另外,站長團上有產品團購,便宜有保證
⑺ linux signal(SIGINT,SIG_IGN);大概解釋一下
signal,此函數相對簡單一些,給定一個信號,給出信號處理函數則可,當然,函數簡單,其功能也相對簡單許多,簡單給出個函數例子如下:
#include<signal.h>
#include<stdio.h>
#include<unistd.h>
voidouch(intsig)
{
printf("Igotsignal%d ",sig);
//(void)signal(SIGINT,SIG_DFL);
//(void)signal(SIGINT,ouch);
}
intmain()
{
(void)signal(SIGINT,ouch);
while(1)
{
printf("helloworld... ");
sleep(1);
}
}
當然,實際運用中,需要對不同到signal設定不同的到信號處理函數,SIG_IGN忽略/SIG_DFL默認,這倆宏也可以作為信號處理函數。同時SIGSTOP/SIGKILL這倆信號無法捕獲和忽略。注意,經過實驗發現,signal函數也會堵塞當前正在處理的signal,但是沒有辦法阻塞其它signal,比如正在處理SIG_INT,再來一個SIG_INT則會堵塞,但是來SIG_QUIT則會被其中斷,如果SIG_QUIT有處理,則需要等待SIG_QUIT處理完了,SIG_INT才會接著剛才處理。
⑻ linux中的signal怎麼使用
signal函數的定義很復雜,但是它的用法還是比較簡單的,你記住它的兩個參數就可以了。signal有兩個參數sig和func,signal這個函數是用來接收信號並處理的,所以sig參數表示將要處理哪種類型的信號,而func參數是一個函數指針,用來指定信號的處理函數,也就是當程序接收到sig那個類型的信號後,就會調用func指針指向的函數。func指針的原型是:
void (*func) (int)
所以信號的處理函數必須是一個返回void,只有一個int類型參數的函數。
比如如果程序需要處理Ctrl+C組合鍵產生的信號,就可以這樣使用signal函數:
(void) signal(SIGINT, myfunc);
而myfunc函數可以這樣定義:
void myfunc(int sig)
{
printf("Hello, the signal is %d\n", sig);
// 因為現在處理的是Ctrl+C信號,所以下面要
// 恢復程序對Ctrl+C的默認反應
(void) signal(SIGINT, SIG_DFL);
}
⑼ linux signal 11 是什麼意思
通過kill -l 可以查看信號列表,11 是段錯誤
$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD
18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN
22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO
30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1
36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5
40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9
44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13
52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9
56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5
60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1
64) SIGRTMAX