sloop公共函数之添加信号,定时器及socket

Posted 会飞的小丑

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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_SOCKETSLOOP_TYPE_TIMEOUTSLOOP_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 }

综上:

  这就是这四种功能的实现思路及使用方式。

 

以上是关于sloop公共函数之添加信号,定时器及socket的主要内容,如果未能解决你的问题,请参考以下文章

多线程之(信号量,Event,定时器)

并发编程之多线程篇之四

PyQt5信号定时器及多线程

信号量,Event,定时器

Linux(程序设计):61---定时机制之SIGALRM信号(附升序的定时器链表设计定时器链表处理非活动连接)

2-8 信号量 Event 定时器