yloop
Yloop概要
Yloop 是AliOS Things的异步事件框架。Yloop借鉴了,libuv及嵌入式业界常见的event loop,综合考虑使用复杂性,性能,及footprint,实现了一个适合于MCU的事件调度机制。我们移植了相关的插件。其主要优势是所有的处理都是在主任务中执行的,不需要额外的创建任务,从而节省内存使用。同时,由于所有处理都是在主任务进行,不需要复杂的互斥操作。
Yloop上下文
每个Yloop实例(aos_loop_t)与特定的任务上下文绑定,AliOS Things的程序入口application_start 所在的上下文与系统的主Yloop实例绑定,该上下文也称为主任务。主任务以外的任务也可以创建自己的Yloop实例。
Yloop调度
Yloop实现了对IO,timer,callback,event的统一调度管理:
IO
:最常见的是Socket,也可以是AliOS Things的vfs管理的设备timer
:即常见的定时器callback
:特定的执行函数event
:包括系统事件,用户自定义事件 当调用aos_loop_run后,当前任务将会等待上述的各类事件发生。
Yloop实现原理
Yloop利用协议栈的select接口实现了对IO及timer的调度。AliOS Things自带的协议栈又暴露一个特殊的eventfd接口,Yloop利用此接口把VFS的设备文件,和eventfd关联起来,实现了对整个系统的事件的统一调度。
主要api介绍
- 注册事件监听函数
/**
* Register system event filter callback.
*
@param[in] type event type interested.
* @param[in] cb system event callback.
* @param[in] priv private data past to cb.
*
* @return the operation status, 0 is OK, others is error.
*/
int aos_register_event_filter(uint16_t type, aos_event_cb cb, void *priv);
/**
* Unregister native event callback.
*
* @param[in] type event type interested.
* @param[in] cb system event callback.
* @param[in] priv private data past to cb.
*
* @return the operation status, 0 is OK, others is error.
*/
int aos_unregister_event_filter(uint16_t type, aos_event_cb cb, void *priv);
- 发布一个 event
/**
* Post local event.
*
* @param[in] type event type.
* @param[in] code event code.
* @param[in] value event value.
*
* @return the operation status, 0 is OK,others is error.
*/
int aos_post_event(uint16_t type, uint16_t code, unsigned long value);
- 注册和取消一个 poll event
/**
* Register a poll event in main loop.
*
* @param[in] fd poll fd.
* @param[in] action action to be executed.
* @param[in] param private data past to action.
*
* @return the operation status, 0 is OK,others is error.
*/
int aos_poll_read_fd(int fd, aos_poll_call_t action, void *param);
/**
* Cancel a poll event to be executed in main loop.
*
* @param[in] fd poll fd.
* @param[in] action action to be executed.
* @param[in] param private data past to action.
*/
void aos_cancel_poll_read_fd(int fd, aos_poll_call_t action, void *param);
- 发布和取消一个延迟执行的 action
/**static void adc_cb_read(int fd, void *param)
{
aos_post_event(EV_ADCKEY, CODE_ADCKEY_INT_TRIGGER, fd);
}
* Post a delayed action to be executed in main loop.
*
* @param[in] ms milliseconds to wait.
* @param[in] action action to be executed.
* @param[in] arg private data past to action.
*
* @return the operation status, 0 is OK,others is error.
*/
int aos_post_delayed_action(int ms, aos_call_t action, void *arg);
/**
* Cancel a delayed action to be executed in main loop.
*
* @param[in] ms milliseconds to wait, -1 means don't care.
* @param[in] action action to be executed.
* @param[in] arg private data past to action.
*/
void aos_cancel_delayed_action(int ms, aos_call_t action, void *arg);
- 安排一次回调
/**
* Schedule a callback in next event loop.
* Unlike aos_post_delayed_action,
* this function can be called from non-aos-main-loop context.
* @param[in] action action to be executed.
* @param[in] arg private data past to action.
*
* @return the operation status, <0 is error,others is OK.
*/
int aos_schedule_call(aos_call_t action, void *arg);
示例代码
这里会介绍事件注册、通知、回调、取消流程、poll事件的注册取消、延迟执行一个actio)以及安排一次回调的使用方法
事件注册、通知、回调、取消流程
aos_register_event_filter(EV_WIFI, event_cb_wifi_event, NULL);
用户首先调用aos_register_event_filter
注册事件监听函数,例如首先显注册一个EV_WIFI
事件的监听函数event_cb_wifi_event
aos_post_event(EV_WIFI, CODE_WIFI_ON_INIT_DONE, 0);
当有任务调用aos_post_event
接口,发布CODE_WIFI_ON_INIT_DONE
事件之后
static void event_cb_wifi_event(input_event_t *event, void *private_data)
{
switch (
case CODE_WIFI_ON_INIT_DONE:
{
printf("[APP] [EVT] CODE_WIFI_ON_INIT_DONE %lld\r\n", aos_now_ms());
}
break;
case CODE_WIFI_ON_PRE_GOT_IP:
{
printf("[APP] [EVT] connected %lld\r\n", aos_now_ms());
}
break;
case CODE_WIFI_ON_GOT_IP:
{
printf("[APP] [EVT] GOT IP %lld\r\n", aos_now_ms());
}
break;
default:
{
/*nothing*/
}
}
}
event_cb_wifi_event
会被调用,并进入caseCODE_WIFI_ON_INIT_DONE
分支
aos_unregister_event_filter(EV_WIFI, event_cb_wifi_event, NULL);
如果用户不需要事件的监听,用户可以主动调用aos_unregister_event_filter
取消监听
poll事件的注册取消
/*uart*/
fd_console = aos_open("/dev/ttyS0", 0);
if (fd_console >= 0) {
printf("Init CLI with event Driven\r\n");
aos_cli_init(0);
aos_poll_read_fd(fd_console, aos_cli_event_cb_read_get(), (void*)0x12345678);
_cli_init();
}
这里以 uart0
为例,用户首先注册一个aos_poll_read_fd
poll事件
aos_cancel_poll_read_fd(fd_console, action, (void*)0x12345678);
如果用户不需要事件的poll,用户可以调用aos_cancel_poll_read_fd
取消poll
延迟执行一个action
aos_post_delayed_action(1000, app_delayed_action_print, NULL);
用户可以调用aos_post_delayed_action
做一个延迟1s
执行的事件
static void app_delayed_action_print(void *arg)
{
printf("test.\r\n");
}
那过1s
之后会主动调用app_delayed_action_print
函数
aos_cancel_delayed_action(1000, app_delayed_action_print, NULL);
当用户想直接取消一个延迟动作可以调用aos_cancel_delayed_action
,其第一个ms
参数,
当ms == -1
时,表示无需关心时间是否一致
安排一次回调
aos_schedule_call(app_action_print, NULL);
用户主动调用aos_schedule_call
函数
static app_action_print(void *arg)
{
printf("test\r\n");
}
那么会在下一次循环中主动调用app_action_print
函数
注意事项
Yloop的API(include/aos/yloop.h)除了下述API,都必须在Yloop实例所绑定的任务的上下文执行:
- aos_schedule_call
- aos_loop_schedule_call
- aos_loop_schedule_work
- aos_cancel_work
- aos_post_event