Linux學習筆記17 alarm pause

2021-09-13 14:05:59 字數 2653 閱讀 9252

#inlcude unsigned int alarm(unsigned int seconds);

int pause(void);

alarm是乙個鬧鐘,在指定的秒數之後發出乙個sigalrm訊號;

但是,alarm函式自身是馬上就返回的,不用等待n秒之後再返回,非同步;

這個訊號只能本程序自己接收;

如果在呼叫alarm時,前乙個鬧鐘還沒到觸發訊號的時候,則返回該鬧鐘的剩餘時間,同時用新鬧鐘的時間替換舊鬧鐘的剩餘時間;

如果前面沒有鬧鐘,返回0;

alarm(0)表示取消以前未觸發的鬧鐘,返回舊鬧鐘的剩餘時間,不會發出sifalrm訊號;

pause使得本程序掛起,直到捕捉到任意乙個訊號;

只有執行了乙個訊號處理程式,並從其返回時,pause才返回;返回值-1;

我們用上面兩個函式就能自己實現乙個sleep的功能。如下:

#include #include #include #include #include void sig_alrm(int signo);

unsigned int sleep1(unsigned int seconds);

int main()

// 10.10 sleep的實現1

void sig_alrm(int signo)

unsigned int sleep1(unsigned int seconds)

//2, 定好鬧鐘傳送訊號

alarm(seconds);

//3,等待訊號

pause();

//4,清除鬧鐘

return(alarm(0));

}

呼叫alarm可以等待指定時間後觸發訊號,呼叫pause可以一直等待訊號的出現。這兩個一結合就是sleep的功能。

實現效果如下:

➜  code ./study_linux

wait for 3s

recived sigalrm

end

但是,這個sleep的實現是有一些問題的:

我們這裡用alarm來發訊號,但是我們沒有考慮到會不會在呼叫sleep1之前剛好有乙個未觸發的鬧鐘?如果有的話,那麼我們會把別人的鬧鐘清除掉;

我們註冊了sigalrm,為它指定了乙個處理程式,所以也就修改了原先的配置,或許人家原先是忽略這個訊號或者使用預設值呢。那麼我們在sleep結束前是不是應當恢復這些配置?

alarm與pause之間有乙個競爭關係。如果執行玩alarm之後,進入了子程序,而不是馬上呼叫pause,那麼就有可能在執行了sigalrm的處理程式之後才呼叫pause,這樣會造成pause一直不被喚醒。。。

現在我們用setjmp來解決第三種問題。

利用setjmp和longjmp可以實現在不同的函式間跳轉。這是goto實現不了的功能。goto只能在函式內部跳轉。

#include #include #include #include #include #include static jmp_buf env_alrm; //儲存setjmp時的環境

unsigned int sleep2(unsigned int seconds);

int main()

//sleep的第二種實現

void sig_alrm2(int signo)

unsigned int sleep2(unsigned int seconds)

//等於0表示第一次執行

//等於1表示sig_alrm2已經被觸發了,再返回這裡

if (setjmp(env_alrm) == 0)

//4,清除鬧鐘

return(alarm(0));

}

現在我們看看,就算在執行alarm之後由於某個原因,沒有馬上執行pause,等待n秒之後,觸發了訊號會怎麼樣?

這時執行了sig_alrm2,執行longjmp時,跳回到setjmp,並使得setjmp返回1,判斷失敗,於是return。

所以即便pause沒有執行也不會出錯。

從標準輸入讀字元,如果到了限制的時間read還沒有完成的話,就停止讀取

我們可以在讀取前設定鬧鐘,讀取後取消鬧鐘;對大部分系統而言,一旦收到訊號並進行處理,則read這種慢系統呼叫就會被終止。所以如果超過了時間read就算沒有返回也會被動終止。

**如下:

#include #include #include #include #include #include #define maxline 1024

int main()

//設定鬧鐘

alarm(20);

//從標準輸入讀取

//對大部分系統而言,捕獲到訊號並處理時,會使得read操作終止

if ((n = read(stdin_fileno,line,maxline)) < 0)

//如果讀完一行之後,鬧鐘還沒觸發,則取消鬧鐘

alarm(0);

//將讀取的內容列印到螢幕上

printf("write: \n");

write(stdout_fileno, line, n);

exit(0);

}

可惜的是,對於ubuntu而言,捕獲訊號並不會使得read終止,而是會使得其重啟。。。。

linux學習筆記17

vim vim介紹 vim是vi的公升級版,vim和vi的最大區別就是編輯乙個文字時vi不會顯示顏色,vim會顯示顏色,vim的安裝方法yum install y vim enhanced。vim顏色顯示 vim的顏色和你檔案的具體內容有關,相同的檔案在不同的目錄下都有可能導致顏色不存在,vim的配...

linux指令碼攻略學習筆記17

sed是進行文字替換的不二之選。這樣,我們就可以通過sed用空白替代匹配的句子。先建立乙個包含替換文字的檔案。例如 我們的目標是移除包含 mobile phones 的句子。可以用sed語句來實現 這裡的匹配模式是用來匹配整句文字的正規表示式,檔案中的每一句話第乙個字元都是空格,句與句之間用 來分割...

linux學習筆記17 管好網路

網路介面 network inte ce ifconfig 所有使用者都可以用此命令檢視網路介面,但是只有root使用者才可以操縱網路介面 此講中所有網路都是指的乙太網 stu localhost ifconfig eth0 link encap ethernet hwaddr 00 0c 29 5...