您的位置:首页 > 运维架构

libubox组件(3)——uloop

2016-07-06 16:27 666 查看
一:uloop概述

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();


}






三:uloop文件描述符触发事件的监控
#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]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: