libubox组件(3)——uloop
2016-07-06 16:27
666 查看
一:uloop概述
uloop有三个功能:文件描述符触发事件的监控,timeout定时器处理,当前进程的子进程的维护
二:uloop的整体框架
三:uloop文件描述符触发事件的监控
[code]#defineULOOP_WRITE(1<<1)
[/code]
例子:
[code]#include<stdlib.h>
[/code]
四:timeout定时器处理
建立一条链表管理所有的timeout节点
[code]{
五:当前进程的子进程的维护建立一条process链表管理所有的进程id
[/code]
uloop有三个功能:文件描述符触发事件的监控,timeout定时器处理,当前进程的子进程的维护
二:uloop的整体框架
/**
*初始化事件循环
*主要工作是poll_fd=epoll_create(32);/*创建一个epoll的文件描述符监控句柄。最多监控32个文件描述符
**/
intuloop_init(void)
{
if(poll_fd>=0)
return0;
poll_fd=epoll_create(32);/*创建一个epoll的句柄。最多监控32个文件描述符*/
if(poll_fd<0)
return-1;
fcntl(poll_fd,F_SETFD,fcntl(poll_fd,F_GETFD)|FD_CLOEXEC);/*fd_cloexecs*/
return0;
}
/**
*事件循环主处理入口
*1.当某一个进程第一次调用uloop_run时,注册sigchld和sigint信号
*2.循环获取当前时间,把超时的timeout处理掉,有一条timeout链表在维护
*3.循环检测是否收到一个sigchld信号,如果收到,删除对应的子进程,有一条process子进程链表在维护
*4.循环调用epoll_wait监相应的触发事件文件描述符fd
**/
voiduloop_run(void)
{
staticintrecursive_calls=0;/*staticvalue*/
structtimevaltv;
/*
*Handlersareonlyupdatedforthefirstcalltouloop_run()(andrestored
*whenthiscallisdone).
*/
if(!recursive_calls++)/*第一次运行uloop_run时调用,注册信号处理函数*/
uloop_setup_signals(true);
uloop_cancelled=false;
while(!uloop_cancelled)
{
uloop_gettime(&tv);/*获取当前时间*/
uloop_process_timeouts(&tv);/*把超时的timeout清理掉*/
if(uloop_cancelled)
break;
if(do_sigchld)/*收到一个sigchld的信号*/
uloop_handle_processes();/*销毁该进程的uloop_process*/
uloop_gettime(&tv);
uloop_run_events(uloop_get_next_timeout(&tv));/*处理相应的触发事件fd*/
}
if(!--recursive_calls)
uloop_setup_signals(false);
}
/**
*销毁事件循环
*关闭epoll描述符
*销毁子进程链表
*销毁timeout链表
**/
voiduloop_done(void)
{
if(poll_fd<0)
return;
close(poll_fd);
poll_fd=-1;
uloop_clear_timeouts();
uloop_clear_processes();
}
#defineULOOP_READ(1<<0)
[code]#defineULOOP_WRITE(1<<1)
#defineULOOP_EDGE_TRIGGER(1<<2)
#defineULOOP_BLOCKING(1<<3)
#defineULOOP_EVENT_MASK(ULOOP_READ|ULOOP_WRITE)
/*internalflags*/
#defineULOOP_EVENT_BUFFERED(1<<4)
#defineULOOP_ERROR_CB(1<<6)
structuloop_fd
{
uloop_fd_handlercb;/*文件描述符对应的处理函数*/
intfd;/*文件描述符*/
booleof;/*EOF*/
boolerror;/*出错*/
boolregistered;/*是否已经添加到epoll的监控队列*/
uint8_tflags;/*ULOOP_READ|ULOOP_WRITE|ULOOP_BLOCKING等*/
};
/**
*注册一个新描述符到事件处理循环
*/
intuloop_fd_add(structuloop_fd*sock,unsignedintflags)
/**
*从事件处理循环中销毁指定描述符
*/
intuloop_fd_delete(structuloop_fd*sock)
[/code]
#include<stdio.h>
[code]#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>/*SeeNOTES*/
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<libubox/usock.h>
#include<libubox/uloop.h>
staticvoidrecv_string(structuloop_fd*u,unsignedintevents)
{
charbuf[1024]={0};
if(events&ULOOP_READ){
if(recv(u->fd,buf,1024,0)>0){
printf("recv_buf:%s\n",buf);
send(u->fd,"helloworldfromserver",strlen("helloworldfromserver"),0);
}
}
}
staticvoidread_std(structuloop_fd*u,unsignedintevents)
{
charbuf[1024]={0};
if(events&ULOOP_READ){
if(read(u->fd,buf,1024)>0){
printf("read_std:%s\n",buf);
}
}
}
intmain()
{
structsockaddr_incli_addr;
socklen_tlen=sizeof(structsockaddr);
inttype=USOCK_TCP|USOCK_SERVER|USOCK_NOCLOEXEC|USOCK_IPV4ONLY;
constchar*host="CarRadio";
constchar*service="8000";
charrecv_buf[1024]={0};
intconnect_fd,u_fd=usock(type,host,service);
if(u_fd<0){
perror("usock");
return-1;
}
connect_fd=accept(u_fd,(structsockaddr*)(&cli_addr),&len);
if(connect_fd<0){
perror("accept");
return-1;
}
structuloop_fdfd[2]={
{
.cb=recv_string,
.fd=connect_fd,
.registered=false,
.flags=ULOOP_READ,
},
{
.cb=read_std,
.fd=STDIN_FILENO,
.registered=false,
.flags=ULOOP_READ,
}
};
uloop_init();
/*添加uloop_fd*/
uloop_fd_add(&fd[0],ULOOP_READ);
uloop_fd_add(&fd[1],ULOOP_READ);
uloop_run();
uloop_fd_delete(&fd[0]);
uloop_done();
return0;
}
[/code]
四:timeout定时器处理
建立一条链表管理所有的timeout节点
structuloop_timeout
[code]{
structlist_headlist;//链表节点
boolpending;//添加一个新的timeoutpending是true,false删除该节点timeout
uloop_timeout_handlercb;//超时处理函数
structtimevaltime;//超时时间
};
/**
*注册一个新定时器
*/
intuloop_timeout_add(structuloop_timeout*timeout);
/**
*设置定时器超时时间(毫秒),并添加
*/
intuloop_timeout_set(structuloop_timeout*timeout,intmsecs);
/**
*销毁指定定时器
*/
intuloop_timeout_cancel(structuloop_timeout*timeout);
/**
*获取定时器还剩多长时间超时
*/
intuloop_timeout_remaining(structuloop_timeout*timeout);
例子:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>/*SeeNOTES*/
#include<sys/socket.h>
#include<libubox/usock.h>
#include<libubox/uloop.h>
intg_fd=-1;
voidsend_sock(structuloop_timeout*t);
structuloop_timeouttm={
.cb=send_sock,
};
voidsend_sock(structuloop_timeout*t)
{
charbuf[1024]={0};
send(g_fd,"helloworldfromcilent",strlen("helloworldfromcilent"),0);
if(recv(g_fd,buf,1024,0)>0){
printf("\nrecv_buf:%s\n",buf);
}
/*添加uloop_timeout实现循环定时*/
uloop_timeout_set(&tm,5000);
}
intmain()
{
structsockaddrcli_addr;
socklen_tlen=sizeof(structsockaddr);
inttype=USOCK_TCP|USOCK_NOCLOEXEC|USOCK_IPV4ONLY;
constchar*host="CarRadio";
constchar*service="8000";
charrecv_buf[1024]={0};
g_fd=usock(type,host,service);/*createalinkersocket*/
if(g_fd<0){
perror("usock");
return-1;
}
uloop_init();
/*添加uloop_timeout*/
uloop_timeout_set(&tm,5000);
uloop_run();
uloop_done();
close(g_fd);
return0;
}
五:当前进程的子进程的维护建立一条process链表管理所有的进程id
structuloop_process{
structlist_headlist;
boolpending;
uloop_process_handlercb;/**文件描述符,调用者初始化*/
pid_tpid;/**文件描述符,调用者初始化*/
};
/*进程退出时回调函数*/
typedefvoid(*uloop_process_handler)(structuloop_process*c,intret);
/**
*注册新进程到事件处理循环
*/
intuloop_process_add(structuloop_process*p);
/**
*从事件处理循环中销毁指定进程
*/
intuloop_process_delete(structuloop_process*p);
例子:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>/*SeeNOTES*/
#include<unistd.h>
#include<libubox/uloop.h>
structuloop_process*u_process=NULL;
/*c:代表推出的进程,ret:代表推出的状态*/
voidprocess_exit(structuloop_process*c,intret)
{
printf("childprocessexitid[%d],status[%#x]\n",c->pid,ret);
free(c);
}
voidchild_process(intt)
{
printf("processpid:%disruning\n",getpid());
if(t>0)
sleep(t);
printf("processid[%d]willexit...\n",getpid());
exit(t);
}
intmain()
{
inti;
pid_tpid;
uloop_init();
for(i=0;i<10;i++){
usleep(500);
pid=fork();
if(pid==0){//子进程
child_process((i+1)*10);//子进程休眠(i+1)*10s
}
else{
u_process=
(structuloop_process*)malloc(sizeof(structuloop_process));
if(NULL==u_process){
perror("malloc");
exit(-1);
}
u_process->pid=pid;
u_process->cb=process_exit;
u_process->pending=false;
if(uloop_process_add(u_process)<0){
printf("uloop_process_addfailed...\n");
}
printf("successcreateprocesspid:%d\n",pid);
}
}
printf("uloop_runing....\n");
uloop_run();
uloop_done();
return0;
}
[/code]
相关文章推荐
- openstack----03_ 安装Keystone
- openstack快照
- openstack kilo 扩展nova api方法
- 让powershell同时只能运行一个脚本(进程互斥例子)
- linux常用端口
- openstack----02_准备工作
- OpenGL的glRotatef旋转变换函数详解
- Linux下的C语言开发(静态库和动态库)
- linux下如何查询哪个磁盘是SSD
- docker.dmg放在360云盘了,官网的太慢了
- Android官方MVP架构示例项目解析
- centOS7 无法ping
- Tomcat配置远程调试端口
- BOSS架构
- Linux内核Makefile分析
- Event Loop
- linux下打开、关闭tomcat,实时查看tomcat运行日志
- Aginx环境的搭建
- Linux内核makefile解析
- 从tomcat角度解读play源代码