成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

在 Linux 中創建定時器

系統 Linux
這是一個演示如何創建 POSIX 兼容的間隔定時器的教程。

對開發人員來說,定時某些事件是一項常見任務。定時器的常見場景是看門狗、任務的循環執行,或在特定時間安排事件。在這篇文章中,我將演示如何使用 ??timer_create(...)?? 創建一個 POSIX 兼容的間隔定時器。

你可以從 ??GitHub?? 下載下面樣例的源代碼。

準備 Qt Creator

我使用 ??Qt Creator??? 作為該樣例的 IDE。為了在 Qt Creator 運行和調試樣例代碼,請克隆 ??GitHub?? 上的倉庫,打開 Qt Creator,在 “文件File -> 打開文件或項目……Open File or Project...” 并選擇 “CMakeLists.txt”:

在 Qt Creator 中打開項目

在 Qt Creator 中打開項目

選擇工具鏈之后,點擊 “配置項目Configure Project”。這個項目包括三個獨立的樣例(我們在這篇文章中將只會用到其中的兩個)。使用綠色標記出來的菜單,可以在每個樣例的配置之間切換,并為每個樣例激活在終端運行 “在終端中運行Run in terminal”(用黃色標記)。當前用于構建和調試的活動示例可以通過左下角的“調試Debug” 按鈕進行選擇(參見下面的橙色標記)。

項目配置

項目配置

線程定時器

讓我們看看 ??simple_threading_timer.c??? 樣例。這是最簡單的一個。它展示了一個調用了超時函數 ??expired??? 的間隔定時器是如何被創建的。在每次過期時,都會創建一個新的線程,在其中調用函數 ??expired??:

#include <stdio.h>#include <stdlib.h>#include <time.h>#include <signal.h>#include <unistd.h>#include <string.h>#include <errno.h>void expired(union sigval timer_data);pid_t gettid(void);struct t_eventData{    int myData;};int main(){    int res = 0;    timer_t timerId = 0;    struct t_eventData eventData = { .myData = 0 };    /*  sigevent 指定了過期時要執行的操作  */    struct sigevent sev = { 0 };    /* 指定啟動延時時間和間隔時間     * it_value和it_interval 不能為零 */    struct itimerspec its = {   .it_value.tv_sec  = 1,                                .it_value.tv_nsec = 0,                                .it_interval.tv_sec  = 1,                                .it_interval.tv_nsec = 0                            };    printf("Simple Threading Timer - thread-id: %d\n", gettid());    sev.sigev_notify = SIGEV_THREAD;    sev.sigev_notify_function = &expired;    sev.sigev_value.sival_ptr = &eventData;    /* 創建定時器 */    res = timer_create(CLOCK_REALTIME, &sev, &timerId);    if (res != 0){        fprintf(stderr, "Error timer_create: %s\n", strerror(errno));        exit(-1);    }    /* 啟動定時器 */    res = timer_settime(timerId, 0, &its, NULL);    if (res != 0){        fprintf(stderr, "Error timer_settime: %s\n", strerror(errno));        exit(-1);    }    printf("Press ETNER Key to Exit\n");    while(getchar()!='\n'){}    return 0;}void expired(union sigval timer_data){    struct t_eventData *data = timer_data.sival_ptr;    printf("Timer fired %d - thread-id: %d\n", ++data->myData, gettid());}

這種方法的優點是在代碼和簡單調試方面用量小。缺點是由于到期時創建新線程而增加額外的開銷,因此行為不太確定。

中斷信號定時器

超時定時器通知的另一種可能性是基于 ??內核信號??。內核不是在每次定時器過期時創建一個新線程,而是向進程發送一個信號,進程被中斷,并調用相應的信號處理程序。

由于接收信號時的默認操作是終止進程(參考 ??signal?? 手冊頁),我們必須要提前設置好 Qt Creator,以便進行正確的調試。

當被調試對象接收到一個信號時,Qt Creator 的默認行為是:

  • 中斷執行并切換到調試器上下文。
  • 顯示一個彈出窗口,通知用戶接收到信號。

這兩種操作都不需要,因為信號的接收是我們應用程序的一部分。

Qt Creator 在后臺使用 GDB。為了防止 GDB 在進程接收到信號時停止執行,進入 “工具(Tools) -> 選項Options” 菜單,選擇 “調試器Debugger”,并導航到 “本地變量和表達式Locals & Expressions”。添加下面的表達式到 “定制調試助手Debugging Helper Customization”:

handle SIG34 nostop pass

Sig 34 時不停止

Sig 34 時不停止

你可以在 ??GDB 文檔?? 中找到更多關于 GDB 信號處理的信息。

接下來,當我們在信號處理程序中停止時,我們要抑制每次接收到信號時通知我們的彈出窗口:

Signal 34 彈出窗口

Signal 34 彈出窗口

為此,導航到 “GDB” 標簽并取消勾選標記的復選框:

定時器信號窗口

定時器信號窗口

現在你可以正確的調試 ??signal_interrupt_timer??。真正的信號定時器的實施會更復雜一些:

#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <unistd.h>#include <signal.h>#include <time.h>#include <unistd.h>#include <errno.h>#include <string.h>#define UNUSED(x) (void)(x)static void handler(int sig, siginfo_t *si, void *uc);pid_t gettid(void);struct t_eventData{    int myData;};int main(){    int res = 0;    timer_t timerId = 0;    struct sigevent sev = { 0 };    struct t_eventData eventData = { .myData = 0 };    /* 指定收到信號時的操作 */    struct sigaction sa = { 0 };    /* 指定啟動延時的時間和間隔時間 */    struct itimerspec its = {   .it_value.tv_sec  = 1,                                .it_value.tv_nsec = 0,                                .it_interval.tv_sec  = 1,                                .it_interval.tv_nsec = 0                            };    printf("Signal Interrupt Timer - thread-id: %d\n", gettid());    sev.sigev_notify = SIGEV_SIGNAL; // Linux-specific    sev.sigev_signo = SIGRTMIN;    sev.sigev_value.sival_ptr = &eventData;    /* 創建定時器 */    res = timer_create(CLOCK_REALTIME, &sev, &timerId);    if ( res != 0){        fprintf(stderr, "Error timer_create: %s\n", strerror(errno));        exit(-1);    }    /* 指定信號和處理程序 */    sa.sa_flags = SA_SIGINFO;    sa.sa_sigaction = handler;    /* 初始化信號 */    sigemptyset(&sa.sa_mask);    printf("Establishing handler for signal %d\n", SIGRTMIN);    /* 注冊信號處理程序 */    if (sigaction(SIGRTMIN, &sa, NULL) == -1){        fprintf(stderr, "Error sigaction: %s\n", strerror(errno));        exit(-1);    }    /* 啟動定時器 */    res = timer_settime(timerId, 0, &its, NULL);    if ( res != 0){        fprintf(stderr, "Error timer_settime: %s\n", strerror(errno));        exit(-1);    }    printf("Press ENTER to Exit\n");    while(getchar()!='\n'){}    return 0;}static voidhandler(int sig, siginfo_t *si, void *uc){    UNUSED(sig);    UNUSED(uc);    struct t_eventData *data = (struct t_eventData *) si->_sifields._rt.si_sigval.sival_ptr;    printf("Timer fired %d - thread-id: %d\n", ++data->myData, gettid());}

與線程定時器相比,我們必須初始化信號并注冊一個信號處理程序。這種方法性能更好,因為它不會導致創建額外的線程。因此,信號處理程序的執行也更加確定。缺點顯然是正確調試需要額外的配置工作。

總結

本文中描述的兩種方法都是接近內核的定時器的實現。不過,即使 ??timer_create(...)?? 函數是 POSIX 規范的一部分,由于數據結構的細微差別,也不可能在 FreeBSD 系統上編譯樣例代碼。除了這個缺點之外,這種實現還為通用計時應用程序提供了細粒度控制。

責任編輯:龐桂玉 來源: Linux中國
相關推薦

2018-11-02 08:10:58

Linuxsystemd定時器

2009-11-11 10:14:10

linux定時器操作系統

2021-08-03 14:33:53

cron定時器Linux命令

2021-08-11 10:10:26

Linux定時器數組

2023-12-11 09:50:35

Linux定時器

2010-03-17 12:37:51

Python定時器

2022-11-11 14:55:14

Linuxcron

2010-07-28 15:56:22

FlexTimer定時

2011-04-21 10:49:28

Linux時間定時器

2009-04-12 08:51:50

Symbian諾基亞移動OS

2011-02-23 10:20:45

2013-07-29 10:10:40

TCP協議TCP定時器TCP

2021-03-31 08:33:17

SysTick定時器SysTick定時器

2022-11-02 11:40:16

Flowable定時器流程

2024-06-03 00:00:20

.NET定時器

2023-08-02 09:26:03

軟件定時器鴻蒙

2017-02-28 17:18:34

Linux驅動技術內核定時器

2023-11-01 11:13:58

Linux信號處理定時器

2023-02-28 18:09:53

Javascript定時器

2014-12-09 16:30:18

TCP定時器
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品毛片 | 久久久久久久久久久一区二区 | 农村妇女毛片精品久久久 | 中文字幕av中文字幕 | 亚洲精品国产区 | 色偷偷人人澡人人爽人人模 | 国产一区二区三区四区区 | 亚洲视频在线一区 | 成人免费视频观看视频 | 午夜免费网站 | 日韩有码一区二区三区 | 欧美成人猛片aaaaaaa | 国产高清自拍视频在线观看 | 国产亚洲精品美女久久久久久久久久 | 国产精品美女久久久久aⅴ国产馆 | 国产精品九九视频 | 一区二区三区欧美 | 97久久久 | 亚洲大片在线观看 | 久在线视频 | 国产一级淫片a直接免费看 免费a网站 | 日韩国产精品一区二区三区 | 日韩精品一区二区三区高清免费 | 最新日韩av | 欧美在线不卡 | 日韩欧美综合在线视频 | 免费看爱爱视频 | 久久精品无码一区二区三区 | 国产乱码精品一区二区三区忘忧草 | 999久久久久久久久 国产欧美在线观看 | 亚洲激情在线观看 | 欧美一区二区在线观看 | 日韩国产高清在线观看 | 热99精品视频 | 国产成人精品一区二区三 | 久久aⅴ乱码一区二区三区 91综合网 | 国产精品1区2区 | 天堂网中文字幕在线观看 | 欧美视频免费在线 | 精品久久久久久亚洲综合网 | 99久久婷婷 |