Thread

리눅스

목록 보기
5/8

Thread의 일반적인 개념

  • Thread는 CPU utilization의 기본 단위로, program counter, stack, thread ID로 구성된다.

  • Thread는 process 내부에서 실행되는 단위이다.

    • 하나의 process는 여러 개의 thread를 가질 수 있다.

Thread는 process 안에서 실제로 CPU 위에서 실행되는 최소 실행 단위이다.


왜 Multithreading을 사용하는가?

  • Thread는 lightweight process라고도 불린다.

  • 하나의 process를 여러 thread로 나누어 parallelism을 달성하기 위함이다.

    • browser에서는 여러 tab을 서로 다른 thread로 관리할 수 있다.
    • MS Word는 여러 thread를 사용한다.
      (예: 한 thread는 text formatting, 다른 thread는 input 처리)

Thread의 일반적인 개념

  • Thread는 같은 program에 속한 동시 실행 흐름(concurrent flows of execution)이다.
  • 같은 process에 속한 thread들은 같은 address space를 공유한다.

Creating Thread in User-level

새로운 Thread 생성

pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg)

  • 호출한 process 안에서 새로운 thread를 생성한다.
  • 새 thread는 start_routine() 함수를 실행하며 시작한다.
  • argstart_routine()의 인자로 전달된다.

종료된 Thread와 Join

pthread_join(pthread_t thread, void **retval)

  • 해당 thread가 종료될 때까지 대기한다.

  • pthread_join()이 성공하면, thread에 할당된 자원이 정리된다.

  • join에 실패하면 zombie thread가 발생할 수 있다.

    • zombie thread는 일부 system resource를 소비한다.
  • Linux kernel은 user-level thread를 생성하기 위해 내부적으로 clone() system call을 사용한다.


User-level Thread Example

기본 개념

  • pthread_create()로 thread 생성

  • pthread_t

    • thread ID를 나타내는 타입
  • pthread_self()

    • 현재 thread의 ID를 반환하는 함수

  • pthread_create()2개의 child thread를 생성한다.
  • 각 child thread는 tid_print 함수를 실행한다.
  • parent thread도 동일하게 tid_print 함수를 호출한다.
  • pthread_join()을 통해 모든 child thread가 종료될 때까지 대기한다.

tid_print 함수

  • 전달받은 thread 이름을 출력한다.
  • getpid()process ID(pid) 를 얻는다.
  • pthread_self()thread ID(tid) 를 얻는다.
  • thread 이름, pid, tid를 출력한다.

실행 결과 해석

[child_thread]  pid: 94247  tid: fbf45700
[parent_thread] pid: 94247  tid: fbf46740
[child_thread]  pid: 94247  tid: fb744700
  • 모든 thread의 pid는 동일 → 같은 process에 속함
  • 각 thread의 tid는 서로 다름 → 서로 다른 thread

Creating Thread in Kernel-level

Kernel Thread

  • Kernel thread는 kernel 내부에서 background 작업을 수행하는 thread이다.

  • 주로 daemon 형태로 동작한다.

  • 예:

    • kswapd
    • journald

kswapd

  • 평소에는 sleep 상태로 대기한다.
  • free memory 양이 low watermark(pages_low) 아래로 내려가면 깨어난다.
  • high watermark에 도달할 때까지 page reclaim을 수행한다.

journald

  • file system의 crash consistency를 보장하기 위해
    journaling 작업을 수행한다.

User-level Thread와의 관계

  • kernel thread는 user-level thread와 매우 유사하다.
  • 각 thread는 kernel scheduler가 관리하는 schedulable entity이다.

Kernel Thread 생성

  • kernel thread를 생성하려면 kthread_create()를 사용한다.

Kthread APIs

생성 API

  • kthread_create(threadfn, data, namefmt, arg...)

    • kernel thread를 생성한다.
  • kthread_run(threadfn, data, namefmt, ...)

    • kernel thread를 생성하고 즉시 실행한다.

종료 API

  • kthread_stop(struct task_struct *k)

    • kernel thread를 종료한다.
  • kthread_should_stop()

    • thread가 계속 실행할지, 종료할지를 판단한다.

Example of Kernel Thread in Kernel Code

EXT4 File System 예제

  • EXT4 file system은 background에서 journaling 작업을 수행하기 위해 kernel thread를 사용한다.

  • kthread_run()으로 journaling kernel thread를 생성한다.
  • thread 생성에 실패하면 error를 반환한다.
  • commit 작업이 완료될 때까지 대기한다.

EXT4 File System – Lazy Initialization

  • lazyinit 기능은 file system 생성 속도를 크게 향상시킨다.

  • 이유:

    • 모든 inode table을 즉시 초기화하지 않고
    • 초기 mount 이후 background에서 점진적으로 초기화하기 때문이다.

코드 동작

  • kthread_run(ext4_lazyinit_thread, ...)

    • lazyinit kernel thread 생성
  • kthread_should_stop()

    • thread 종료 여부 확인
  • kthread_stop(ext4_lazyinit_task)

    • kernel thread 종료
  • module 종료 시 ext4_destroy_lazyinit_thread()로 정리한다.


How to Make a Kernel Thread

Makefile 예제

  • kernel module용 Makefile을 작성한다.
  • $ make로 빌드한다.
  • $ make clean으로 정리한다.

Kernel Thread Module 예제

  • kernel module에서 kernel thread를 생성하는 예제이다.

  • test_thread()

    • 전달받은 argument를 출력하고 종료한다.
  • thread_create()

    • 10개의 kernel thread를 생성한다.
  • kthread_module_init()

    • module load 시 호출되며 kernel thread를 생성한다.
  • kthread_module_cleanup()

    • module unload 시 호출된다.

실행 방법

$ make
$ insmod kthread_module.ko
$ dmesg
$ rmmod kthread_module

실행 결과

  • 각 kernel thread가 전달받은 argument 값을 출력한다.
  • module load 시 "Hello Module" 메시지가 출력된다.

반복 실행 Kernel Thread 예제

  • MyThread

    • 생성된 kernel thread를 가리킨다.
  • MyPrintk()

    • kthread_should_stop()이 호출되기 전까지
    • 10초마다 문자열을 출력한다.
  • init_kthread()

    • kthread_run()으로 kernel thread를 생성한다.
  • exit_kthread()

    • kthread_stop()으로 kernel thread를 종료한다.

핵심 정리

kthread_stop()이 호출되기 전까지 kernel thread는 계속 실행된다

0개의 댓글