sloop公共函数之添加信号,定时器及socket
1:添加信号
1.1 原型:sloop_handle sloop_register_signal(int sig, sloop_signal_handler handler, void * param)
1 /* register a signal handler */ 2 sloop_handle sloop_register_signal(int sig, sloop_signal_handler handler, void * param) 3 { 4 struct sloop_signal * entry; 5 struct sigaction sa; 6 7 sa.sa_handler = sloop_signals_handler; 8 sigemptyset(&sa.sa_mask); 9 sa.sa_flags = SA_RESTART; 10 11 /* allocate a new structure sloop_signal */ 12 entry = get_signal(); 13 if (entry == NULL) 14 return NULL; 15 16 /* setup structure and insert into list. */ 17 entry->sig = sig; 18 entry->param = param; 19 entry->handler = handler; 20 dlist_add(&entry->list, &sloop.signals); 21 SLOOPDBG(d_dbg("sloop: sloop_register_signal(%d)\n", sig)); 22 if (sigaction(sig, &sa, NULL) < 0) { 23 dlist_del(&entry->list); 24 free_signal(entry); 25 d_error("sigaction %d error %s\n", sig, strerror(errno)); 26 return NULL; 27 } 28 29 return entry; 30 }
这个函数提供给使用sloop模块的第三方,只需要传入要监听的信号、信号处理函数、参数,就可以将此信号登记到sloop_data结构体中的struct dlist_head signals链表中,在sloop_run函数中进行监听。get_signal函数是从初始化时的struct dlist_head free_signals链表中取出一个可用的节点挂在struct dlist_head signals链表中。具体实现如下:
1 /* get signal from pool */ 2 static struct sloop_signal * get_signal(void) 3 { 4 struct dlist_head * entry; 5 struct sloop_signal * target; 6 7 if (dlist_empty(&sloop.free_signals)) { 8 d_error("sloop: no sloop_signal available !!!\n"); 9 return NULL; 10 } 11 entry = sloop.free_signals.next; 12 dlist_del(entry); 13 target = dlist_entry(entry, struct sloop_signal, list); 14 target->flags = SLOOP_INUSED | SLOOP_TYPE_SIGNAL; 15 return target; 16 }
flags参数主要是为了标识此节点的类型,有三种类型,SLOOP_TYPE_SOCKET、SLOOP_TYPE_TIMEOUT、SLOOP_TYPE_SIGNAL。
1.2 一般使用方法
sloop_register_signal(SIGTERM, sig_term, NULL);登记SIGTERM信号的处理函数是sig_term,没有要传递的参数。
2:添加定时器
2.1 原型:sloop_handle sloop_register_timeout(unsigned int secs, unsigned int usecs, sloop_timeout_handler handler, void * param)
同添加信号的实现思路是一样的,需要传递的参数是定时器的秒和微妙参数。
1 /* register a timer */ 2 sloop_handle sloop_register_timeout(unsigned int secs, unsigned int usecs, sloop_timeout_handler handler, void * param) 3 { 4 struct sloop_timeout * timeout, * tmp; 5 struct dlist_head * entry; 6 7 /* allocate a new struct sloop_timeout. */ 8 timeout = get_timeout(); 9 if (timeout == NULL) return NULL; 10 11 /* get current time */ 12 gettimeofday(&timeout->time, NULL); 13 timeout->time.tv_sec += secs; 14 timeout->time.tv_usec += usecs; 15 16 while (timeout->time.tv_usec >= 1000000) { 17 timeout->time.tv_sec++; 18 timeout->time.tv_usec -= 1000000; 19 } 20 timeout->handler = handler; 21 timeout->param = param; 22 INIT_DLIST_HEAD(&timeout->list); 23 24 /* put into the list */ 25 if (dlist_empty(&sloop.timeout)) { 26 dlist_add(&timeout->list, &sloop.timeout); 27 SLOOPDBG(d_dbg("sloop: timeout(0x%x) added !\n", timeout)); 28 return timeout; 29 } 30 31 entry = sloop.timeout.next; 32 while (entry != &sloop.timeout) { 33 tmp = dlist_entry(entry, struct sloop_timeout, list); 34 if (timercmp(&timeout->time, &tmp->time, < )) break; 35 entry = entry->next; 36 } 37 dlist_add_tail(&timeout->list, entry); 38 SLOOPDBG(d_dbg("sloop: timeout(0x%x) added !!\n", timeout)); 39 return timeout; 40 }
2.2 一般使用方法
sloop_register_timeout(1, 0, wan_handler, param);在登记之后的1秒执行函数wan_handler。
3:添加套接字
3.1 原型:套接字分为监听可读或可写两种
/* register a read socket */ sloop_handle sloop_register_read_sock(int sock, sloop_socket_handler handler, void * param) { return register_socket(sock, handler, param, &sloop.readers); } /* register a write socket */ sloop_handle sloop_register_write_sock(int sock, sloop_socket_handler handler, void * param) { return register_socket(sock, handler, param, &sloop.writers); }
分别挂载到sloop.readers和sloop.writers链表上。
1 static struct sloop_socket * register_socket(int sock, 2 sloop_socket_handler handler, void * param, struct dlist_head * head) 3 { 4 struct sloop_socket * entry; 5 6 /* allocate a new structure sloop_socket */ 7 entry = get_socket(); 8 if (entry == NULL) return NULL; 9 10 /* setup structure and insert into list. */ 11 entry->sock = sock; 12 entry->param = param; 13 entry->handler = handler; 14 dlist_add(&entry->list, head); 15 SLOOPDBG(d_dbg("sloop: new socket : 0x%x (fd=%d)\n", (unsigned int)entry, entry->sock)); 16 return entry; 17 }
get_socket实现:
1 /* get socket from pool */ 2 static struct sloop_socket * get_socket(void) 3 { 4 struct dlist_head * entry; 5 struct sloop_socket * target; 6 7 if (dlist_empty(&sloop.free_sockets)) { 8 d_error("sloop: no sloop_socket available !!!\n"); 9 return NULL; 10 } 11 entry = sloop.free_sockets.next; 12 SLOOPDBG(daig_printf("%s: get socket sd=[%x],\n", __FILE__, entry)); 13 dlist_del(entry); 14 target = dlist_entry(entry, struct sloop_socket, list); 15 target->flags = SLOOP_INUSED | SLOOP_TYPE_SOCKET; 16 return target; 17 }
综上:
这就是这四种功能的实现思路及使用方式。