使用SIGALRM訊號量和sleep衝突的解決辦法
系統中的一個模組需要頻繁的獲取系統時間,使用linux中內建的函式開銷過大,因為需要的精度不是很高(毫秒級),索性用signal函式配合setitimer實現了個簡易的全域性時鐘。
但是後來發現,SIGALRM的中斷訊號回終止sleep,因為sleep就是用SIGALRM訊號量實現的,得另想方案。
這個替代方案就是POSIX中內建的定時器:timer_create()(建立)、timer_settime()(初始化)以及timer_delete(銷燬),將自己的時間訊號處理函式用timer_create註冊為SIGUSR2,這樣就不會中斷sleep了。
POSIX定時器:timer_settime()
最強大的定時器介面來自POSIX時鐘系列,其建立、初始化以及刪除一個定時器的行動被分為三個不同的函式:timer_create()(建立定時器)、timer_settime()(初始化定時器)以及timer_delete(銷燬它)。
建立一個定時器:
int timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid)
[cpp] view plaincopyprint?- struct itimespec{
- struct timespec it_interval;
- struct
- };
struct itimespec{
struct timespec it_interval;
struct timespec it_value;
};
程序可以通過呼叫timer_create()建立特定的定時器,定時器是每個程序自己的,不是在fork時繼承的。clock_id說明定時器是基於哪個時鐘的,*timerid裝載的是被建立的定時器的ID。該函式建立了定時器,並將他的ID 放入timerid指向的位置中。引數evp指定了定時器到期要產生的非同步通知。如果evp為NULL,那麼定時器到期會產生預設的訊號,對 CLOCK_REALTIMER來說,預設訊號就是SIGALRM。如果要產生除預設訊號之外的其它訊號,程式必須將 evp->sigev_signo設定為期望的訊號碼。struct
sigevent 結構中的成員evp->sigev_notify說明了定時器到期時應該採取的行動。通常,這個成員的值為SIGEV_SIGNAL,這個值說明在定時器到期時,會產生一個訊號。程式可以將成員evp->sigev_notify設為SIGEV_NONE來防止定時器到期時產生訊號。
如果幾個定時器產生了同一個訊號,處理程式可以用 evp->sigev_value來區分是哪個定時器產生了訊號。要實現這種功能,程式必須在為訊號安裝處理程式時,使用struct sigaction的成員sa_flags中的標誌符SA_SIGINFO。
clock_id取值為以下:
CLOCK_REALTIME :Systemwide realtime clock.
CLOCK_MONOTONIC:Represents monotonic time. Cannot be set.
CLOCK_PROCESS_CPUTIME_ID :High resolution per-process timer.
CLOCK_THREAD_CPUTIME_ID :Thread-specific timer.
CLOCK_REALTIME_HR :High resolution version of CLOCK_REALTIME.
CLOCK_MONOTONIC_HR :High resolution version of CLOCK_MONOTONIC.
- struct sigevent
- {
- int sigev_notify; //notification type
- int sigev_signo; //signal number
- union sigval sigev_value; //signal valu
- void (*sigev_notify_function)(union sigval)
- pthread_attr_t *sigev_notify_attributes
- }
- union sigval
- {
- int sival_int; //integer valu
- void *sival_ptr; //pointer value
- }
struct sigevent
{
int sigev_notify; //notification type
int sigev_signo; //signal number
union sigval sigev_value; //signal valu
void (*sigev_notify_function)(union sigval)
pthread_attr_t *sigev_notify_attributes
}
union sigval
{
int sival_int; //integer valu
void *sival_ptr; //pointer value
}
通過將evp->sigev_notify設定為如下值來定製定時器到期後的行為:
SIGEV_NONE:什麼都不做,只提供通過timer_gettime和timer_getoverrun查詢超時資訊。
SIGEV_SIGNAL: 當定時器到期,核心會將sigev_signo所指定的訊號傳送給程序。在訊號處理程式中,si_value會被設定會sigev_value。
SIGEV_THREAD: 當定時器到期,核心會(在此程序內)以sigev_notification_attributes為執行緒屬性建立一個執行緒,並且讓它執行sigev_notify_function,傳入sigev_value作為為一個引數。
啟動一個定時器:
timer_create()所建立的定時器並未啟動。要將它關聯到一個到期時間以及啟動時鐘週期,可以使用timer_settime()。
int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspect *ovalue);
如同settimer(),it_value用於指定當前的定時器到期時間。當定時器到期,it_value的值會被更新成it_interval 的值。如果it_interval的值為0,則定時器不是一個時間間隔定時器,一旦it_value到期就會回到未啟動狀態。timespec的結構提供了納秒級解析度:
- struct timespec{
- time_t tv_sec;
- long tv_nsec;
- };
struct timespec{
time_t tv_sec;
long tv_nsec;
};
如果flags的值為TIMER_ABSTIME,則value所指定的時間值會被解讀成絕對值(此值的預設的解讀方式為相對於當前的時間)。這個經修改的行為可避免取得當前時間、計算“該時間”與“所期望的未來時間”的相對差額以及啟動定時器期間造成競爭條件。
如果ovalue的值不是NULL,則之前的定時器到期時間會被存入其所提供的itimerspec。如果定時器之前處在未啟動狀態,則此結構的成員全都會被設定成0。
獲得一個活動定時器的剩餘時間:
int timer_gettime(timer_t timerid,struct itimerspec *value);
取得一個定時器的超限執行次數:
有可能一個定時器到期了,而同一定時器上一次到期時產生的訊號還處於掛起狀態。在這種情況下,其中的一個訊號可能會丟失。這就是定時器超限。程式可以通過呼叫timer_getoverrun來確定一個特定的定時器出現這種超限的次數。定時器超限只能發生在同一個定時器產生的訊號上。由多個定時器,甚至是那些使用相同的時鐘和訊號的定時器,所產生的訊號都會排隊而不會丟失。
int timer_getoverrun(timer_t timerid);
執行成功時,timer_getoverrun()會返回定時器初次到期與通知程序(例如通過訊號)定時器已到期之間額外發生的定時器到期次數。舉例來說,在我們之前的例子中,一個1ms的定時器運行了10ms,則此呼叫會返回9。如果超限執行的次數等於或大於DELAYTIMER_MAX,則此呼叫會返回DELAYTIMER_MAX。
執行失敗時,此函式會返回-1並將errno設定會EINVAL,這個唯一的錯誤情況代表timerid指定了無效的定時器。
刪除一個定時器:
int timer_delete (timer_t timerid);
一次成功的timer_delete()呼叫會銷燬關聯到timerid的定時器並且返回0。執行失敗時,此呼叫會返回-1並將errno設定會 EINVAL,這個唯一的錯誤情況代表timerid不是一個有效的定時器。
例1:
- void handle()
- {
- time_t t;
- char p[32];
- time(&t);
- strftime(p, sizeof(p), "%T", localtime(&t));
- printf("time is %s\n", p);
- }
- int main()
- {
- struct sigevent evp;
- struct itimerspec ts;
- timer_t timer;
- int ret;
- evp.sigev_value.sival_ptr = &timer;
- evp.sigev_notify = SIGEV_SIGNAL;
- evp.sigev_signo = SIGUSR1;
- signal(SIGUSR1, handle);
- ret = timer_create(CLOCK_REALTIME, &evp, &timer);
- if( ret )
- perror("timer_create");
- ts.it_interval.tv_sec = 1;
- ts.it_interval.tv_nsec = 0;
- ts.it_value.tv_sec = 3;
- ts.it_value.tv_nsec = 0;
- ret = timer_settime(timer, 0, &ts, NULL);
- if( ret )
- perror("timer_settime");
- while(1);
- }
void handle()
{
time_t t;
char p[32];
time(&t);
strftime(p, sizeof(p), "%T", localtime(&t));
printf("time is %s\n", p);
}
int main()
{
struct sigevent evp;
struct itimerspec ts;
timer_t timer;
int ret;
evp.sigev_value.sival_ptr = &timer;
evp.sigev_notify = SIGEV_SIGNAL;
evp.sigev_signo = SIGUSR1;
signal(SIGUSR1, handle);
ret = timer_create(CLOCK_REALTIME, &evp, &timer);
if( ret )
perror("timer_create");
ts.it_interval.tv_sec = 1;
ts.it_interval.tv_nsec = 0;
ts.it_value.tv_sec = 3;
ts.it_value.tv_nsec = 0;
ret = timer_settime(timer, 0, &ts, NULL);
if( ret )
perror("timer_settime");
while(1);
}
例2:
- void handle(union sigval v)
- {
- time_t t;
- char p[32];
- time(&t);
- strftime(p, sizeof(p), "%T", localtime(&t));
- printf("%s thread %lu, val = %d, signal captured.\n", p, pthread_self(), v.sival_int);
- return;
- }
- int main()
- {
- struct sigevent evp;
- struct itimerspec ts;
- timer_t timer;
- int ret;
- memset (&evp, 0, sizeof (evp));
- evp.sigev_value.sival_ptr = &timer;
- evp.sigev_notify = SIGEV_THREAD;
- evp.sigev_notify_function = handle;
- evp.sigev_value.sival_int = 3; //作為handle()的引數
- ret = timer_create(CLOCK_REALTIME, &evp, &timer);
- if( ret)
- perror("timer_create");
- ts.it_interval.tv_sec = 1;
- ts.it_interval.tv_nsec = 0;
- ts.it_value.tv_sec = 3;
- ts.it_value.tv_nsec = 0;
- ret = timer_settime(timer, TIMER_ABSTIME, &ts, NULL);
- if( ret )
- perror("timer_settime");
- while(1);
- }
void handle(union sigval v)
{
time_t t;
char p[32];
time(&t);
strftime(p, sizeof(p), "%T", localtime(&t));
printf("%s thread %lu, val = %d, signal captured.\n", p, pthread_self(), v.sival_int);
return;
}
int main()
{
struct sigevent evp;
struct itimerspec ts;
timer_t timer;
int ret;
memset (&evp, 0, sizeof (evp));
evp.sigev_value.sival_ptr = &timer;
evp.sigev_notify = SIGEV_THREAD;
evp.sigev_notify_function = handle;
evp.sigev_value.sival_int = 3; //作為handle()的引數
ret = timer_create(CLOCK_REALTIME, &evp, &timer);
if( ret)
perror("timer_create");
ts.it_interval.tv_sec = 1;
ts.it_interval.tv_nsec = 0;
ts.it_value.tv_sec = 3;
ts.it_value.tv_nsec = 0;
ret = timer_settime(timer, TIMER_ABSTIME, &ts, NULL);
if( ret )
perror("timer_settime");
while(1);
}
相關推薦
使用SIGALRM訊號量和sleep衝突的解決辦法
系統中的一個模組需要頻繁的獲取系統時間,使用linux中內建的函式開銷過大,因為需要的精度不是很高(毫秒級),索性用signal函式配合setitimer實現了個簡易的全域性時鐘。 但是後來發現,SIGALRM的中斷訊號回終止sleep,因為sleep就是用SIGALRM
ScrollView(Listview)和Viewpager(banner)的衝突解決辦法
原文地址:https://blog.csdn.net/qq_36255612/article/details/77987947 其實就是在onInterceptTouchEvent中做處理即可: 也可以直接使用下面的自定義: public class MyScrollView exte
同一個dom上加單擊事件和雙擊事件的衝突解決辦法,雙擊事件方法進不去
data() { return { TimeFn:''//定義公用變數}} $(".proManage fieldset ul li").dblclick(function(){//雙擊播放專案 //雙擊事件執行的方法 this.TimeFn = ""}) $(".proManage
git 開發注意問題和衝突解決辦法
1、分支切換,一般需要將當前分支全部提交。如不提交,可以stash(暫存),考慮當前分支未提交部分是否需要merge到目標分支,如果需要,直接切換,如果不要先提交或者暫存。 git checkout [branch-name] 如果[branch-name] 遠端分支有,
Django忘記管理員賬號和密碼的解決辦法
com server superuser 技術分享 tor reat n) 一個 min 看著Django的教程學習搭建網站,結果忘記第一次創建的賬號和密碼了。結果搭建成功以後,一直無法登陸到管理頁面,進行不下去了。 如圖所示: 在網上找了很多的方法都不行,最後使用新建一個
HttpWebRequest的GetResponse或GetRequestStream偶爾超時 + 總結各種超時死掉的可能和相應的解決辦法
遇到 padding conn 計算 動作 spa 多次 獲得 archive 用C#模擬網頁登陸,其中去請求幾個頁面,會發起對應的http的請求request,其中keepAlive設置為true,提交請求後,然後會有對應的response: resp = (HttpW
for批處理skip參數不支持變量延遲!n!的解決辦法
+= txt amp lse AS 參數 處理 off 變量延遲 a.txt 文件a第1行 文件a第2行 文件a第3行 b.txt 文件b第1行 文件b第2行 文件b第3行 合並ab .bat @echo off REM 把兩個文件逐
alembic常用命令和經典錯誤解決辦法
經典 bsp ima 分享 技術分享 nbsp 技術 經典錯誤 bic alembic常用命令和經典錯誤解決辦法
Pycharm載入第三方外掛失敗方法(關鍵字:Nothing to show)和安裝失敗解決辦法
一、修復外掛顯示錯誤,共3個步驟: 1,新增額外源: 清華:https://pypi.tuna.tsinghua.edu.cn/simple 阿里雲:http://mirrors.aliyun.com/pypi/simple/ 中國科技大學 https://pypi.mi
Linux多執行緒程式設計---執行緒間同步(互斥鎖、條件變數、訊號量和讀寫鎖)
本篇博文轉自http://zhangxiaoya.github.io/2015/05/15/multi-thread-of-c-program-language-on-linux/ Linux下提供了多種方式來處理執行緒同步,最常用的是互斥鎖、條件變數、訊號量和讀寫鎖。 下面是思維導
innerHTML與button事件衝突解決辦法
事情描述,我在body裡面寫了如下一個button <body> <input id="btn" type="button" value="自動生成V提高版本"> </body> 然後在js裡面獲取了這個button,然後給它新增點選事件 var b
關於mac上操作nginx的命令以及遇到的問題和對應的解決辦法
1、mac上查詢nginx安裝位置 在終端輸入: nginx -V 檢視nginx版本及安裝的本地位置 ngxin -v 檢視nginx版本(此方法依然可以檢測是否安裝某一軟體,如git,hg等) 2、在Mac上用brew安裝Nginx,然後修改Nginx配置檔案,再重啟時報出如下錯
CoordinatorLayout 巢狀Recyclerview在巢狀Recyclerview滑動出現衝突解決辦法
RecyclerView巢狀RecycleView 要做一個介面,CoordinatorLayout巢狀AppBarLayout和RecyclerView來實現摺疊滑動,我的RecycleView裡面佈局較多,計劃再嵌入RecyclerView來實現,當我用到RecyclerView新增
Git程式碼衝突解決辦法
如果伺服器上的檔案發生了更改了的話,在本地更改該檔案之前未使用git pull命令的話,那麼在本地修改完該檔案後使用git pull 或者git push時會發生衝突: error: Your local changes to the following files would be overw
表單驗證——input和required衝突解決
1. input和required衝突解決 Question: 使用表單提交驗證必填欄位時,若同時給 input[type="file"] 新增 readonly 以及 required 屬性,則發現,required必填驗證失效,既不會提示必填,也可以成功提交。 解決方法:將 r
HashMap原理及衝突解決辦法
class HashMap<K,V> extends AbstractMap<K,V> HashMap put() HashMap get() 1.put() HashMap put()方法原始碼如下:
maven依賴衝突解決辦法
一般的開發,maven依賴衝突基本不存在,但是如果專案多,依賴複雜,就說不定了。依賴衝突說明專案依賴的某一個jar包,有多個不同的版本,至少兩個或兩個以上,對於這種問題,最直接的就是通過修改專案依賴的版本為最新的版本即可。同時,也有另一種解決辦法,就是將傳遞依賴剪除掉(低版本的那個依
hash衝突解決和javahash衝突解決
其實就是四種方法的演變 1.開放定址法 具體就是把資料的標誌等的對長度取模 有三種不同的取模 線性探測再雜湊 給資料的標誌加增量,取模 平方探測再雜湊 給資料的標誌平方,取模 隨機探測再雜湊 把資料的標誌隨機化,取模 線性,平方顯然很容被人猜出規律,所以最終是隨機
Oracle資料庫安裝+漢化版PLsql+Oracle外掛,plsql連線Oracle步驟和報錯解決辦法
從https://download.csdn.net/download/fxiaoyaole/10449523 此連結下載裡面有所資源,資源包括(Oracle兩個資料庫壓縮包win64_11gR2_database_1of2, win64_11gR2_database
有關訊號量和PV操作的易(粗)懂(淺)理解
大概只有作業系統老師佈置的作業(要交)能讓我認真學習吧…… 訊號量Semaphore 1.有關訊號量的一些說明: 訊號量S是一個整數,S大於等於零時代表可供併發程序使用的資源實體數,但S小於零時