API 介绍:
# fd 相关
int uloop_fd_add(struct uloop_fd *sock, unsigned int flags);
int uloop_fd_delete(struct uloop_fd *sock);
# 定时器相关
int uloop_timeout_add(struct uloop_timeout *timeout);
int uloop_timeout_set(struct uloop_timeout *timeout, int msecs);
int uloop_timeout_cancel(struct uloop_timeout *timeout);
int uloop_timeout_remaining(struct uloop_timeout *timeout) __attribute__((deprecated("use uloop_timeout_remaining64")));
int64_t uloop_timeout_remaining64(struct uloop_timeout *timeout);
# 进程相关
int uloop_process_add(struct uloop_process *p);
int uloop_process_delete(struct uloop_process *p);
# 控制uloop循环
bool uloop_cancelling(void);
static inline void uloop_end(void)
{
uloop_cancelled = true;
}
int uloop_init(void);
int uloop_run_timeout(int timeout);
static inline int uloop_run(void)
{
return uloop_run_timeout(-1);
}
void uloop_done(void);
DEMO
01_hello.c
#include <stdio.h>
#include <libubox/uloop.h>
int main()
{
uloop_init();
printf("hello world\n");
uloop_run();
uloop_done();
return 0;
}
现象:
root@DataJar-0C7D:~# ./01_hello
hello world
02_timer.c
#include <stdio.h>
#include <string.h>
#include <libubox/uloop.h>
// timeout 必须是全局的,或者静态的
// 一次性定时器
static struct uloop_timeout once_timer;
// 永久性定时器
static struct uloop_timeout forever_timer;
static struct uloop_timeout limit_cnt_timer;
static int cnt = 10;
static void once_timer_callback(struct uloop_timeout *timeout)
{
printf("once_timer_callback\n");
}
static void forever_timer_callback(struct uloop_timeout *timeout)
{
printf("forever_timer_callback\n");
uloop_timeout_set(timeout, 1000);
}
static void forever2_timer_callback(struct uloop_timeout *timeout)
{
static struct uloop_timeout forever_timer2 = {
.cb = forever2_timer_callback
};
printf("forever2_timer_callback\n");
uloop_timeout_set(&forever_timer2, 1000);
}
static void limit_cnt_timer_callback(struct uloop_timeout *timeout)
{
printf("limit_cnt_timer_callback: %d\n", cnt);
if (cnt > 0) {
uloop_timeout_set(&limit_cnt_timer, 1000);
cnt--;
}
}
static void example1()
{
memset(&once_timer, 0, sizeof(struct uloop_timeout));
once_timer.cb = once_timer_callback;
uloop_timeout_set(&once_timer, 1000);
}
static void example2()
{
memset(&forever_timer, 0, sizeof(struct uloop_timeout));
forever_timer.cb = forever_timer_callback;
uloop_timeout_set(&forever_timer, 1000);
}
static void example3()
{
forever2_timer_callback(NULL);
}
static void example4()
{
memset(&limit_cnt_timer, 0, sizeof(struct uloop_timeout));
limit_cnt_timer.cb = limit_cnt_timer_callback;
uloop_timeout_set(&limit_cnt_timer, 1000);
}
int main(int argc, char **argv)
{
uloop_init();
if (argc > 1) {
if (strcmp(argv[1], "1") == 0) {
example1();
} else if (strcmp(argv[1], "2") == 0) {
example2();
} else if (strcmp(argv[1], "3") == 0) {
example3();
} else if (strcmp(argv[1], "4") == 0) {
example4();
}
} else {
example1();
}
uloop_run();
uloop_done();
return 0;
}
现象:
root@DataJar-0C7D:~# ./02_timer 1
once_timer_callback
root@DataJar-0C7D:~# ./02_timer 2
forever_timer_callback
forever_timer_callback
forever_timer_callback
root@DataJar-0C7D:~# ./02_timer 3
forever2_timer_callback
forever2_timer_callback
forever2_timer_callback
root@DataJar-0C7D:~# ./02_timer 4
limit_cnt_timer_callback: 10
limit_cnt_timer_callback: 9
limit_cnt_timer_callback: 8
limit_cnt_timer_callback: 7
limit_cnt_timer_callback: 6
limit_cnt_timer_callback: 5
limit_cnt_timer_callback: 4
limit_cnt_timer_callback: 3
limit_cnt_timer_callback: 2
limit_cnt_timer_callback: 1
limit_cnt_timer_callback: 0
03_fd.c
#include <stdio.h>
#include <libubox/uloop.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
static struct uloop_fd sock;
void sock_read_handler(struct uloop_fd *u, unsigned int events)
{
printf("sock_read_handler\n");
}
void example1()
{
memset(&sock, 0, sizeof(struct uloop_fd));
// 读取 /proc/kmsg
int fd = open("/proc/kmsg", S_IREAD);
if (fd < 0) {
perror("open");
return;
}
sock.fd = fd;
sock.cb = sock_read_handler;
uloop_fd_add(&sock, ULOOP_READ);
}
int main()
{
uloop_init();
example1();
uloop_run();
uloop_done();
return 0;
}
现象:
root@DataJar-0C7D:~# echo 111 > /dev/kmsg
[ 4531.381035] 111
root@DataJar-0C7D:~# sock_read_handler
sock_read_handler
sock_read_handler
sock_read_handler
sock_read_handler
root@DataJar-0C7D:~# echo 111 > /dev/kmsg
[ 4535.670722] 111
root@DataJar-0C7D:~# sock_read_handler
04_process.c
#include <stdio.h>
#include <libubox/uloop.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
static struct uloop_process proc;
void process_cb(struct uloop_process *c, int ret)
{
// 判断是否是通过exit退出,而不是信号
if (WIFEXITED(ret)) {
printf("child process exit with: %d\n", WEXITSTATUS(ret));
}
}
int main()
{
uloop_init();
memset(&proc, 0, sizeof(struct uloop_process));
pid_t pid = fork();
if (pid == 0) {
// 返回127退出
exit(127);
} else {
proc.pid = pid;
proc.cb = process_cb;
uloop_process_add(&proc);
}
uloop_run();
uloop_done();
return 0;
}
现象:
root@DataJar-0C7D:~# ./04_process
child process exit with: 127
注意点:
-
模板:
uloop_init(); xxxx uloop_run(); // 阻塞 uloop_free();
-
uloop 监听文件描述符时,flags 常用有两个取值:ULOOP_READ,ULOOP_WRITE
-
uloop_timeout_add 与 uloop_timeout_set 功能类似,使用需确保 uloop_timeout 提前设置了超时时间
-
不支持多线程 uloop,因为 uloop 使用了全局变量来共享数据