新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 多線程中定時器的使用

        多線程中定時器的使用

        作者: 時間:2016-11-24 來源:網絡 收藏
        不管是在進程還是線程,很多時候我們都會使用一些定時器之類的功能,這里就定時器在多線程的使用說一下。首先在linux編程中定時器函數有alarm()和setitimer(),alarm()可以提供一個基于秒的定時功能,而setitimer可以提供一個基于微妙的定時功能。 alarm()原型:
        #i nclude
        unsigned int alarm(unsigned int seconds);
        這個函數在使用上很簡單,第一次調用這個函數的時候是設置定時器的初值,下一次調用是重新設置這個值,并會返回上一次定時的剩余時間。
        setitimer()原型:
        #i nclude
        int setitimer(int which, const struct itimerval *value,
        struct itimerval *ovalue);
        這個函數使用起來稍微有點說法,首先是第一個參數which的值,這個參數設置timer的計時策略,which有三種狀態(tài)分別是:
        ITIMER_REAL:使用系統時間來計數,時間為0時發(fā)出SIGALRM信號,這種定時能夠得到一個精準的定時,當然這個定時是相對的,因為到了微秒級別我們的處理器本身就不夠精確。
        ITIMER_VIRTUAL:使用進程時間也就是進程分配到的時間片的時間來計數,時間為0是發(fā)出SIGVTALRM信號,這種定時顯然不夠準確,因為系統給進程分配時間片不由我們控制。
        ITIMER_PROF:上面兩種情況都能夠觸發(fā)
        第二個參數參數value涉及到兩個結構體:
        struct itimerval {
        struct timeval it_interval;
        struct timeval it_value;
        };

        struct timeval {
        long tv_sec;
        long tv_usec;
        };
        在結構體itimerval中it_value是定時器當前的值,it_interval是當it_value的為0后重新填充的值。而timeval結構體中的兩個變量就簡單了一個是秒一個是微秒。
        上面是這兩個定時函數的說明,這個函數使用本不是很難,可以說是很簡單,但是碰到具體的應用的時候可能就遇到問題了,在多進程編程中使用一般不會碰到什么問題,這里說的這些問題主要體現在多線程編程中。比如下面這個程序
        #i nclude
        #i nclude
        #i nclude
        #i nclude
        #i nclude
        #i nclude

        void sig_handler(int signo)
        {
        alarm(2);
        printf("alarm signal");
        }

        void *pthread_func()
        {
        alarm(2);
        while(1)
        {
        pause();
        }
        }

        int main(int argc, char **argv)
        {
        pthread_t tid;
        int retval;

        signal(SIGALRM, sig_handler);

        if((retval = pthread_create(&tid, NULL, pthread_func, NULL)) < 0)
        {
        perror("pthread_create");
        exit(-1);
        }

        while(1)
        {
        printf("main thread");
        sleep(10);
        }
        return 0;
        }
        這個程序的理想結果是:
        main thread
        alarm signal
        alarm signal
        alarm signal
        alarm signal
        alarm signal
        main thread
        可事實上并不是這樣的,它的結果是:
        main pthread
        alarm signal
        main pthread
        alarm signal
        main pthread
        為什么會出現這種情況呢?是因為發(fā)送給工作線程的信號中斷的主線程的sleep,并且這個中情況只影響主線程而不會影響到其他的工作線程。我們怎么才能解決這種問題呢,最簡單的方法是修改這個程序,修改這個線程主線程使用alarm,工作線程使用sleep。這樣就能夠達到我們的要求,但是有時候有不能簡單的這樣操作。所以我們就需要進一步的修改我們的程序。在這里我第一個想到的是使用signal(SIGALRM, SIG_IGN),可是這個是設置整個進程對這個信號的響應方式,經過測試也確實不能完成我期望的功能,那么怎么辦呢?有這樣一個函數pthread_sigmask,線程中的信號屏蔽,函數的原型及相關函數為:
        #i nclude
        int pthread_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
        函數中第一個參數how有三個值SIG_BLOCK、SIG_SETMASK和SIG_UNBLOCK這里我們是用第二個值SIG_SETMASK
        int sigemptyset(sigset_t *set);
        int sigaddset(sigset_t *set, int signum);
        然后我們改造我們的程序為:
        #i nclude
        #i nclude
        #i nclude
        #i nclude
        #i nclude
        #i nclude

        void sig_handler(int signo)
        {
        alarm(2);
        printf("alarm signal");
        }

        void *pthread_func()
        {
        alarm(2);
        while(1)
        {
        pause();
        }
        }

        int main(int argc, char **argv)
        {
        pthread_t tid, tid_1;
        int retval;

        signal(SIGALRM, sig_handler);

        if((retval = pthread_create(&tid, NULL, pthread_func, NULL)) < 0)
        {
        perror("pthread_create");
        exit(-1);
        }

        sigset_t sigset;
        sigemptyset(&sigset);
        sigaddset(&sigset, SIGALRM);
        pthread_sigmask(SIG_SETMASK,&sigset,NULL);

        while(1)
        {
        printf("main pthread");
        sleep(10);
        }
        return 0;
        }
        這個時候我們就能夠看到我們想要的結果了。
        這里再附一個setitimer的使用范例
        #i nclude
        #i nclude
        #i nclude
        #i nclude
        #i nclude
        #i nclude

        struct itimerval timerval;
        void sig_handler(int signo)
        {
        printf("alarm signal");
        }


        void *pthread_func()
        {

        setitimer(ITIMER_REAL, &timerval, NULL);
        while(1)
        {
        pause();
        }
        }

        int main(int argc, char **argv)
        {
        pthread_t tid;
        int retval;
        timerval.it_interval.tv_sec = 2;
        timerval.it_interval.tv_usec = 0;
        timerval.it_value.tv_sec = 2;
        timerval.it_value.tv_usec = 0;

        signal(SIGALRM, sig_handler);

        if((retval = pthread_create(&tid, NULL, pthread_func, NULL)) < 0)
        {
        perror("pthread_create");
        exit(-1);
        }

        sigset_t sigset;
        sigemptyset(&sigset);
        sigaddset(&sigset, SIGALRM);
        pthread_sigmask(SIG_SETMASK,&sigset,NULL);

        while(1)
        {
        printf("main thread");
        sleep(5);
        }




        return 0;

        }



        關鍵詞: 多線程定時

        評論


        技術專區(qū)

        關閉
        主站蜘蛛池模板: 紫金县| 和顺县| 天全县| 来凤县| 登封市| 保亭| 井冈山市| 宁化县| 五大连池市| 台南市| 含山县| 连州市| 宜兰县| 湘西| 准格尔旗| 双柏县| 辛集市| 娱乐| 和田市| 勐海县| 洪雅县| 慈利县| 遂平县| 商都县| 合作市| 惠州市| 颍上县| 广宗县| 涪陵区| 射阳县| 澳门| 竹北市| 精河县| 沾化县| 武安市| 禹州市| 乌兰县| 密云县| 宜城市| 清远市| 青神县|