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

之前调试vxworks下PCIE的中断程序,都封装好了,所以只用了个intConnect,感觉没学到东西,就再看了下Linux的源码。

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

int main (int argc, char **argv) {   char *p;   int daemon_mode = 0;   char *progname;   struct thread thread;   /* Set umask before anything for security */   umask (0027);   /* Get program name. */   progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);   /* First of all we need logging init. */ // 在这里设置 log   zlog_default = openzlog (progname, ZLOG_NOLOG, ZLOG_RIP,                         LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);   /* Command line option parse. */   while (1)     {       int opt; // 解析参数        opt = getopt_long (argc, argv, "df:hA:P:rv", longopts, 0);       if (opt == EOF)        break;       switch (opt)        {        case 0:          break;        case 'd':          daemon_mode = 1;         break;        case 'f':          config_file = optarg;          break;        case 'A':          vty_addr = optarg;          break;         case 'i':           pid_file = optarg;           break;        case 'P':          vty_port = atoi (optarg);          break;        case 'r':          retain_mode = 1;          break;        case 'v':          print_version (progname);          exit (0);          break;        case 'h':          usage (progname, 0);          break;        default:         usage (progname, 1);          break;        }     }   /* Prepare master thread. */   master = thread_master_create ();   /* Library initialization. */   signal_init ();   cmd_init (1);   vty_init ();   memory_init ();   keychain_init ();   /* RIP related initialization. */   rip_init ();   rip_if_init ();   rip_zclient_init ();   rip_peer_init ();   /* Sort all installed commands. */   sort_node ();   /* Get configuration file. */   vty_read_config (config_file, config_current, config_default);   /* Change to the daemon program. */   if (daemon_mode)  // 进入后台运行,成为守护进程     daemon (0, 0);   /* Pid file create. */   pid_output (pid_file);   /* Create VTY's socket */   vty_serv_sock (vty_addr, vty_port, RIP_VTYSH_PATH);   /* Execute each thread. */   while (thread_fetch (master, &thread)) // 真正执行线程在这里     thread_call (&thread);    /* Not reached. */   exit (0); } /*先看看 thread_call (&thread); 这一行,进入此函数 */void thread_call (struct thread *thread) {   unsigned long thread_time;   RUSAGE_T ru;   GETRUSAGE (&thread->ru);   (*thread->func) (thread); // 此处调用线程链表的钩子函数,具体钩子函数是什么,待会看   GETRUSAGE (&ru);   thread_time = thread_consumed_time (&ru, &thread->ru);   #ifdef THREAD_CONSUMED_TIME_CHECK   if (thread_time > 200000L)     {       /*        * We have a CPU Hog on our hands.        * Whinge about it now, so we're aware this is yet another task        * to fix.        */       zlog_err ("CPU HOG task %lx ran for %ldms",   /* FIXME: report the name of the function somehow */               (unsigned long) thread->func,               thread_time / 1000L);     } #endif /* THREAD_CONSUMED_TIME_CHECK */ } /*在看看 thread_fetch ,贴出代码 */struct thread * thread_fetch (struct thread_master *m, struct thread *fetch) {   int num;   int ready;   struct thread *thread;   fd_set readfd;   fd_set writefd;   fd_set exceptfd;   struct timeval timer_now;   struct timeval timer_val;   struct timeval *timer_wait;   struct timeval timer_nowait;   timer_nowait.tv_sec = 0;   timer_nowait.tv_usec = 0;   while (1)     {       /* Normal event is the highest priority.  */  /*event 事件优先级最高,其实就是触发更新,所谓触发更新,就是路由表一改变,马上调用线程的钩子函数,多播出去 */      if ((thread = thread_trim_head (&m->event)) != NULL)        return thread_run (m, thread, fetch);       /* Execute timer.  */       gettimeofday (&timer_now, NULL); /* 在这里看是否超时,也就是一个路由表项在 180S 内没有更新,则将对应的线程从活动链表取出, * 放入 master - >unuse 链表。说白了就是把此线程挂起,不再执行 */      for (thread = m->timer.head; thread; thread = thread->next)        if (timeval_cmp (timer_now, thread->u.sands) >= 0)          {            thread_list_delete (&m->timer, thread);            return thread_run (m, thread, fetch);          } // 如果接收到新的 RIP 数据包,则读入 , 采用 select 机制       /* If there are any ready threads, process top of them.  */       if ((thread = thread_trim_head (&m->ready)) != NULL)        return thread_run (m, thread, fetch);       /* Structure copy.  */       readfd = m->readfd;       writefd = m->writefd;       exceptfd = m->exceptfd;       /* Calculate select wait timer. */       timer_wait = thread_timer_wait (m, &timer_val);       num = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);       if (num == 0)        continue;       if (num < 0)        {          if (errno == EINTR)            continue;          zlog_warn ("select() error: %s", strerror (errno));          return NULL;        }       /* Normal priority read thead. */       ready = thread_process_fd (m, &m->read, &readfd, &m->readfd);       /* Write thead. */       ready = thread_process_fd (m, &m->write, &writefd, &m->writefd);       if ((thread = thread_trim_head (&m->ready)) != NULL)        return thread_run (m, thread, fetch);     } } /* 通过以上分析,发现就是 RIP 经过初始化后,然后进入一个 while 死循环, * 在这个死循环中根据不同的优先级去执行不同的线程钩子函数。而这些钩子函数在什么地方注册的呢, * 进入 ripd.c 的 void rip_event (enum rip_event event, int sock) 函数。 */void rip_event (enum rip_event event, int sock) {   int jitter = 0;   switch (event) { //read 事件,通过 thread_add_read 注册的钩子函数为 rip_read.     case RIP_READ:       rip->t_read = thread_add_read (master, rip_read, NULL, sock);       break; //update 事件,通过 thread_add_read 注册的钩子函数为 rip_update.     case RIP_UPDATE_EVENT:       if (rip->t_update)       {          thread_cancel (rip->t_update);          rip->t_update = NULL;        }       jitter = rip_update_jitter (rip->update_time);       rip->t_update = thread_add_timer (master, rip_update, NULL,                        sock ? 2 : rip->update_time + jitter);       break; // 触发更新,通过 thread_add_read 注册的钩子函数为 rip_triggered_update.     case RIP_TRIGGERED_UPDATE:        printf("come in RIP_TRIGGERED_UPDATE\n");       if (rip->t_triggered_interval)        rip->trigger = 1;       else if (! rip->t_triggered_update)           {           printf("add event rip_triggered_update\n");       rip->t_triggered_update =          thread_add_event (master, rip_triggered_update, NULL, 0);           }       break;     default:       break;     } } 

积极的人在每一次忧患中都看到一个机会,

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

相关文章:

你感兴趣的文章:

标签云: