微信平臺的微網(wǎng)站怎么做網(wǎng)站關(guān)鍵詞優(yōu)化培訓(xùn)
linux在使用重定向?qū)懭胛募r(使用標(biāo)準(zhǔn)C庫函數(shù)時)使處理信號異常(延時)–問題分析
在使用alarm函數(shù)進(jìn)行序號處理測試的時候發(fā)現(xiàn)如果把輸出重定向到文件里面會導(dǎo)致信號的處理出現(xiàn)嚴(yán)重的延遲(ubuntu18)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main(void){alarm(3);//定時三秒while(1){int i;printf("%d\n", i++); //打印信息}return 0;
}
測試
- 正常情況
使用命令
time ./a.out
進(jìn)行計(jì)時
這時候這是個時間是基本沒有誤差的
- 出現(xiàn)問題
這時候使用命令
time ./a.out > text.out
把輸出的信息放到文件里面
這時候就會發(fā)現(xiàn)這一個處理的時間開始不對勁了
嘗試分析
庫函數(shù)分析
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main(void){alarm(3);printf("now alarm = %d\n", alarm(3));while(1){char buf[20];int i;sprintf(buf, "%d\n", i++);write(STDOUT_FILENO, buf, strlen(buf));}return 0;
}
把這一個輸出使用系統(tǒng)調(diào)用進(jìn)行
這里可以看出延時少了很多
查看實(shí)際的系統(tǒng)調(diào)用
使用命令
strace ./a.out > out.txt
查看實(shí)際的系統(tǒng)調(diào)用
-
庫函數(shù)版本(shell)
-
庫函數(shù)版本(文件)
-
系統(tǒng)調(diào)用版本(shell)
-
系統(tǒng)調(diào)用版本(文件)
這時候可以發(fā)現(xiàn)這庫函數(shù)進(jìn)行文件寫入的時候是使用了一個緩存區(qū)4096字節(jié)
測試緩沖區(qū)大小對信號處理的影響
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main(void){alarm(3);printf("now alarm = %d\n", alarm(3));while(1){int i;printf("%d ", i++);//不使用換行, 這時候庫函數(shù)會使用大的緩沖區(qū)}return 0;
}
這時候可以獲取結(jié)論這一個不是因?yàn)榫彌_區(qū)大小出現(xiàn)的, 寫入shell的時候使用的是1024的緩沖區(qū), 但是對于時間的影響不大
write函數(shù)分析
在man文檔里面的write里面有這樣一段話
If a write() is interrupted by a signal handler before any bytes are written, then the call fails with the error EINTR; if it is interrupted after at least one byte has been written, the call succeeds, and returns the number of bytes written.
從這一段可以推測出write不是原子操作, 并且這一個是可以被信號打斷的, 并且實(shí)際測試寫shell的時候是隨時可以使用Ctrl + C打斷的, 只有在文件處理的時候會出現(xiàn)Ctrl + C無法立刻打斷這一個程序
信號處理分析
信號處理分析
從這一篇文章里面可以獲取信號處理是在從內(nèi)核態(tài)返回的時候處理的
推測結(jié)論
猜測可能是內(nèi)核在對文件處理的時候會把很多的write里面的信息合并起來處理(就算是4096處理一次從跟蹤可以看出來也是有很多次的, 如果每一處只處理一個4096不至于出現(xiàn)延時達(dá)到好幾秒的情況), 寫入shell的時候沒有進(jìn)行合并, 所以誤差比較小, 這時候由于硬盤的寫入比較慢, 數(shù)據(jù)量比較大, 需要等待IO, 會長時間處于內(nèi)核態(tài), 導(dǎo)致信號處理的延時
使用write每一次寫入的數(shù)量比較少的時候反應(yīng)比較快, 推測這一個合并可能是和write的次數(shù)也有關(guān)系
這一段僅供參考, 沒有實(shí)際查看源碼, 回頭分析源碼以后會再補(bǔ)充的