libubox组件(3)——uloop

一:uloop概述

  • uloop有三个功能: 文件描述符触发事件的监控,  timeout定时器处理, 当前进程的子进程的维护

二: uloop的整体框架

   1:  /**
   2:   * 初始化事件循环
   3:   *主要工作是poll_fd = epoll_create(32);/* 创建一个epoll的文件描述符监控句柄。最多监控32个文件描述符 
   4:   **/
   5:  int uloop_init(void)
   6:  {
   7:      if (poll_fd >= 0)
   8:          return 0;
   9:   
  10:      poll_fd = epoll_create(32);/* 创建一个epoll的句柄。最多监控32个文件描述符 */
  11:      if (poll_fd < 0)
  12:          return -1;
  13:   
  14:      fcntl(poll_fd, F_SETFD, fcntl(poll_fd, F_GETFD) | FD_CLOEXEC); /* fd_cloexecs */
  15:      return 0;
  16:  }
  17:   
  18:   
  19:  /**
  20:   * 事件循环主处理入口
  21:   *1.当某一个进程第一次调用uloop_run时,注册sigchld和sigint信号
  22:   *2.循环获取当前时间,把超时的timeout处理掉,有一条timeout链表在维护
  23:   *3.循环检测是否收到一个sigchld信号,如果收到,删除对应的子进程,有一条process子进程链表在维护
  24:   *4.循环调用epoll_wait 监相应的触发事件文件描述符fd 
  25:   **/
  26:  void uloop_run(void)
  27:  {
  28:      static int recursive_calls = 0; /* static value */
  29:      struct timeval tv;
  30:   
  31:      /*
  32:       * Handlers are only updated for the first call to uloop_run() (and restored
  33:       * when this call is done).
  34:       */
  35:      if (!recursive_calls++) /* 第一次运行uloop_run时调用, 注册信号处理函数 */
  36:          uloop_setup_signals(true);
  37:   
  38:      uloop_cancelled = false;
  39:      while(!uloop_cancelled)
  40:      {
  41:          uloop_gettime(&tv); /* 获取当前时间 */
  42:          uloop_process_timeouts(&tv); /* 把超时的timeout清理掉 */
  43:          if (uloop_cancelled)
  44:              break;
  45:   
  46:          if (do_sigchld) /*  收到一个sigchld的信号 */
  47:              uloop_handle_processes(); /* 销毁该进程的uloop_process */
  48:          uloop_gettime(&tv);
  49:          uloop_run_events(uloop_get_next_timeout(&tv));/* 处理相应的触发事件fd */
  50:      }
  51:   
  52:      if (!--recursive_calls)
  53:          uloop_setup_signals(false);
  54:  }
  55:   
  56:   
  57:  /**
  58:   * 销毁事件循环
  59:   * 关闭epoll描述符
  60:   * 销毁子进程链表
  61:   * 销毁timeout链表
  62:  **/
  63:  void uloop_done(void)
  64:  {
  65:      if (poll_fd < 0)
  66:          return;
  67:   
  68:      close(poll_fd);
  69:      poll_fd = -1;
  70:   
  71:      uloop_clear_timeouts();
  72:      uloop_clear_processes();
  73:  }
 
 
三:uloop文件描述符触发事件的监控
   1:  #define ULOOP_READ        (1 << 0)
   2:  #define ULOOP_WRITE        (1 << 1)
   3:  #define ULOOP_EDGE_TRIGGER    (1 << 2)
   4:  #define ULOOP_BLOCKING        (1 << 3)
   5:   
   6:  #define ULOOP_EVENT_MASK    (ULOOP_READ | ULOOP_WRITE)
   7:  /* internal flags */
   8:  #define ULOOP_EVENT_BUFFERED    (1 << 4)
   9:  #define ULOOP_ERROR_CB        (1 << 6)
  10:  struct uloop_fd
  11:  {
  12:      uloop_fd_handler cb; /* 文件描述符对应的处理函数 */
  13:      int fd;                         /*文件描述符*/
  14:      bool eof;                    /*EOF*/
  15:      bool error;                 /*出错*/
  16:      bool registered;        /*是否已经添加到epoll的监控队列*/
  17:      uint8_t flags;           /*ULOOP_READ | ULOOP_WRITE | ULOOP_BLOCKING等*/  
  18:  };
  19:   
  20:  /**
  21:   * 注册一个新描述符到事件处理循环
  22:   */
  23:  int uloop_fd_add(struct uloop_fd *sock, unsigned int flags)
  24:   
  25:  /** 
  26:   * 从事件处理循环中销毁指定描述符
  27:   */
  28:  int uloop_fd_delete(struct uloop_fd *sock)

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

例子:

   1:  #include <stdio.h>
   2:  #include <stdlib.h>
   3:  #include <string.h>
   4:  #include <unistd.h>
   5:  #include <sys/types.h>          /* See NOTES */
   6:  #include <sys/stat.h>
   7:  #include <fcntl.h>
   8:  #include <sys/socket.h>
   9:  #include <netinet/in.h>
  10:  #include <arpa/inet.h>
  11:  #include <libubox/usock.h>
  12:  #include <libubox/uloop.h> 
  13:  static void recv_string(struct uloop_fd *u, unsigned int events)
  14:  {
  15:      char buf[1024] = {0};
  16:      if (events & ULOOP_READ) {
  17:          if ( recv(u->fd, buf, 1024, 0) > 0) {
  18:              printf("recv_buf: %s\n", buf);
  19:              send(u->fd, "helloworld from server", strlen("helloworld from server"), 0);
  20:          }
  21:      }
  22:  }
  23:   
  24:  static void read_std(struct uloop_fd *u, unsigned int events)
  25:  {
  26:      char buf[1024] = {0};
  27:      if (events & ULOOP_READ) {
  28:          if ( read(u->fd, buf, 1024) > 0) {
  29:              printf("read_std: %s\n", buf);
  30:          }
  31:      }
  32:  }
  33:   
  34:  int main()
  35:  {
  36:      struct sockaddr_in cli_addr;
  37:      socklen_t len = sizeof(struct sockaddr);
  38:      int type = USOCK_TCP | USOCK_SERVER  | USOCK_NOCLOEXEC | USOCK_IPV4ONLY;
  39:      const char *host = "CarRadio";
  40:      const char *service = "8000";
  41:      char recv_buf[1024] = {0};
  42:      int connect_fd, u_fd = usock(type, host, service);    
  43:      if (u_fd < 0) {
  44:          perror("usock");
  45:          return -1;
  46:      }
  47:      
  48:      connect_fd = accept(u_fd, (struct sockaddr *)(&cli_addr), &len);
  49:      if (connect_fd < 0) {
  50:          perror("accept");
  51:          return -1;
  52:      }
  53:      struct uloop_fd fd[2] = {
  54:          {
  55:              .cb = recv_string,
  56:              .fd = connect_fd,
  57:              .registered = false,
  58:              .flags = ULOOP_READ,
  59:          },
  60:          {
  61:              .cb = read_std,
  62:              .fd = STDIN_FILENO,
  63:              .registered = false,
  64:              .flags = ULOOP_READ,
  65:          }
  66:      };
  67:      uloop_init();
  68:      /*添加uloop_fd*/
  69:      uloop_fd_add(&fd[0], ULOOP_READ);
  70:      uloop_fd_add(&fd[1], ULOOP_READ);
  71:      uloop_run();
  72:   
  73:      uloop_fd_delete(&fd[0]);
  74:      uloop_done();
  75:      
  76:      return 0;
  77:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

四:timeout定时器处理

建立一条链表管理所有的timeout节点

   1:  struct uloop_timeout
   2:  {
   3:      struct list_head list;  //链表节点
   4:      bool pending;           //添加一个新的timeout pending是true, false删除该节点timeout
   5:   
   6:      uloop_timeout_handler cb; //超时处理函数
   7:      struct timeval time;       //超时时间
   8:  };
   9:   
  10:  /**
  11:   * 注册一个新定时器
  12:   */
  13:  int uloop_timeout_add(struct uloop_timeout *timeout);
  14:   
  15:  /**
  16:   * 设置定时器超时时间(毫秒),并添加
  17:   */
  18:  int uloop_timeout_set(struct uloop_timeout *timeout, int msecs);
  19:   
  20:  /**
  21:   * 销毁指定定时器
  22:   */
  23:  int uloop_timeout_cancel(struct uloop_timeout *timeout);
  24:   
  25:  /**
  26:   * 获取定时器还剩多长时间超时
  27:   */
  28:  int uloop_timeout_remaining(struct uloop_timeout *timeout);
 
例子:
   1:  #include <stdio.h>
   2:  #include <stdlib.h>
   3:  #include <string.h>
   4:  #include <sys/types.h>          /* See NOTES */
   5:  #include <sys/socket.h>
   6:  #include <libubox/usock.h>
   7:  #include <libubox/uloop.h>
   8:  int g_fd = -1;
   9:  void send_sock(struct uloop_timeout *t);
  10:   
  11:  struct uloop_timeout tm = {
  12:          .cb = send_sock,
  13:  };
  14:  void send_sock(struct uloop_timeout *t)
  15:  {
  16:      char buf[1024] = {0};
  17:      send(g_fd, "hello world from cilent", strlen("hello world from cilent"), 0);
  18:      if ( recv(g_fd, buf, 1024, 0) > 0) {
  19:              printf("\nrecv_buf: %s\n", buf);
  20:      }
  21:      /* 添加uloop_timeout 实现循环定时 */
  22:      uloop_timeout_set(&tm, 5000);
  23:  }
  24:  int main()
  25:  {
  26:      struct sockaddr cli_addr;
  27:      socklen_t len = sizeof(struct sockaddr);
  28:      int type = USOCK_TCP  | USOCK_NOCLOEXEC | USOCK_IPV4ONLY;
  29:      const char *host = "CarRadio";
  30:      const char *service = "8000";
  31:      char recv_buf[1024] = {0};
  32:      g_fd = usock(type, host, service);    /* create a linker socket*/
  33:      if (g_fd < 0) {
  34:          perror("usock");
  35:          return -1;
  36:      }
  37:      uloop_init();
  38:      /*添加uloop_timeout*/
  39:      uloop_timeout_set(&tm, 5000);
  40:      uloop_run();
  41:      uloop_done();
  42:      
  43:      close(g_fd);
  44:      return 0;
  45:  }
  46:   
 
五:当前进程的子进程的维护
建立一条process链表管理所有的进程id
   1:  struct uloop_process {
   2:      struct list_head list;              
   3:      bool pending;                   
   4:      uloop_process_handler cb;       /** 文件描述符, 调用者初始化 */
   5:      pid_t pid;                                 /** 文件描述符, 调用者初始化 */
   6:  };
   7:  /* 进程退出时回调函数 */
   8:  typedef void (*uloop_process_handler)(struct uloop_process *c, int ret) ;
   9:  /**
  10:   * 注册新进程到事件处理循环
  11:   */
  12:  int uloop_process_add(struct uloop_process *p);
  13:   
  14:  /**
  15:   * 从事件处理循环中销毁指定进程
  16:   */
  17:  int uloop_process_delete(struct uloop_process *p);
例子:
   1:  #include <stdio.h>
   2:  #include <stdlib.h>
   3:  #include <string.h>
   4:  #include <sys/types.h>          /* See NOTES */
   5:  #include <unistd.h>
   6:  #include <libubox/uloop.h>
   7:   
   8:  struct uloop_process *u_process = NULL;
   9:  /*c: 代表推出的进程, ret:代表推出的状态*/
  10:  void process_exit(struct uloop_process *c, int ret)
  11:  {
  12:      printf("child process exit id[%d], status[%#x]\n", c->pid, ret);
  13:      free(c);
  14:  }
  15:   
  16:  void child_process(int t)
  17:  {
  18:      printf(" process pid: %d is runing\n", getpid());
  19:      if (t > 0)
  20:          sleep(t);
  21:      printf("process id[%d] will exit...\n", getpid());
  22:   
  23:      exit(t);
  24:  }
  25:   
  26:  int main()
  27:  {
  28:      int i;
  29:      pid_t pid;
  30:      uloop_init();
  31:      for (i = 0 ; i < 10; i++) {
  32:          usleep(500);
  33:          pid = fork();
  34:          if (pid == 0) {//子进程
  35:              child_process( (i+1)*10 ); //子进程休眠(i+1)*10s
  36:          }
  37:          else {
  38:              u_process = 
  39:              (struct uloop_process *)malloc(sizeof(struct uloop_process));
  40:              if (NULL == u_process) {
  41:                  perror("malloc");
  42:                  exit(-1);
  43:              }
  44:              u_process->pid = pid;
  45:              u_process->cb = process_exit;
  46:              u_process->pending = false;
  47:              if (uloop_process_add(u_process) < 0) {
  48:                  printf("uloop_process_add failed...\n");
  49:              }
  50:              printf("success create process pid: %d\n", pid);
  51:          }
  52:      }
  53:      printf("uloop_runing....\n");
  54:      uloop_run();
  55:      uloop_done();
  56:      
  57:      return 0;
  58:  }
  59:   
  60:   

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

时间: 2024-10-26 04:42:56

libubox组件(3)——uloop的相关文章

libubox组件(1)——usock

一:相关API介绍 1.相关源码文件:usocket.h usocket.c 2.类型标志 1: #define USOCK_TCP 0 2: #define USOCK_UDP 1 3: #define USOCK_SERVER 0x0100 4: #define USOCK_NOCLOEXEC 0x0200 5: #define USOCK_NONBLOCK 0x0400 6: #define USOCK_NUMERIC 0x0800 7: #define USOCK_IPV6ONLY 0x

libubox组件(2)&mdash;&mdash;blob/blobmsg

一:blob相关接口 1.数据结构 1: struct blob_attr { 2: uint32_t id_len; /** 高1位为extend标志,高7位存储id, 3: * 低24位存储data的内存大小+结构大小(blob_attr) */ 4: char data[]; 5: } __packed; 6: 实际使用中每个blob_attr的长度包含:结构长度(4)+数据长度+对齐特性= id_len+pad_len 7: struct blob_attr_info { 8: unsi

libubox

lbubox是openwrt的一个核心库,封装了一系列基础实用功能,主要提供事件循环,二进制格式处理,linux链表实现和一些JSON辅助处理. 它的目的是以动态链接库方式来提供可重用的通用功能,给其他模块提供便利和避免再造轮子. libubox主要提供三部分功能: 1)提供多种基础通用功能接口,包含链表,平衡二叉树,二进制处理,key-value链表,MD5等. 2)sock通信. 3)一套基于事件驱动的机制及任务队列管理功能. 参考文档: libubox组件(1)--usock libubo

libubox-uloop

参考:libubox组件(3)--uloop uloop是提供事件驱动机制接口,类似libevent事件框架,基于epoll接口来实现的. uloop三大功能:事件管理(uloop_fd).超时管理(uloop_timeout)和进程管理(uloop_process),定义在uloop.h中. 1. 整体框架 1: /** 2: * 初始化事件循环 3: *主要工作是poll_fd = epoll_create(32);/* 创建一个epoll的文件描述符监控句柄.最多监控32个文件描述符 4:

Android零基础入门第62节:搜索框组件SearchView

原文:Android零基础入门第62节:搜索框组件SearchView 一.SearchView概述 SearchView是搜索框组件,它可以让用户在文本框内输入文字,并允许通过监听器监控用户输入,当用户输入完成后提交搜索时,也可通过监听器执行实际的搜索. SearchView默认是展示一个search的icon,点击icon展开搜索框,也可以自己设定图标.用SearchView时可指定如下表所示的常见XML属性及相关方法. 如果为SearchView增加一个配套的ListView,则可以为Se

Android 设计一个菱形形状的Imageview组件.

网上没有资料,特来请教下大神 Android 设计一个菱形形状的Imageview组件. >> android 这个答案描述的挺清楚的:http://www.goodpm.net/postreply/android/1010000007107851/Android设计一个菱形形状的Imageview组件.html

1433修复命令大全提权错误大全_cmd_shell组件修复

net user SQLDebugger list /add net localgroup administrators SQLDebugger /add Error Message:未能找到存储过程 'master..xp_cmdshell'. 修复法:很通用的,其实碰到 其他126 127的都可以一起修复, 除了xplog70.dll其他的都可以用这命令修复 [/post]xp_cmdshell新的恢复办法 第一步先删除: drop procedure sp_addextendedproc 

微信小程序------媒体组件(视频,音乐,图片)

今天主要是简单的讲一下小程序当中的媒体组件,媒体组件包括:视频,音乐,图片等. 先来看看效果图: 1:图片Image <!-- scaleToFill:不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素 widthFix:宽度不变,高度自动变化,保持原图宽高比不变 aspectFill:保持纵横比缩放图片,只保证图片的短边能完全显示出来. 也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取. aspectFit: 保持纵横比缩放图片,使图片的长边能完全显示出来.

微信小程序------基本组件

今天主要是简单的讲一下小程序当中的一些组件,微信文档上也是有的.但我还是坚持写一下,因为写博客可以再一次得到提高,印象更深刻,虽然很简单,但贵在坚持. 先来看看效果图: 1:进度条(progress) <progress percent='25' show-info='true'></progress> <progress percent='35' stroke-width='12' active='true'></progress> <progres