参考: https://www.cnblogs.com/muyi23333/articles/13523251.html
https://blog.51cto.com/u_15352922/3745226
https://blog.csdn.net/weixin_34145418/article/details/116968058
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <pthread.h>
6 #include <signal.h>
7 #include <time.h>
8 #include <sys/timeb.h>
9 #include <sys/times.h>
10
11
12
13 #define xxxx_print_ln(log_level, fmt, ...) do { printf("(%s|%d)" fmt "\r\n", __func__, __LINE__, ##__VA_ARGS__); fflush(stdout);} while(0)
14
15 typedef void (*F_TIMER_CB)(void *);
16
17
18 void xxxx_timer_delete(void *timerid);
19
20 typedef struct _T_TIMER_ARG
21 {
22 F_TIMER_CB timer_cb;
23 void *arg;
24 void *timerid;
25 int is_onlyOnce;
26 }T_TIMER_ARG;
27
28
29 /*****************************************************************
30
31 定时器接口(第0套): 启动定时器
32
33 参数 : timerid, 定时器句柄
34 deleay_ms, 触发时间(ms)
35 interval_ms, 周期触发间隔(ms)
36
37 return : 非NULL, 成功, 返回定时器句柄
38 NULL, 失败
39
40 *****************************************************************/
41 static int xxxx_timer_start(void *timerid, size_t deleay_ms, size_t interval_ms)
42 {
43 struct itimerspec it;
44
45 it.it_value.tv_sec = deleay_ms / 1000;
46 it.it_value.tv_nsec = (deleay_ms % 1000) * 1000 * 1000;
47
48 it.it_interval.tv_sec = interval_ms / 1000;
49 it.it_interval.tv_nsec = (interval_ms % 1000) * 1000 * 1000;
50
51 if (0 != timer_settime((timer_t)timerid, 0, &it, NULL)) {
52 return -1;
53 }
54
55 return 0;
56 }
57
58 static void xxxx_timer_thread(union sigval sig_v)
59 {
60 T_TIMER_ARG *timer_arg = NULL;
61
62 timer_arg = (T_TIMER_ARG *)sig_v.sival_ptr;
63
64 if (NULL == timer_arg) {
65 xxxx_print_ln(xxxx_ERROR, "timer_arg is no-valid");
66 return ;
67 }
68
69 if (NULL != timer_arg->timer_cb) {
70 timer_arg->timer_cb(timer_arg->arg);
71 }
72
73 if (timer_arg->is_onlyOnce) {
74 xxxx_timer_delete(timer_arg->timerid);
75 timer_arg->timerid = 0;
76 }
77 }
78
79 /*****************************************************************
80
81 定时器接口(第0套): 创建定时器
82
83 参数 :
84 is_onlyOnce, 1仅一次(结束后句柄自动被删除), 0周期性定时器
85 timer_cb, 回调函数
86 arg, 回调函数的参数
87
88 return : 非NULL, 成功, 返回定时器句柄
89 NULL, 失败
90
91 *****************************************************************/
92 static void *xxxx_timer_create(int is_onlyOnce, F_TIMER_CB timer_cb, void *arg)
93 {
94 timer_t timerid;
95 struct sigevent evp;
96 T_TIMER_ARG *timer_arg = NULL;
97
98 /*
99 参考: https://www.cnblogs.com/muyi23333/articles/13523251.html
100 https://blog.51cto.com/u_15352922/3745226
101 https://blog.csdn.net/weixin_34145418/article/details/116968058
102 */
103
104 timer_arg = (T_TIMER_ARG *)calloc(1, sizeof(T_TIMER_ARG));
105 if (NULL == timer_arg) {
106 xxxx_print_ln(xxxx_ERROR, "malloc failed(size=%u)", sizeof(T_TIMER_ARG));
107 return NULL;
108 }
109
110 timer_arg->arg = arg;
111 timer_arg->timer_cb = timer_cb;
112 timer_arg->is_onlyOnce = (is_onlyOnce) ? 1 : 0;
113
114 memset(&evp, 0, sizeof(struct sigevent));
115
116 evp.sigev_value.sival_ptr = (void *)timer_arg;
117 evp.sigev_notify = SIGEV_THREAD; // 线程通知的方式,派驻新线程
118 evp.sigev_notify_function = xxxx_timer_thread;
119
120 if (0 != timer_create(CLOCK_REALTIME, &evp, &timerid)) {
121 return NULL;
122 }
123 timer_arg->timerid = (void *)timerid;
124
125 return (void *)timerid;
126 }
127
128 /*****************************************************************
129
130 定时器接口(第0套): 删除定时器
131
132 参数 : timerid, 定时器句柄
133 deleay_ms, 触发时间(ms)
134 interval_ms, 周期触发间隔(ms)
135
136 return : 非NULL, 成功, 返回定时器句柄
137 NULL, 失败
138
139 *****************************************************************/
140 void xxxx_timer_delete(void *timerid)
141 {
142 if (NULL == timerid) {
143 return;
144 }
145
146 // 同一个timerid, 多次重复删除, 不会引起崩溃
147 timer_delete((timer_t)timerid);
148
149 xxxx_print_ln(xxxx_INFO, "timer deleted (timerid=%x)", timerid);
150
151 return ;
152 }
153
154 /*****************************************************************
155
156 定时器接口(第一套): 创建一次性定时器
157
158 参数 :
159 deleay_ms, 触发时间(ms)
160 timer_cb, 回调函数
161 arg, 回调函数的参数
162
163 return : 非NULL, 成功, 返回定时器句柄
164 NULL, 失败
165
166 *****************************************************************/
167 void *xxxx_timer_once(size_t deleay_ms, F_TIMER_CB timer_cb, void *arg)
168 {
169 void *timerid = NULL;
170 int ret = 0;
171
172 timerid = xxxx_timer_create(1, timer_cb, arg);
173 if (NULL == timerid) {
174 return NULL;
175 }
176
177 ret = xxxx_timer_start(timerid, deleay_ms, 0);
178
179 return (0 == ret )? timerid : NULL;
180 }
181
182 /*****************************************************************
183
184 定时器接口(第二套): 创建重复性定时器
185
186 参数 :
187 deleay_ms, 触发时间(ms)
188 interval_ms, 周期触发间隔(ms)
189 timer_cb, 回调函数
190 arg, 回调函数的参数
191
192 return : 非NULL, 成功, 返回定时器句柄
193 NULL, 失败
194
195 *****************************************************************/
196 void *xxxx_timer_interval(size_t deleay_ms, size_t interval_ms, F_TIMER_CB timer_cb, void *arg)
197 {
198 void *timerid = NULL;
199 int ret = 0;
200
201 timerid = xxxx_timer_create(0, timer_cb, arg);
202 if (NULL == timerid) {
203 return NULL;
204 }
205
206 ret = xxxx_timer_start(timerid, deleay_ms, interval_ms);
207
208 return (0 == ret ) ? timerid : NULL;
209 }
/****************************************
返回当前时间字符串
格式为20211223_160548_054
参数 : 无
return : 非NULL, 当前时间字符串, 需要释放
****************************************/
char *xxxx_get_time_stamp(void)
{
char *time_stamp_out = NULL;
time_t ltime;
struct tm *today;
struct timeb timebuffer;
time( <ime );
today = localtime( <ime );
ftime( &timebuffer);
asprintf(&time_stamp_out, "%04d%02d%02d_%02d%02d%02d_%03d", 1900 + today->tm_year,
today->tm_mon + 1,
today->tm_mday,
today->tm_hour,
today->tm_min,
today->tm_sec,
timebuffer.millitm);
return time_stamp_out;
}
void t_cb(void *arg)
{
printf("%s\r\n", arg);
printf("%s\r\n", xxxx_get_time_stamp());
}
int main(int argc, char *argv)
{
void *h = NULL;
printf("%s\r\n", xxxx_get_time_stamp());
#if 0
h = xxxx_timer_once(2600, t_cb, "thanks!!!");
sleep(5);
xxxx_timer_delete(h);
sleep(5);
#else
h = xxxx_timer_interval(2897, 5897, t_cb, "thanks!!!");
sleep(30);
xxxx_timer_delete(h);
sleep(30);
#endif
return 0;
}
gcc my_timer.c my_timer_test.c -lrt -o a.out ; ./a.out