一: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)

 
例子:
   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:  }

四: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:   




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

  1. openWrt libubox组件之uloop原理分析

    1.    libubox概述 libubox是openwrt新版本中的一个基础库,有很多应用是基于libubox开发的,如uhttpd,netifd,ubusd等. libubox主要提供以下两种功 ...

  2. libubox组件(1)——usock

    一:相关API介绍 1.相关源码文件:usocket.h usocket.c 2.类型标志 1: #define USOCK_TCP 0 2: #define USOCK_UDP 1 3: #defi ...

  3. libubox组件(2)——blob/blobmsg (转载 https://segmentfault.com/a/1190000002391970)

    一:blob相关接口 1.数据结构 1: struct blob_attr { 2: uint32_t id_len; /** 高1位为extend标志,高7位存储id, 3: * 低24位存储dat ...

  4. libubox

    lbubox是openwrt的一个核心库,封装了一系列基础实用功能,主要提供事件循环,二进制格式处理,linux链表实现和一些JSON辅助处理. 它的目的是以动态链接库方式来提供可重用的通用功能,给其 ...

  5. libubox-uloop

    参考:libubox组件(3)——uloop uloop是提供事件驱动机制接口,类似libevent事件框架,基于epoll接口来实现的. uloop三大功能:事件管理(uloop_fd).超时管理( ...

  6. openwrt procd启动流程和脚本分析

    Linux内核执行start_kernel函数时会调用kernel_init来启动init进程,流程如下图: graph LR A[start_kernel] -->B(rest_init) B ...

  7. ExtJS 4.2 评分组件

    上一文章是扩展ExtJS自带的Date组件.在这里将创建一个评分组件. 目录 1. 介绍 2. 示例 3. 资源下载 1. 介绍 代码参考的是 Sencha Touch 2上的一个RatingStar ...

  8. react组件的生命周期

    写在前面: 阅读了多遍文章之后,自己总结了一个.一遍加强记忆,和日后回顾. 一.实例化(初始化) var Button = React.createClass({ getInitialState: f ...

  9. react-router 组件式配置与对象式配置小区别

    1. react-router 对象式配置 和 组件式配置    组件式配置(Redirect) ----对应---- 对象式配置(onEnter钩子) IndexRedirect -----对应-- ...

随机推荐

  1. JNI之常用函数大全

    要素  :1. 该函数大全是基于C语言方式的,对于C++方式可以直接转换 ,例如,对于生成一个jstring类型的方法转换分别如下: C编程环境中使用方法为:(*env) ->NewString ...

  2. getopt使用

    参考: http://www.gnu.org/software/libc/manual/html_node/Example-of-Getopt.html http://en.wikipedia.org ...

  3. 微信开发之自定义菜单--weixin-java-tools

    一.前言 平时在开发微信的过程中,肯定会设计到微信的相关菜单的使用,这次就和大家介绍下如何使用weixin-java-tools来管理菜单 二.自定义菜单分类 1.click:点击推事件用户点击cli ...

  4. coco2dx jni 调用 java 相机返回 图片数据

    新建 一个项目 名字:testJin  包名:com.TanSon.org  python命令:python create_project.py -project testJin -package c ...

  5. [Android Memory] Android 的 StrictMode

    android的2.3 之后引入的StrictMode 对网络的访问做了限制啊. public void onCreate() { if (DEVELOPER_MODE) { StrictMode.s ...

  6. AJAX && JSON之讲解

    Ajax技术的核心是XMLHttpRequest对象(简称XHR),可以通过使用XHR对象获取到服务器的数据,然后再通过DOM将数据插入到页面中呈现.虽然名字中包含XML,但Ajax通讯与数据格式无关 ...

  7. LWIP的移植笔记

    第一次发表博客,文章摘录于还不懂同学的专栏 lwIp的作者做了大量的工作以方便像我这种懒人移植该协议栈,基本上只需修改一个配置头文件和改写3个函数即可完成lwIP的移植.要改写的函数位于lwIP-1. ...

  8. http://jingyan.baidu.com/article/dca1fa6fa07000f1a44052f6.html

    http://jingyan.baidu.com/article/dca1fa6fa07000f1a44052f6.html

  9. [Typescript] Improve Readability with TypeScript Numeric Separators when working with Large Numbers

    When looking at large numbers in code (such as 1800000) it’s oftentimes difficult for the human eye ...

  10. 常见的七大排序算法Java实现

    /** * @author Javen * @Email javenlife@126.com * 2015年12月9日 */ public class Sorting { static int[] a ...