新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > Linux中斷(interrupt)子系統(tǒng)之一:中斷系統(tǒng)基本原理

Linux中斷(interrupt)子系統(tǒng)之一:中斷系統(tǒng)基本原理

作者: 時(shí)間:2016-12-14 來源:網(wǎng)絡(luò) 收藏

  這個(gè)系列文章主要針對(duì)移動(dòng)設(shè)備中的進(jìn)行討論,文中的例子基本都是基于ARM這一體系架構(gòu),其他架構(gòu)的原理其實(shí)也差不多,區(qū)別只是其中的硬件抽象層。內(nèi)核版本基于3.3。雖然內(nèi)核的版本不斷地提升,不過自從上一次變更到當(dāng)前的通用子系統(tǒng)后,大的框架性的東西并沒有太大的改變。

本文引用地址:http://2s4d.com/article/201612/341595.htm

  1. 設(shè)備、控制器和CPU

  一個(gè)完整的設(shè)備中,與中斷相關(guān)的硬件可以劃分為3類,它們分別是:設(shè)備、中斷控制器和CPU本身,下圖展示了一個(gè)smp系統(tǒng)中的中斷硬件的組成結(jié)構(gòu):

 

  圖 1.1 中斷系統(tǒng)的硬件組成

  設(shè)備 設(shè)備是發(fā)起中斷的源,當(dāng)設(shè)備需要請(qǐng)求某種服務(wù)的時(shí)候,它會(huì)發(fā)起一個(gè)硬件中斷信號(hào),通常,該信號(hào)會(huì)連接至中斷控制器,由中斷控制器做進(jìn)一步的處理。在現(xiàn)代的移動(dòng)設(shè)備中,發(fā)起中斷的設(shè)備可以位于soc(system-on-chip)芯片的外部,也可以位于soc的內(nèi)部,因?yàn)槟壳按蠖鄶?shù)soc都集成了大量的硬件IP,例如I2C、SPI、Display Controller等等。

  中斷控制器 中斷控制器負(fù)責(zé)收集所有中斷源發(fā)起的中斷,現(xiàn)有的中斷控制器幾乎都是可編程的,通過對(duì)中斷控制器的編程,我們可以控制每個(gè)中斷源的優(yōu)先級(jí)、中斷的電器類型,還可以打開和關(guān)閉某一個(gè)中斷源,在smp系統(tǒng)中,甚至可以控制某個(gè)中斷源發(fā)往哪一個(gè)CPU進(jìn)行處理。對(duì)于ARM架構(gòu)的soc,使用較多的中斷控制器是VIC(Vector Interrupt Controller),進(jìn)入多核時(shí)代以后,GIC(General Interrupt Controller)的應(yīng)用也開始逐漸變多。

  CPU cpu是最終響應(yīng)中斷的部件,它通過對(duì)可編程中斷控制器的編程操作,控制和管理者系統(tǒng)中的每個(gè)中斷,當(dāng)中斷控制器最終判定一個(gè)中斷可以被處理時(shí),他會(huì)根據(jù)事先的設(shè)定,通知其中一個(gè)或者是某幾個(gè)cpu對(duì)該中斷進(jìn)行處理,雖然中斷控制器可以同時(shí)通知數(shù)個(gè)cpu對(duì)某一個(gè)中斷進(jìn)行處理,實(shí)際上,最后只會(huì)有一個(gè)cpu相應(yīng)這個(gè)中斷請(qǐng)求,但具體是哪個(gè)cpu進(jìn)行響應(yīng)是可能是隨機(jī)的,中斷控制器在硬件上對(duì)這一特性進(jìn)行了保證,不過這也依賴于操作系統(tǒng)對(duì)中斷系統(tǒng)的軟件實(shí)現(xiàn)。在smp系統(tǒng)中,cpu之間也通過IPI(inter processor interrupt)中斷進(jìn)行通信。

  2. IRQ編號(hào)

  系統(tǒng)中每一個(gè)注冊(cè)的中斷源,都會(huì)分配一個(gè)唯一的編號(hào)用于識(shí)別該中斷,我們稱之為IRQ編號(hào)。IRQ編號(hào)貫穿在整個(gè)的通用中斷子系統(tǒng)中。在移動(dòng)設(shè)備中,每個(gè)中斷源的IRQ編號(hào)都會(huì)在arch相關(guān)的一些頭文件中,例如arch/xxx/mach-xxx/include/irqs.h。驅(qū)動(dòng)程序在請(qǐng)求中斷服務(wù)時(shí),它會(huì)使用IRQ編號(hào)注冊(cè)該中斷,中斷發(fā)生時(shí),cpu通常會(huì)從中斷控制器中獲取相關(guān)信息,然后計(jì)算出相應(yīng)的IRQ編號(hào),然后把該IRQ編號(hào)傳遞到相應(yīng)的驅(qū)動(dòng)程序中。

  3. 在驅(qū)動(dòng)程序中申請(qǐng)中斷

  中斷子系統(tǒng)向驅(qū)動(dòng)程序提供了一系列的API,其中的一個(gè)用于向系統(tǒng)申請(qǐng)中斷:

  [cpp] view plain copyint request_threaded_irq(unsigned int irq, irq_handler_t handler,

  irq_handler_t thread_fn, unsigned long irqflags,

  const char *devname, void *dev_id)

  其中,

  irq是要申請(qǐng)的IRQ編號(hào),

  handler是中斷處理服務(wù)函數(shù),該函數(shù)工作在中斷上下文中,如果不需要,可以傳入NULL,但是不可以和thread_fn同時(shí)為NULL;

  thread_fn是中斷線程的回調(diào)函數(shù),工作在內(nèi)核進(jìn)程上下文中,如果不需要,可以傳入NULL,但是不可以和handler同時(shí)為NULL;

  irqflags是該中斷的一些標(biāo)志,可以指定該中斷的電氣類型,是否共享等信息;

  devname指定該中斷的名稱;

  dev_id用于共享中斷時(shí)的cookie data,通常用于區(qū)分共享中斷具體由哪個(gè)設(shè)備發(fā)起;

  關(guān)于該API的詳細(xì)工作機(jī)理我們后面再討論。

  4. 通用中斷子系統(tǒng)(Generic irq)的軟件抽象

  在通用中斷子系統(tǒng)(generic irq)出現(xiàn)之前,內(nèi)核使用__do_IRQ處理所有的中斷,這意味著__do_IRQ中要處理各種類型的中斷,這會(huì)導(dǎo)致軟件的復(fù)雜性增加,層次不分明,而且代碼的可重用性也不好。事實(shí)上,到了內(nèi)核版本2.6.38,__do_IRQ這種方式已經(jīng)徹底在內(nèi)核的代碼中消失了。通用中斷子系統(tǒng)的原型最初出現(xiàn)于ARM體系中,一開始內(nèi)核的開發(fā)者們把3種中斷類型區(qū)分出來,他們是:

  電平觸發(fā)中斷(level type)

  邊緣觸發(fā)中斷(edge type)

  簡(jiǎn)易的中斷(simple type)

  后來又針對(duì)某些需要回應(yīng)eoi(end of interrupt)的中斷控制器,加入了fast eoi type,針對(duì)smp加入了per cpu type。把這些不同的中斷類型抽象出來后,成為了中斷子系統(tǒng)的流控層。要使所有的體系架構(gòu)都可以重用這部分的代碼,中斷控制器也被進(jìn)一步地封裝起來,形成了中斷子系統(tǒng)中的硬件封裝層。我們可以用下面的圖示表示通用中斷子系統(tǒng)的層次結(jié)構(gòu):

    

 

  圖 4.1 通用中斷子系統(tǒng)的層次結(jié)構(gòu)

  硬件封裝層 它包含了體系架構(gòu)相關(guān)的所有代碼,包括中斷控制器的抽象封裝,arch相關(guān)的中斷初始化,以及各個(gè)IRQ的相關(guān)數(shù)據(jù)結(jié)構(gòu)的初始化工作,cpu的中斷入口也會(huì)在arch相關(guān)的代碼中實(shí)現(xiàn)。中斷通用邏輯層通過標(biāo)準(zhǔn)的封裝接口(實(shí)際上就是struct irq_chip定義的接口)訪問并控制中斷控制器的行為,體系相關(guān)的中斷入口函數(shù)在獲取IRQ編號(hào)后,通過中斷通用邏輯層提供的標(biāo)準(zhǔn)函數(shù),把中斷調(diào)用傳遞到中斷流控層中。我們看看irq_chip的部分定義:

  [cpp] view plain copystruct irq_chip {

  const char *name;

  unsigned int (*irq_startup)(struct irq_data *data);

  void (*irq_shutdown)(struct irq_data *data);

  void (*irq_enable)(struct irq_data *data);

  void (*irq_disable)(struct irq_data *data);

  void (*irq_ack)(struct irq_data *data);

  void (*irq_mask)(struct irq_data *data);

  void (*irq_mask_ack)(struct irq_data *data);

  void (*irq_unmask)(struct irq_data *data);

  void (*irq_eoi)(struct irq_data *data);

  int (*irq_set_affinity)(struct irq_data *data, const struct cpumask *dest, bool force);

  int (*irq_retrigger)(struct irq_data *data);

  int (*irq_set_type)(struct irq_data *data, unsigned int flow_type);

  int (*irq_set_wake)(struct irq_data *data, unsigned int on);

  ......

  };

  看到上面的結(jié)構(gòu)定義,很明顯,它實(shí)際上就是對(duì)中斷控制器的接口抽象,我們只要對(duì)每個(gè)中斷控制器實(shí)現(xiàn)以上接口(不必全部),并把它和相應(yīng)的irq關(guān)聯(lián)起來,上層的實(shí)現(xiàn)即可通過這些接口訪問中斷控制器。而且,同一個(gè)中斷控制器的代碼可以方便地被不同的平臺(tái)所重用。

  中斷流控層 所謂中斷流控是指合理并正確地處理連續(xù)發(fā)生的中斷,比如一個(gè)中斷在處理中,同一個(gè)中斷再次到達(dá)時(shí)如何處理,何時(shí)應(yīng)該屏蔽中斷,何時(shí)打開中斷,何時(shí)回應(yīng)中斷控制器等一系列的操作。該層實(shí)現(xiàn)了與體系和硬件無關(guān)的中斷流控處理操作,它針對(duì)不同的中斷電氣類型(level,edge......),實(shí)現(xiàn)了對(duì)應(yīng)的標(biāo)準(zhǔn)中斷流控處理函數(shù),在這些處理函數(shù)中,最終會(huì)把中斷控制權(quán)傳遞到驅(qū)動(dòng)程序注冊(cè)中斷時(shí)傳入的處理函數(shù)或者是中斷線程中。目前內(nèi)核提供了以下幾個(gè)主要的中斷流控函數(shù)的實(shí)現(xiàn)(只列出部分):

  handle_simple_irq();

  handle_level_irq(); 電平中斷流控處理程序

  handle_edge_irq(); 邊沿觸發(fā)中斷流控處理程序

  handle_fasteoi_irq(); 需要eoi的中斷處理器使用的中斷流控處理程序

  handle_percpu_irq(); 該irq只有單個(gè)cpu響應(yīng)時(shí)使用的流控處理程序

  中斷通用邏輯層 該層實(shí)現(xiàn)了對(duì)中斷系統(tǒng)幾個(gè)重要數(shù)據(jù)的管理,并提供了一系列的輔助管理函數(shù)。同時(shí),該層還實(shí)現(xiàn)了中斷線程的實(shí)現(xiàn)和管理,共享中斷和嵌套中斷的實(shí)現(xiàn)和管理,另外它還提供了一些接口函數(shù),它們將作為硬件封裝層和中斷流控層以及驅(qū)動(dòng)程序API層之間的橋梁,例如以下API:

  generic_handle_irq();

  irq_to_desc();

  irq_set_chip();

  irq_set_chained_handler();

  驅(qū)動(dòng)程序API 該部分向驅(qū)動(dòng)程序提供了一系列的API,用于向系統(tǒng)申請(qǐng)/釋放中斷,打開/關(guān)閉中斷,設(shè)置中斷類型和中斷喚醒系統(tǒng)的特性等操作。驅(qū)動(dòng)程序的開發(fā)者通常只會(huì)使用到這一層提供的這些API即可完成驅(qū)動(dòng)程序的開發(fā)工作,其他的細(xì)節(jié)都由另外幾個(gè)軟件層較好地“隱藏”起來了,驅(qū)動(dòng)程序開發(fā)者無需再關(guān)注底層的實(shí)現(xiàn),這看起來確實(shí)是一件美妙的事情,不過我認(rèn)為,要想寫出好的中斷代碼,還是花點(diǎn)時(shí)間了解一下其他幾層的實(shí)現(xiàn)吧。其中的一些API如下:

  enable_irq();

  disable_irq();

  disable_irq_nosync();

  request_threaded_irq();

  irq_set_affinity();

  這里不再對(duì)每一層做詳細(xì)的介紹,我將會(huì)在本系列的其他幾篇文章中做深入的探討。

  5. irq描述結(jié)構(gòu):struct irq_desc

  整個(gè)通用中斷子系統(tǒng)幾乎都是圍繞著irq_desc結(jié)構(gòu)進(jìn)行,系統(tǒng)中每一個(gè)irq都對(duì)應(yīng)著一個(gè)irq_desc結(jié)構(gòu),所有的irq_desc結(jié)構(gòu)的組織方式有兩種:

  基于數(shù)組方式 平臺(tái)相關(guān)板級(jí)代碼事先根據(jù)系統(tǒng)中的IRQ數(shù)量,定義常量:NR_IRQS,在kernel/irq/irqdesc.c中使用該常量定義irq_desc結(jié)構(gòu)數(shù)組:

  [cpp] view plain copystruct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {

  [0 ... NR_IRQS-1] = {

  .handle_irq = handle_bad_irq,

  .depth = 1,

  .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),

  }

  };

  基于基數(shù)樹方式 當(dāng)內(nèi)核的配置項(xiàng)CONFIG_SPARSE_IRQ被選中時(shí),內(nèi)核使用基數(shù)樹(radix tree)來管理irq_desc結(jié)構(gòu),這一方式可以動(dòng)態(tài)地分配irq_desc結(jié)構(gòu),對(duì)于那些具備大量IRQ數(shù)量或者IRQ編號(hào)不連續(xù)的系統(tǒng),使用該方式管理irq_desc對(duì)內(nèi)存的節(jié)省有好處,而且對(duì)那些自帶中斷控制器管理設(shè)備自身多個(gè)中斷源的外部設(shè)備,它們可以在驅(qū)動(dòng)程序中動(dòng)態(tài)地申請(qǐng)這些中斷源所對(duì)應(yīng)的irq_desc結(jié)構(gòu),而不必在系統(tǒng)的編譯階段保留irq_desc結(jié)構(gòu)所需的內(nèi)存。

  下面我們看一看irq_desc的部分定義:

  [cpp] view plain copystruct irq_data {

  unsigned int irq;

  unsigned long hwirq;

  unsigned int node;

  unsigned int state_use_accessors;

  struct irq_chip *chip;

  struct irq_domain *domain;

  void *handler_data;

  void *chip_data;

  struct msi_desc *msi_desc;

  #ifdef CONFIG_SMP

  cpumask_var_t affinity;

  #endif

  };

  [cpp] view plain copystruct irq_desc {

  struct irq_data irq_data;

  unsigned int __percpu *kstat_irqs;

  irq_flow_handler_t handle_irq;

  #ifdef CONFIG_IRQ_PREFLOW_FASTEOI

  irq_preflow_handler_t preflow_handler;

  #endif

  struct irqaction *action; /* IRQ action list */

  unsigned int status_use_accessors;

  unsigned int depth; /* nested irq disables */

  unsigned int wake_depth; /* nested wake enables */

  unsigned int irq_count; /* For detecting broken IRQs */

  raw_spinlock_t lock;

  struct cpumask *percpu_enabled;

  #ifdef CONFIG_SMP

  const struct cpumask *affinity_hint;

  struct irq_affinity_notify *affinity_notify;

  #ifdef CONFIG_GENERIC_PENDING_IRQ

  cpumask_var_t pending_mask;

  #endif

  #endif

  wait_queue_head_t wait_for_threads;

  const char *name;

  } ____cacheline_internodealigned_in_smp;

  對(duì)于irq_desc中的主要字段做一個(gè)解釋:

  irq_data 這個(gè)內(nèi)嵌結(jié)構(gòu)在2.6.37版本引入,之前的內(nèi)核版本的做法是直接把這個(gè)結(jié)構(gòu)中的字段直接放置在irq_desc結(jié)構(gòu)體中,然后在調(diào)用硬件封裝層的chip->xxx()回調(diào)中傳入IRQ編號(hào)作為參數(shù),但是底層的函數(shù)經(jīng)常需要訪問->handler_data,->chip_data,->msi_desc等字段,這需要利用irq_to_desc(irq)來獲得irq_desc結(jié)構(gòu)的指針,然后才能訪問上述字段,者帶來了性能的降低,尤其在配置為sparse irq的系統(tǒng)中更是如此,因?yàn)檫@意味著基數(shù)樹的搜索操作。為了解決這一問題,內(nèi)核開發(fā)者把幾個(gè)低層函數(shù)需要使用的字段單獨(dú)封裝為一個(gè)結(jié)構(gòu),調(diào)用時(shí)的參數(shù)則改為傳入該結(jié)構(gòu)的指針。實(shí)現(xiàn)同樣的目的,那為什么不直接傳入irq_desc結(jié)構(gòu)指針?因?yàn)檫@會(huì)破壞層次的封裝性,我們不希望低層代碼可以看到不應(yīng)該看到的部分,僅此而已。

  kstat_irqs 用于irq的一些統(tǒng)計(jì)信息,這些統(tǒng)計(jì)信息可以從proc文件系統(tǒng)中查詢。

  action 中斷響應(yīng)鏈表,當(dāng)一個(gè)irq被觸發(fā)時(shí),內(nèi)核會(huì)遍歷該鏈表,調(diào)用action結(jié)構(gòu)中的回調(diào)handler或者激活其中的中斷線程,之所以實(shí)現(xiàn)為一個(gè)鏈表,是為了實(shí)現(xiàn)中斷的共享,多個(gè)設(shè)備共享同一個(gè)irq,這在外圍設(shè)備中是普遍存在的。

  status_use_accessors 記錄該irq的狀態(tài)信息,內(nèi)核提供了一系列irq_settings_xxx的輔助函數(shù)訪問該字段,詳細(xì)請(qǐng)查看kernel/irq/settings.h

  depth 用于管理enable_irq()/disable_irq()這兩個(gè)API的嵌套深度管理,每次enable_irq時(shí)該值減去1,每次disable_irq時(shí)該值加1,只有depth==0時(shí)才真正向硬件封裝層發(fā)出關(guān)閉irq的調(diào)用,只有depth==1時(shí)才會(huì)向硬件封裝層發(fā)出打開irq的調(diào)用。disable的嵌套次數(shù)可以比enable的次數(shù)多,此時(shí)depth的值大于1,隨著enable的不斷調(diào)用,當(dāng)depth的值為1時(shí),在向硬件封裝層發(fā)出打開irq的調(diào)用后,depth減去1后,此時(shí)depth為0,此時(shí)處于一個(gè)平衡狀態(tài),我們只能調(diào)用disable_irq,如果此時(shí)enable_irq被調(diào)用,內(nèi)核會(huì)報(bào)告一個(gè)irq失衡的警告,提醒驅(qū)動(dòng)程序的開發(fā)人員檢查自己的代碼。

  lock 用于保護(hù)irq_desc結(jié)構(gòu)本身的自旋鎖。

  affinity_hit 用于提示用戶空間,作為優(yōu)化irq和cpu之間的親緣關(guān)系的依據(jù)。

  pending_mask 用于調(diào)整irq在各個(gè)cpu之間的平衡。

  wait_for_threads 用于synchronize_irq(),等待該irq所有線程完成。

  irq_data結(jié)構(gòu)中的各字段:

  irq 該結(jié)構(gòu)所對(duì)應(yīng)的IRQ編號(hào)。

  hwirq 硬件irq編號(hào),它不同于上面的irq;

  node 通常用于hwirq和irq之間的映射操作;

  state_use_accessors 硬件封裝層需要使用的狀態(tài)信息,不要直接訪問該字段,內(nèi)核定義了一組函數(shù)用于訪問該字段:irqd_xxxx(),參見include/linux/irq.h。

  chip 指向該irq所屬的中斷控制器的irq_chip結(jié)構(gòu)指針

  handler_data 每個(gè)irq的私有數(shù)據(jù)指針,該字段由硬件封轉(zhuǎn)層使用,例如用作底層硬件的多路復(fù)用中斷。

  chip_data 中斷控制器的私有數(shù)據(jù),該字段由硬件封轉(zhuǎn)層使用。

  msi_desc 用于PCIe總線的MSI或MSI-X中斷機(jī)制。

  affinity 記錄該irq與cpu之間的親緣關(guān)系,它其實(shí)是一個(gè)bit-mask,每一個(gè)bit代表一個(gè)cpu,置位后代表該cpu可能處理該irq。

  這是通用中斷子系統(tǒng)系列文章的第一篇,這里不會(huì)詳細(xì)介紹各個(gè)軟件層次的實(shí)現(xiàn)原理,但是有必要對(duì)整個(gè)架構(gòu)做簡(jiǎn)要的介紹:

  系統(tǒng)啟動(dòng)階段,取決于內(nèi)核的配置,內(nèi)核會(huì)通過數(shù)組或基數(shù)樹分配好足夠多的irq_desc結(jié)構(gòu);

  根據(jù)不同的體系結(jié)構(gòu),初始化中斷相關(guān)的硬件,尤其是中斷控制器;

  為每個(gè)必要irq的irq_desc結(jié)構(gòu)填充默認(rèn)的字段,例如irq編號(hào),irq_chip指針,根據(jù)不同的中斷類型配置流控handler;

  設(shè)備驅(qū)動(dòng)程序在初始化階段,利用request_threaded_irq() api申請(qǐng)中斷服務(wù),兩個(gè)重要的參數(shù)是handler和thread_fn;

  當(dāng)設(shè)備觸發(fā)一個(gè)中斷后,cpu會(huì)進(jìn)入事先設(shè)定好的中斷入口,它屬于底層體系相關(guān)的代碼,它通過中斷控制器獲得irq編號(hào),在對(duì)irq_data結(jié)構(gòu)中的某些字段進(jìn)行處理后,會(huì)將控制權(quán)傳遞到中斷流控層(通過irq_desc->handle_irq);

  中斷流控處理代碼在作出必要的流控處理后,通過irq_desc->action鏈表,取出驅(qū)動(dòng)程序申請(qǐng)中斷時(shí)注冊(cè)的handler和thread_fn,根據(jù)它們的賦值情況,或者只是調(diào)用handler回調(diào),或者啟動(dòng)一個(gè)線程執(zhí)行thread_fn,又或者兩者都執(zhí)行;

  至此,中斷最終由驅(qū)動(dòng)程序進(jìn)行了響應(yīng)和處理。

  6. 中斷子系統(tǒng)的proc文件接口

  在/proc目錄下面,有兩個(gè)與中斷子系統(tǒng)相關(guān)的文件和子目錄,它們是:

  /proc/interrupts:文件

  /proc/irq:子目錄

  讀取interrupts會(huì)依次顯示irq編號(hào),每個(gè)cpu對(duì)該irq的處理次數(shù),中斷控制器的名字,irq的名字,以及驅(qū)動(dòng)程序注冊(cè)該irq時(shí)使用的名字,以下是一個(gè)例子:

    

 

  /proc/irq目錄下面會(huì)為每個(gè)注冊(cè)的irq創(chuàng)建一個(gè)以irq編號(hào)為名字的子目錄,每個(gè)子目錄下分別有以下條目:

  smp_affinity irq和cpu之間的親緣綁定關(guān)系;

  smp_affinity_hint 只讀條目,用于用戶空間做irq平衡只用;

  spurious 可以獲得該irq被處理和未被處理的次數(shù)的統(tǒng)計(jì)信息;

  handler_name 驅(qū)動(dòng)程序注冊(cè)該irq時(shí)傳入的處理程序的名字;

  根據(jù)irq的不同,以上條目不一定會(huì)全部都出現(xiàn),以下是某個(gè)設(shè)備的例子:

  # cd /proc/irq

  # ls

  ls

  332

  248

  ......

  ......

  12

  11

  default_smp_affinity

  # ls 332

  bcmsdh_sdmmc

  spurious

  node

  affinity_hint

  smp_affinity

  # cat 332/smp_affinity

  可見,以上設(shè)備是一個(gè)使用雙核cpu的設(shè)備,因?yàn)閟mp_affinity的值是3,系統(tǒng)默認(rèn)每個(gè)中斷可以由兩個(gè)cpu進(jìn)行處理。

  本章內(nèi)容結(jié)束。接下來的計(jì)劃:

  Linux中斷(interrupt)子系統(tǒng)之二:arch相關(guān)的硬件封裝層

  Linux中斷(interrupt)子系統(tǒng)之三:中斷流控處理層

  Linux中斷(interrupt)子系統(tǒng)之四:驅(qū)動(dòng)程序接口層

  Linux中斷(interrupt)子系統(tǒng)之五:軟件中斷(softirq)



關(guān)鍵詞: Linux 中斷

評(píng)論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉