커 널 소스 코드 분석의 소프트 인 터 럽 트 (3.16 - rc4 기반)
27247 단어 소스 코드 분석
softing_vec 배열 (kernel / softirq. c)
1 static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;
NR_SOFTIRQS 값 은 10 으로 커 널 이 10 개의 소프트 인 터 럽 트 함 수 를 지원 한 다 는 뜻 입 니 다.
softirq_action 구조 체 (include / linux / interrupt. h)
1 struct softirq_action
2 {
3 void (*action)(struct softirq_action *);
4 };
action 은 함수 포인터 변수 로 소프트 인 터 럽 트 함 수 를 가리 키 고 있 습 니 다.
irq_cpustat_t 구조 체 (arch / x86 / include / asm / hardirq. h)
1 typedef struct {
2 unsigned int __softirq_pending;
3 unsigned int __nmi_count; /* arch dependent */
4 #ifdef CONFIG_X86_LOCAL_APIC
5 unsigned int apic_timer_irqs; /* arch dependent */
6 unsigned int irq_spurious_count;
7 unsigned int icr_read_retry_count;
8 #endif
9 #ifdef CONFIG_HAVE_KVM
10 unsigned int kvm_posted_intr_ipis;
11 #endif
12 unsigned int x86_platform_ipis; /* arch dependent */
13 unsigned int apic_perf_irqs;
14 unsigned int apic_irq_work_irqs;
15 #ifdef CONFIG_SMP
16 unsigned int irq_resched_count;
17 unsigned int irq_call_count;
18 /*
19 * irq_tlb_count is double-counted in irq_call_count, so it must be
20 * subtracted from irq_call_count when displaying irq_call_count
21 */
22 unsigned int irq_tlb_count;
23 #endif
24 #ifdef CONFIG_X86_THERMAL_VECTOR
25 unsigned int irq_thermal_count;
26 #endif
27 #ifdef CONFIG_X86_MCE_THRESHOLD
28 unsigned int irq_threshold_count;
29 #endif
30 #if IS_ENABLED(CONFIG_HYPERV) || defined(CONFIG_XEN)
31 unsigned int irq_hv_callback_count;
32 #endif
33 } ____cacheline_aligned irq_cpustat_t;
cpu 마다 이러한 구조 체 변 수 를 가지 고 있 습 니 다. 소프트 인 터 럽 트 에서 우 리 는 두 번 째 줄 의 구성원, 32 비트 의 소프트 인 터 럽 트 마스크 를 사용 해 야 합 니 다.소프트 인 터 럽 트 가 걸 려 있 을 때 이 마스크 의 해당 위 치 를 설정 합 니 다.
2. 소프트 인 터 럽 트 의 실행 과정
우선 오픈 사용softirq () 함수 등록 소프트 인 터 럽 트 함수, 코드 는 다음 과 같 습 니 다 (kernel / softirq. c):
1 void open_softirq(int nr, void (*action)(struct softirq_action *))
2 {
3 softirq_vec[nr].action = action;
4 }
소프트 인 터 럽 트 함수 포인터 action 을 softirq 에 저장 합 니 다.vec 배열 의 대응 요소 중.
이어서 raise 사용softirq () 활성화 소프트 인 터 럽 트, 코드 는 다음 과 같 습 니 다 (kernel / softirq. c):
1 void raise_softirq(unsigned int nr)
2 {
3 unsigned long flags;
4
5 local_irq_save(flags);
6 raise_softirq_irqoff(nr);
7 local_irq_restore(flags);
8 }
다섯 번 째 줄 은 로 컬 인 터 럽 트 를 닫 고 일곱 번 째 줄 은 인 터 럽 트 를 복원 합 니 다.여섯 번 째 줄 은 nr 에 대응 하 는 소프트 인 터 럽 트 함 수 를 활성화 합 니 다.이어서 raise 분석softirq_irqoff (), 코드 는 다음 과 같 습 니 다 (kernel / softirq. c):
1 inline void raise_softirq_irqoff(unsigned int nr)
2 {
3 __raise_softirq_irqoff(nr);
4
5 /*
6 * If we're in an interrupt or softirq, we're done
7 * (this also catches softirq-disabled code). We will
8 * actually run the softirq once we return from
9 * the irq or softirq.
10 *
11 * Otherwise we wake up ksoftirqd to make sure we
12 * schedule the softirq soon.
13 */
14 if (!in_interrupt())
15 wakeup_softirqd();
16 }
제3 행raise_softirq_irqoff 함수 가 소프트 인 터 럽 트 마스크 의 해당 위 치 를 설정 하 였 습 니 다. 코드 는 다음 과 같 습 니 다 (kernel / softirq. c).그리고 14 번 째 줄 은 소프트 인 터 럽 트 가 활성화 되 었 거나 비활성화 되 었 는 지 판단 합 니 다. 없 으 면 15 줄 에서 커 널 스 레 드 ksoftirq 를 활성화 하여 소프트 인 터 럽 트 를 실행 합 니 다.
1 void (unsigned int nr)
2 {
3 trace_softirq_raise(nr);
4 or_softirq_pending(1UL << nr);
5 }
구체 적 으로 네 번 째 줄 의 함수 에 마스크 위 치 를 설정 합 니 다.
3. 어느 곳 에서 든 소프트 인 터 럽 트 에 들 어 갈 수 있 는 지 분석 해 보 자.
첫 번 째 부분 은 물론 위 에서 언급 한 커 널 스 레 드 ksoftirq 가 활성화 되 었 을 때 입 니 다.다음은 ksoftirq 스 레 드 (kernel / softirq. c) 를 보 겠 습 니 다.
1 DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
cpu 마다 struct task 를 가리 키 는 것 을 정의 합 니 다struct 형식의 구조 체 변 수 는 분명 합 니 다. 이 변 수 는 ksoftirq 스 레 드 의 프로 세 스 설명 자 를 저장 합 니 다.(이 를 통 해 Liux 의 스 레 드 와 프로 세 스 는 하나의 것 임 을 나타 낸다)
이 어 ksoftirq 스 레 드 가 실행 할 함수 (kernel / softirq. c) 를 살 펴 보 겠 습 니 다.
1 static void run_ksoftirqd(unsigned int cpu)
2 {
3 local_irq_disable();
4 if (local_softirq_pending()) {
5 /*
6 * We can safely run softirq on inline stack, as we are not deep
7 * in the task stack here.
8 */
9 __do_softirq();
10 rcu_note_context_switch(cpu);
11 local_irq_enable();
12 cond_resched();
13 return;
14 }
15 local_irq_enable();
16 }
이 함 수 는 ksoftirq 스 레 드 의 스 레 드 입 니 다.제9 행do_softirq () 에서 모든 소프트 인 터 럽 트 함 수 를 호출 합 니 다.
우리 뒤 돌아 서 wakeup 분석 해 보 자.softirqd (), ksoftirq 라인 이 어떻게 깨 어 나 는 지 보 세 요 (kernel / softirq. c).
1 static void wakeup_softirqd(void)
2 {
3 /* Interrupts are disabled: no need to stop preemption */
4 struct task_struct *tsk = __this_cpu_read(ksoftirqd);
5
6 if (tsk && tsk->state != TASK_RUNNING)
7 wake_up_process(tsk);
8 }
네 번 째 줄 은 로 컬 cpu 의 ksoftirq 스 레 드 설명 자 를 tsk 변수 에 읽 고 여섯 번 째 줄 에서 ksoftirq 스 레 드 가 실행 되 지 않 으 면 일곱 번 째 줄 에서 이 스 레 드 를 깨 웁 니 다.
두 번 째 곳, 처리 프로그램 중단 doIRQ 처리 완료 또는 irq 호출exit 함수 시.다음은 irqexit 코드 (kernel / softirq. c).
1 void irq_exit(void)
2 {
3 #ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED
4 local_irq_disable();
5 #else
6 WARN_ON_ONCE(!irqs_disabled());
7 #endif
8
9 account_irq_exit_time(current);
10 preempt_count_sub(HARDIRQ_OFFSET);
11 if (!in_interrupt() && local_softirq_pending())
12 invoke_softirq();
13
14 tick_irq_exit();
15 rcu_irq_exit();
16 trace_hardirq_exit(); /* must be last! */
17 }
내 가 말 할 필요 없 지, 나 는 네가 한눈 에 12 번 째 줄 을 노 릴 수 있 을 것 이 라 고 생각한다.invokesoftirq 함수 (kernel / softirq. c).
1 static inline void invoke_softirq(void)
2 {
3 if (!force_irqthreads) {
4 #ifdef CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK
5 /*
6 * We can safely execute softirq on the current stack if
7 * it is the irq stack, because it should be near empty
8 * at this stage.
9 */
10 __do_softirq();
11 #else
12 /*
13 * Otherwise, irq_exit() is called on the task stack that can
14 * be potentially deep already. So call softirq in its own stack
15 * to prevent from any overrun.
16 */
17 do_softirq_own_stack();
18 #endif
19 } else {
20 wakeup_softirqd();
21 }
22 }
제3 행 forceirqthreads 값 이 0 이기 때문에 이 함수 도 를 호출 하 였 습 니 다.do_소프트 인 터 럽 트 를 실행 하기 위해 softirq () 를 사용 합 니 다.
아직 몇 군데 분석 을 하지 않 고 나중에 시간 이 있 으 면 보충 할 곳 이 있다.
4. 다음은do_softirq () 함수 (kernel / softirq. c).
1 asmlinkage __visible void __do_softirq(void)
2 {
3 unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
4 unsigned long old_flags = current->flags;
5 int max_restart = MAX_SOFTIRQ_RESTART;
6 struct softirq_action *h;
7 bool in_hardirq;
8 __u32 pending;
9 int softirq_bit;
10
11 /*
12 * Mask out PF_MEMALLOC s current task context is borrowed for the
13 * softirq. A softirq handled such as network RX might set PF_MEMALLOC
14 * again if the socket is related to swap
15 */
16 current->flags &= ~PF_MEMALLOC;
17
18 pending = local_softirq_pending();
19 account_irq_enter_time(current);
20
21 __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET);
22 in_hardirq = lockdep_softirq_start();
23
24 restart:
25 /* Reset the pending bitmask before enabling irqs */
26 set_softirq_pending(0);
27
28 local_irq_enable();
29
30 h = softirq_vec;
31
32 while ((softirq_bit = ffs(pending))) {
33 unsigned int vec_nr;
34 int prev_count;
35
36 h += softirq_bit - 1;
37
38 vec_nr = h - softirq_vec;
39 prev_count = preempt_count();
40
41 kstat_incr_softirqs_this_cpu(vec_nr);
42
43 trace_softirq_entry(vec_nr);
44 h->action(h);
45 trace_softirq_exit(vec_nr);
46 if (unlikely(prev_count != preempt_count())) {
47 pr_err("huh, entered softirq %u %s %p with preempt_count %08x, exited with %08x?
",
48 vec_nr, softirq_to_name[vec_nr], h->action,
49 prev_count, preempt_count());
50 preempt_count_set(prev_count);
51 }
52 h++;
53 pending >>= softirq_bit;
54 }
55
56 rcu_bh_qs(smp_processor_id());
57 local_irq_disable();
58
59 pending = local_softirq_pending();
60 if (pending) {
61 if (time_before(jiffies, end) && !need_resched() &&
62 --max_restart)
63 goto restart;
64
65 wakeup_softirqd();
66 }
67
68 lockdep_softirq_end(in_hardirq);
69 account_irq_exit_time(current);
70 __local_bh_enable(SOFTIRQ_OFFSET);
71 WARN_ON_ONCE(in_interrupt());
72 tsk_restore_flags(current, old_flags, PF_MEMALLOC);
73 }
이 함수 에서 순환 호출 된 모든 활성 화 된 소프트 인 터 럽 트 함수 입 니 다.제5 행 MAXSOFTIRQ_RESTART 값 은 10 으로 최대 10 회 순환 (다른 프로 세 스 를 오래 기다 리 게 할 수 없 음), 32 번 째 줄 은 pending 표 에서 첫 번 째 로 설 정 된 비트 위 치 를 가 져 오고 44 번 째 줄 은 설 정 된 소프트 인 터 럽 트 함 수 를 실행 하기 시작 합 니 다.53 번 째 줄 은 pending 에 대해 오른쪽 이동 연산 을 한 다음 다음 순환 에 들 어 갑 니 다.이번 라운드 에 설 치 된 소프트 인 터 럽 트 함 수 를 모두 실행 하고 순환 을 종료 합 니 다.59 번 째 줄 은 로 컬 cpu 의 소프트 인 터 럽 트 마스크 를 다시 가 져 옵 니 다. 61 번 째 줄 은 end 를 초과 하지 않 았 고 더 높 은 우선 순위 의 프로 세 스 가 나타 나 지 않 았 으 며 10 번 의 링 을 다 사용 하지 않 았 다 면 restart 로 돌아 가 다시 for 순환 합 니 다.그렇지 않 으 면 65 번 째 줄 에서 softirqd 커 널 스 레 드 를 깨 웁 니 다.그리고 이 함 수 를 종료 합 니 다.
이로써 소프트 인 터 럽 트 의 처리 과정 은 분석 이 끝났다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
자바 클래스 상용 방법 분석Class 클래스 는 자바 에서 클래스 정 보 를 저장 하 는 인 스 턴 스 입 니 다.그 안에 각종 반사 방법 이 있 는데 이미 가지 고 있 는 정 보 를 파악 하고 그것 을 익히 면 우리 의 일상적인 반사 프로 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.