Linux下中斷處理常式源碼分析

來源:互聯網
上載者:User

    之前調試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;     } } 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.