Linux Kernel(4.19) Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

230224
1178
109352


[리눅스커널] 워크큐: 워커 스레드는 누가 언제 만들까 8. Workqueue

이번 챕터 앞 부분에서 워크큐에 대해 다음과 같이 소개했습니다. 

    워크를 처리하는 워커 스레드를 미리 생성해 놓고 워크 실행 요청이 오면 해당 워커 
    스레드가 이를 처리한다.

이번 시간에는 워커 스레드의 핸들인 워커를 언제 생성하는지 알아보겠습니다. 그렇다면 워커는 어느 함수를 실행할 때 생성할까요? 

    워커는 create_worker() 함수를 호출할 때 생성합니다. 
   
워커를 생성하는 create_worker() 함수를 분석하기 전 이 함수를 호출하는 경로를 알아보겠습니다. 
maybe_create_worker() 
get_unbound_pool() 
workqueue_prepare_cpu()

커널 내부에서 워크를 사용해 후반부 처리를 하므로 커널은 워커 스레드를 미리 생성해 놓습니다. 

그런데 리눅스 시스템에서 여러 드라이버에서 워크를 평소보다 아주 많이 큐잉할 수 있습니다. 이 조건에서 추가로 워크를 처리하기 위해 create_worker() 함수를 호출해 워커 스레드를 생성해야 합니다. 

기본으로 부팅 과정에서 워크큐 자료구조를 초기화할 때 워커 스레드를 생성합니다. 우선 이 코드부터 분석해 봅시다.

부팅 과정에서 워커 스레드를 만드는 동작 살펴보기

워커 스레드는 부팅 과정에서 만듭니다. 이 동작은 workqueue_init() 함수에서 볼 수 있습니다. 
[https://elixir.bootlin.com/linux/v4.19.30/source/kernel/workqueue.c]
1 int __init workqueue_init(void)
2 {
3 struct workqueue_struct *wq;
4 struct worker_pool *pool;
5 int cpu, bkt;
6
7 wq_numa_init();
8
9 mutex_lock(&wq_pool_mutex);
10
...
11 /* create the initial workers */
12 for_each_online_cpu(cpu) {
13 for_each_cpu_worker_pool(pool, cpu) {
14 pool->flags &= ~POOL_DISASSOCIATED;
15 BUG_ON(!create_worker(pool));
16 }
17 }

11번째 줄 코드를 보겠습니다.
12 for_each_online_cpu(cpu) {
13 for_each_cpu_worker_pool(pool, cpu) {
14 pool->flags &= ~POOL_DISASSOCIATED;
15 BUG_ON(!create_worker(pool));
16 }

각 CPU 별로 워커 풀에 접근해서 풀 노드 정보를 저장하는 코드입니다. 각 워크풀 별로 create_worker() 함수를 호출해서 워커를 생성합니다.


핑백

덧글

댓글 입력 영역