Linux下中断处理程序源码分析

下面是最近调试中断时额外研习了一下Linux的内核代码,下面就直接贴代码和注释了,大量借鉴了网上牛人的见解,还望海涵!!

 
  1. int main (int argc, char **argv)   
  2. {   
  3.   char *p;   
  4.   int daemon_mode = 0;   
  5.   char *progname;   
  6.   struct thread thread;   
  7.   
  8.   /* Set umask before anything for security */   
  9.   umask (0027);   
  10.   
  11.   /* Get program name. */   
  12.   
  13.   progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);   
  14.   
  15.   /* First of all we need logging init. */   
  16.   
  17. // 在这里设置 log    
  18.   
  19.   zlog_default = openzlog (progname, ZLOG_NOLOG, ZLOG_RIP,   
  20.   
  21.                         LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);   
  22.   
  23.   
  24.   /* Command line option parse. */   
  25.   
  26.   while (1)   
  27.     {   
  28.       int opt;   
  29. // 解析参数    
  30.   
  31.        opt = getopt_long (argc, argv, "df:hA:P:rv", longopts, 0);   
  32.   
  33.       if (opt == EOF)   
  34.   
  35.        break;   
  36.   
  37.       switch (opt)   
  38.   
  39.        {   
  40.        case 0:   
  41.   
  42.          break;   
  43.   
  44.        case 'd':   
  45.          daemon_mode = 1;   
  46.         break;   
  47.   
  48.        case 'f':   
  49.          config_file = optarg;   
  50.          break;   
  51.   
  52.        case 'A':   
  53.          vty_addr = optarg;   
  54.          break;   
  55.   
  56.         case 'i':   
  57.           pid_file = optarg;   
  58.           break;   
  59.   
  60.        case 'P':   
  61.          vty_port = atoi (optarg);   
  62.          break;   
  63.   
  64.        case 'r':   
  65.          retain_mode = 1;   
  66.          break;   
  67.   
  68.        case 'v':   
  69.          print_version (progname);   
  70.          exit (0);   
  71.          break;   
  72.   
  73.        case 'h':   
  74.          usage (progname, 0);   
  75.          break;   
  76.   
  77.        default:   
  78.         usage (progname, 1);   
  79.          break;   
  80.   
  81.        }   
  82.     }   
  83.   /* Prepare master thread. */   
  84.   
  85.   master = thread_master_create ();   
  86.   /* Library initialization. */   
  87.   
  88.   signal_init ();   
  89.   
  90.   cmd_init (1);   
  91.   
  92.   vty_init ();   
  93.   
  94.   memory_init ();   
  95.   
  96.   keychain_init ();   
  97.   
  98.   /* RIP related initialization. */   
  99.   rip_init ();   
  100.   
  101.   rip_if_init ();   
  102.   
  103.   rip_zclient_init ();   
  104.   
  105.   rip_peer_init ();   
  106.   
  107.   /* Sort all installed commands. */   
  108.   sort_node ();   
  109.   
  110.   /* Get configuration file. */   
  111.   
  112.   vty_read_config (config_file, config_current, config_default);   
  113.   /* Change to the daemon program. */   
  114.   
  115.   if (daemon_mode)  // 进入后台运行,成为守护进程    
  116.   
  117.     daemon (0, 0);   
  118.   
  119.   /* Pid file create. */   
  120.   
  121.   pid_output (pid_file);   
  122.   
  123.   /* Create VTY's socket */   
  124.   
  125.   vty_serv_sock (vty_addr, vty_port, RIP_VTYSH_PATH);   
  126.   /* Execute each thread. */   
  127.   
  128.   while (thread_fetch (master, &thread)) // 真正执行线程在这里    
  129.   
  130.     thread_call (&thread);    
  131.   
  132.   /* Not reached. */   
  133.   
  134.   exit (0);   
  135.   
  136. }   
  137.   
  138. /*先看看 thread_call (&thread); 这一行,进入此函数 */  
  139.   
  140. void   
  141. thread_call (struct thread *thread)   
  142. {   
  143.   unsigned long thread_time;   
  144.   RUSAGE_T ru;   
  145.   
  146.   GETRUSAGE (&thread->ru);   
  147.   
  148.   (*thread->func) (thread); // 此处调用线程链表的钩子函数,具体钩子函数是什么,待会看    
  149.   
  150.   GETRUSAGE (&ru);   
  151.   
  152.   thread_time = thread_consumed_time (&ru, &thread->ru);     
  153.   
  154. #ifdef THREAD_CONSUMED_TIME_CHECK    
  155.   if (thread_time > 200000L)   
  156.     {   
  157.       /*  
  158.        * We have a CPU Hog on our hands.  
  159.        * Whinge about it now, so we're aware this is yet another task  
  160.        * to fix.  
  161.        */   
  162.       zlog_err ("CPU HOG task %lx ran for %ldms",   
  163.   
  164.           /* FIXME: report the name of the function somehow */   
  165.               (unsigned longthread->func,   
  166.               thread_time / 1000L);   
  167.     }   
  168. #endif /* THREAD_CONSUMED_TIME_CHECK */    
  169. }   
  170.   
  171. /*在看看 thread_fetch ,贴出代码 */  
  172.   
  173. struct thread *   
  174. thread_fetch (struct thread_master *m, struct thread *fetch)   
  175. {   
  176.   int num;   
  177.   int ready;   
  178.   struct thread *thread;   
  179.   fd_set readfd;   
  180.   fd_set writefd;   
  181.   fd_set exceptfd;   
  182.   struct timeval timer_now;   
  183.   struct timeval timer_val;   
  184.   struct timeval *timer_wait;   
  185.   struct timeval timer_nowait;   
  186.   
  187.   timer_nowait.tv_sec = 0;   
  188.   timer_nowait.tv_usec = 0;   
  189.   
  190.   while (1)   
  191.     {   
  192.       /* Normal event is the highest priority.  */  
  193.       /*event 事件优先级最高,其实就是触发更新,所谓触发更新,就是路由表一改变,马上调用线程的钩子函数,多播出去 */  
  194.       if ((thread = thread_trim_head (&m->event)) != NULL)   
  195.        return thread_run (m, thread, fetch);   
  196.   
  197.       /* Execute timer.  */   
  198.   
  199.       gettimeofday (&timer_now, NULL);   
  200.   
  201. /* 在这里看是否超时,也就是一个路由表项在 180S 内没有更新,则将对应的线程从活动链表取出, 
  202.  * 放入 master - >unuse 链表。说白了就是把此线程挂起,不再执行 */  
  203.       for (thread = m->timer.head; threadthread = thread->next)   
  204.        if (timeval_cmp (timer_now, thread->u.sands) >= 0)   
  205.          {   
  206.            thread_list_delete (&m->timer, thread);   
  207.            return thread_run (m, thread, fetch);   
  208.          }   
  209.   
  210. // 如果接收到新的 RIP 数据包,则读入 , 采用 select 机制    
  211.   
  212.       /* If there are any ready threads, process top of them.  */   
  213.       if ((thread = thread_trim_head (&m->ready)) != NULL)   
  214.   
  215.        return thread_run (m, thread, fetch);   
  216.   
  217.       /* Structure copy.  */   
  218.   
  219.       readfd = m->readfd;   
  220.   
  221.       writefd = m->writefd;   
  222.   
  223.       exceptfd = m->exceptfd;   
  224.   
  225.       /* Calculate select wait timer. */   
  226.   
  227.       timer_wait = thread_timer_wait (m, &timer_val);   
  228.   
  229.       num = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);   
  230.   
  231.       if (num == 0)   
  232.   
  233.        continue;   
  234.   
  235.       if (num < 0)   
  236.        {   
  237.          if (errno == EINTR)   
  238.            continue;   
  239.   
  240.          zlog_warn ("select() error: %s", strerror (errno));   
  241.   
  242.          return NULL;   
  243.        }   
  244.   
  245.       /* Normal priority read thead. */   
  246.   
  247.       ready = thread_process_fd (m, &m->read, &readfd, &m->readfd);   
  248.   
  249.       /* Write thead. */   
  250.   
  251.       ready = thread_process_fd (m, &m->write, &writefd, &m->writefd);   
  252.   
  253.       if ((thread = thread_trim_head (&m->ready)) != NULL)   
  254.   
  255.        return thread_run (m, thread, fetch);   
  256.   
  257.     }   
  258.   
  259. }   
  260.   
  261. /* 通过以上分析,发现就是 RIP 经过初始化后,然后进入一个 while 死循环, 
  262.  * 在这个死循环中根据不同的优先级去执行不同的线程钩子函数。而这些钩子函数在什么地方注册的呢, 
  263.  * 进入 ripd.c 的 void rip_event (enum rip_event event, int sock) 函数。 */  
  264.   
  265. void   
  266. rip_event (enum rip_event event, int sock)   
  267. {   
  268.   int jitter = 0;   
  269.   
  270.   switch (event)   
  271. {   
  272. //read 事件,通过 thread_add_read 注册的钩子函数为 rip_read.    
  273.     case RIP_READ:   
  274.   
  275.       rip->t_read = thread_add_read (master, rip_read, NULL, sock);   
  276.   
  277.       break;   
  278. //update 事件,通过 thread_add_read 注册的钩子函数为 rip_update.        
  279. case RIP_UPDATE_EVENT:   
  280.   
  281.       if (rip->t_update)   
  282.       {   
  283.          thread_cancel (rip->t_update);   
  284.          rip->t_update = NULL;   
  285.        }   
  286.   
  287.       jitter = rip_update_jitter (rip->update_time);   
  288.   
  289.       rip->t_update = thread_add_timer (master, rip_update, NULL,   
  290.   
  291.                        sock ? 2 : rip->update_time + jitter);   
  292.   
  293.       break;   
  294.   
  295. // 触发更新,通过 thread_add_read 注册的钩子函数为 rip_triggered_update.    
  296.   
  297.     case RIP_TRIGGERED_UPDATE:   
  298.   
  299.        printf("come in RIP_TRIGGERED_UPDATE\n");   
  300.   
  301.       if (rip->t_triggered_interval)   
  302.   
  303.        rip->trigger = 1;   
  304.   
  305.       else if (! rip->t_triggered_update)   
  306.           {   
  307.           printf("add event rip_triggered_update\n");  
  308.   
  309.        rip->t_triggered_update =   
  310.   
  311.          thread_add_event (master, rip_triggered_update, NULL, 0);   
  312.           }   
  313.   
  314.       break;   
  315.   
  316.     default:   
  317.       break;   
  318.   
  319.     }   
  320.   
  321. }  

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值