APUE習題10.5之implementing software timer
題目:僅使用一個定時器,構造一組函式,使得程序在該單一定時器基礎上可以設定任意數量的定時器。
first mytimer.h
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <time.h> #include <unistd.h> #include <limits.h> #define TRUE 1 #define FALSE 0 #define MAX_TIMERS 100 // 最大定時器數 #define VERY_LONG_TIME LONG_MAX // 最長定時數 typedef time_t TIME; // 隱藏TIME的實現 typedef void timer_handler(void *arg); volatile TIME time_now,time_set; // now為當前時間,set為當前定時器設定時間 struct sigaction newact,oldact; // 設定sigalrm的處理程式 sigset_t newmask,oldmask; // 設定遮蔽字 struct timer { int inuse; // true if in use TIME time; // relative time to wait timer_handler *ahandler; // called when the timer has expired void *arg; // arguemtn of handler }timers[MAX_TIMERS]; struct timer *timer_next; void timer_init(void); // 初始化計時器 struct timer* timer_declare(TIME,timer_handler*,void*); // 生成一個計時器 void timer_undeclare(struct timer*); // 取消一個計時器 void timer_update(); // 更新計時器陣列,並獲得下一個將要計時的計時器 void timer_out_handler(int signo); // 訊號處理函式 void func(void *arg); // 自定義輸出函式
second mytimer.c
#include "mytimer.h" static void disable_interrupt(void) // 關閉中斷 { sigemptyset(&newmask); sigaddset(&newmask,SIGINT); if(sigprocmask(SIG_BLOCK,&newmask,&oldmask) < 0) fprintf(stderr,"sigprocmask error\n"); } static void enable_interrupt(void) // 開啟中斷 { if(sigprocmask(SIG_SETMASK,&oldmask,NULL) < 0) fprintf(stderr,"sigprocmask error\n"); } void timer_init(void) { int i; disable_interrupt(); for(i = 0;i<MAX_TIMERS;i++) timers[i].inuse = FALSE; // 將計時器陣列中每個計時器inuse狀態設定為未用 sigfillset(&newact.sa_mask); // 在處理訊號時,阻塞所有訊號的遞送 newact.sa_flags = 0; newact.sa_handler = timer_out_handler; if(sigaction(SIGALRM,&newact,&oldact) < 0) { fprintf(stderr,"sigaction error\n"); enable_interrupt(); return; } enable_interrupt(); } struct timer* timer_declare(TIME time_s,timer_handler *handler,void *arg) { int i; disable_interrupt(); for(i = 0;i<MAX_TIMERS;i++) // 找到第一個未用的計時器 if(!timers[i].inuse) break; if(i == MAX_TIMERS) // 所有計時器都已用完 { enable_interrupt(); return NULL; } timers[i].time = time_s; // 計時器時間 timers[i].ahandler = handler; // 計時器處理函式 timers[i].arg = arg; // 處理函式引數 if(!timer_next) // 當前計時器為唯一計時器 { time_set = time(NULL); // 儲存當前設定時間 alarm((timer_next = &timers[i])->time); // 開始計時 }else if(time_s < (timer_next->time - (time(NULL) - time_set))) // 比較當前計時器和當前正在計時的計時器的時間長度 { timer_update(); // 更新每個計時器的計時 timer_next = &timers[i]; // 設定新的當前正在計時的計時器 time_set = time(NULL); // 記錄設定時間 alarm(timer_next->time); // 開始計時 } timers[i].inuse = TRUE; // 最後再改變inuse防止update干擾 enable_interrupt(); return &timers[i]; } void timer_undeclare(struct timer* t) { disable_interrupt(); if(!t->inuse) { enable_interrupt(); return; } t->inuse = FALSE; if(t == timer_next) // 如果是當前正在計時的計時器 timer_update(); enable_interrupt(); } void timer_update() // 更新所有計時器時間,並將時間最短的設定為當前正在計時的計時器。 { disable_interrupt(); int i; static struct timer timer_last = {FALSE,VERY_LONG_TIME,NULL,NULL}; timer_next = &timer_last; time_now = time(NULL); // 讀取當前時間 for(i = 0;i<MAX_TIMERS;i++) { if(timers[i].inuse) { timers[i].time -= time_now - time_set; // 所有計時更新 if(timers[i].time < timer_next->time) timer_next = &timers[i]; // 更新當前正在計時的計時器 } } if(timer_next->inuse) // 如果存在還未發生的定時器 { alarm(timer_next->time); time_set = time(NULL); }else timer_next = NULL; enable_interrupt(); } void timer_out_handler(int signo) { timer_next->ahandler(timer_next->arg); timer_next->inuse = FALSE; timer_update(); // 尋找下一個執行的定時器 } void func(void* arg) { char *p = (char*)arg; printf("%s\n",p); } Contact GitHub API Training Shop Blog About © 2017 GitHub, Inc. Terms Privacy Security Status Help
third main.c
#include "mytimer.c" int main() { setbuf(stdout,NULL); timer_init(); TIME time = 1; timer_declare(time,func,(void*)"hello world"); time = 3; struct timer* t =timer_declare(time,func,(void*)"this is a test"); time = 5; struct timer* m = timer_declare(time,func,(void*)"func(5)"); timer_undeclare(t); while(1) pause(); exit(0); }
執行結果
具體專案程式碼可見:https://github.com/xiaoHzp/apue/tree/master/ch10/simple10_5
相關推薦
APUE習題10.5之implementing software timer
題目:僅使用一個定時器,構造一組函式,使得程序在該單一定時器基礎上可以設定任意數量的定時器。 first mytimer.h #include <stdio.h> #include <stdlib.h> #include <signal
APUE 第三版 習題 10.5
truct spa ive ast discuss bsp timeout 問題 pla 這是書本上的答案: See ‘‘Implementing Software Timers’’ by Don Libes (C Users Journal, vol. 8, no. 11
1047 - C語言程式設計教程(第三版)課後習題10.5
1047 - C語言程式設計教程(第三版)課後習題10.5 時間限制:1秒 記憶體限制:128兆 題目描述 有n人圍成一圈,順序排號。從第1個人開始報數(從1到3報數),凡報到3的人退出圈子,問最後留下的是原來的第幾號的那位。 輸入 初始人數n 輸出 最後一人的初始編號 樣例輸入
1098: C語言程式設計教程(第三版)課後習題10.5---有n人圍成一圈,順序排號。從第1個人開始報數(從1到3報數),凡報到3的人退出圈子,問最後留下的是原來的第幾號的那位。
題目描述 有n人圍成一圈,順序排號。從第1個人開始報數(從1到3報數),凡報到3的人退出圈子,問最後留下的是原來的第幾號的那位。 輸入 初始人數n 輸出 最後一人的初始編號 樣例輸入 3 樣例輸出 2 提示 來源 思路點撥:定義一個數組,陣列下標表示人的編號,若數組裡面的
APUE習題10.6(父子程序同步)
編寫一段程式測試圖10_24中父子程序的同步函式,要求程序建立一個檔案並向檔案寫一個整數0,然後程序呼叫fork,接著父子程序交替增加檔案中的計數器值,每次計數器值增加1,列印是哪一個程序進行來該增加1操作 沒有完全按照題目要求做,直接fork之後01234這樣列印的
習題 7.5 有10個學生,每個學生的資料包括學號、姓名、3門課的成績,從鍵盤輸入10個學生資料,要求打印出3門課的總平均成績,以及最高分的學生的資料。
C++程式設計(第三版)譚浩強 習題7.5 個人設計 習題 7.5 有10個學生,每個學生的資料包括學號、姓名、3門課的成績,從鍵盤輸入10個學生資料,要求打印出3門課的總平均成績,以及最高分的學生的
Centos_6.5之Mysql數據庫
服務器 dns服務器 centos6.5 linux mysql 數據庫 1、安裝Mysql數據庫 yum install mysql mysql-server mysql-devel -y 2、啟動Mysql服務 service mysqld start3、設置My
delphi 7 下安裝 indy 10.5.8 教程
沒有 tar png variables 技術分享 移動 二次 rar use 曉不得2013 Delphi XE8 的實際應用。服務對象:非程序員,但期望用delphi提升工作技能。Delphi群:59129236 delphi 7 下安裝
10.5-全棧Java筆記:常見流詳解(三)
java上節我們講到「Java中常用流:緩沖流」,本節我們學習數據流和對象流~ 數據流數據流將“基本數據類型變量”作為數據源,從而允許程序以與機器無關方式從底層輸入輸出流中操作java基本數據類型。 DataInputStream和DataOutputStream提供了可以存取與機器無關的所有Java基礎類
紫書 習題2-5 分數化小數
logs i++ break %d pri max double code bre 1 #include<stdio.h> //基礎版 2 #define MAX 110 3 4 int main(void) 5 { 6 in
IntelliJ IDEA 10.5.1 引用外部Jar包
jar tac att ide dea 引用 int structure nbsp 具體步驟: File -> Project Structure (ctrl + shift + alt + s ) -> Module -> Dependencies -&
2014-10-5 NOIP模擬賽
str 隨機 一個人 保留 有根樹 tree noip 否則 數據規模 祖孫詢問 (tree.pas/c/cpp) 【問題描述】 已知一棵n個節點的有根樹。有m個詢問。每個詢問給出了一對節點的編號x和y,詢問x與y的祖孫關系。 【輸入格式】 輸入第
C/C++算法競賽入門經典Page16 習題1-5 打折
span 博客 保留 double int 保留兩位小數 c++ 小數 pan 題目:一件衣服 95元,若消費滿300元,可打八五折。輸入購買衣服件數,輸出需要支付的金額(單位元),保留兩位小數. 通過分支結構可以判斷是否要打八五折. (1)聲明衣服件數a,需要支付的金額b
Spark Structured Streaming框架(5)之進程管理
ntp 框架 manager lis ive term red ogr pan Structured Streaming提供一些API來管理Streaming對象。用戶可以通過這些API來手動管理已經啟動的Streaming,保證在系統中的Streaming有序執行。
ArcGIS Enterprise 10.5.1 靜默安裝部署記錄(Centos 7.2 minimal版)- 2、安裝Portal for ArcGIS
-a 切換 https stop user 安裝 執行 limits 方式 安裝Portal for ArcGIS 解壓portal安裝包,tar -xzvf Portal_for_ArcGIS_Linux_1051_156440.tar.gz 切換到arcgis賬戶靜
ArcGIS Enterprise 10.5.1 靜默安裝部署記錄(Centos 7.2 minimal版)- 3、安裝 ArcGIS for Server
切換 驗證 裝包 start dap sof 訪問權限 tar 服務 安裝ArcGIS for Server 解壓server安裝包,tar -xzvf ArcGIS_Server_Linux_1051_156429.tar.gz 切換到arcgis賬戶靜默安裝serv
ArcGIS Enterprise 10.5.1 靜默安裝部署記錄(Centos 7.2 minimal版)- 1、安裝前準備
計算機 boot thread connect conf 1.8 div 導入 top 安裝前準備 上傳文件到服務器,x-ftp xshell登陸Centos 檢查機器名 修改機器名為:portal.cloud.local 方法一:零時設置,重啟後失效,
2017-09-10-構建之法:現代軟件工程-閱讀筆記
參數 驗證 時間 第二章 軟件企業 功能 模塊 復雜 1.3 第一章 軟件= 程序+軟件工程 程序= 數據結構+算法 軟件企業 = 軟件+商業模式 軟件的特殊性:復雜性、不可見性、易變性、服從性、非連續性。 第二章 2.1單元測試: 2.1.1用VSTS寫單元測試 2.1
0.1 使用w查看系統負載 - 10.2 vmstat命令 - 10.3 top命令 - 10.4 sar命令 - 10.5 nload命令
使用 查看 系統負載 - 10.1 使用w查看系統負載 - 10.2 vmstat命令 - 10.3 top命令 - 10.4 sar命令 - 10.5 nload命令 # 10.1 使用w查看系統負載 ![mark](http://oqxf7c508.bkt.clouddn.com/blo
10.按鍵之互斥、阻塞機制
inter lee 多個進程 span 滿足 -1 類型 執行過程 mutex 本節目標: 學習原子操作和互斥信號量,實現互斥機制,同一時刻只能一個應用程序使用驅動程序 學習阻塞和非阻塞操作 當設備被一個程序打開時,存在被另一個程序打開的可能,如果兩個或多個程序同時