Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

43111
637
415419


[리눅스커널][스케줄링] 선점 스케줄링 진입점은 어디인가? 10. 프로세스 스케줄링

여기서 중요한 질문을 던질 수 있습니다. 과연 "선점은 언제 일어날까?"란 의문입니다.
선점 스케줄링은 언제든 발생할 수 있습니다.

소스 코드를 보면서 선점 스케줄링이 언제 발생할 수 있는지 생각해 봅시다.
[https://elixir.bootlin.com/linux/v4.14.70/source/fs/configfs/file.c]
1 static ssize_t
2 configfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
3 {
4 struct configfs_buffer * buffer = file->private_data;
5 ssize_t len;
6
7 mutex_lock(&buffer->mutex);
8 len = fill_write_buffer(buffer, buf, count);
9 if (len > 0)
10 len = flush_write_buffer(file->f_path.dentry, buffer, len);
11 if (len > 0)
12 *ppos += len;
13 mutex_unlock(&buffer->mutex);
14 return len;
15 }

위에서 볼 수 있는 configfs_write_file() 함수 코드는 4~13 번째 줄입니다. 이 구간 코드 실행 도중 언제든 선점 스케줄링이 일어날 수 있습니다. 예를 들면 12 번째 줄 코드를 실행하다 코드 실행을 중단하고 다른 프로세스가 실행할 수 있다는 것입니다.

여러분이 작성한 디바이스 드라이버 코드도 마찬가지입니다. 어느 코드를 실행하던 선점될 수 있습니다. 이 점을 염두하고 코드를 작성할 필요가 있습니다.


만약 7~13 번째 줄 코드가 실행할 때 선점 스케줄링이 되면 안 되는 조건이라고 가정합시다. 그러면 어떻게 하면 선점 스케줄링이 일어나지 않도록 할 수 있을까요?

다음 7 번째와 15 번째 코드와 같이 preempt_disable() 함수와 preempt_enable() 함수를 호출하면 됩니다.
[https://elixir.bootlin.com/linux/v4.14.70/source/fs/configfs/file.c]
1 static ssize_t
2 configfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
3 {
4 struct configfs_buffer * buffer = file->private_data;
5 ssize_t len;
6
7 + preempt_disable();
8 mutex_lock(&buffer->mutex);
9 len = fill_write_buffer(buffer, buf, count);
10 if (len > 0)
11 len = flush_write_buffer(file->f_path.dentry, buffer, len);
12 if (len > 0)
13 *ppos += len;
14 mutex_unlock(&buffer->mutex);
15 +    preempt_enable();
16 return len;
17 }

선점 스케줄링이 발생하면 안 되는 코드 구간을 preempt_disable() 함수와 preempt_enable() 함수로 감쏴주는 것입니다. preempt_disable() 함수는 선점 스케줄링을 지연하고 preempt_enable() 함수는 선점 스케줄링을 할 수 있도록 설정합니다. |

위에서 필자는 과연 "선점 스케줄링은 언제든 일어날 수 있다."고 설명을 드렸습니다.
이 대답은 어떻게 보면 맞고 틀릴 수 있습니다. 사실, 선점 스케줄링을 1초에 사실 수 백번 이상 시도하므로 선점 스케줄링은 어느 때나 발생할 수 있다고 볼 수 있습니다.
 
그러면 리눅스 커널은 언제 선점 스케줄링을 시작할까요?
선점 스케줄링 실행 진입점은 다음과 같이 정해져 있습니다.
1. 인터럽트 핸들링 후
  : 인터럽트 핸들러를 실행한 후 실행을 멈춘 프로세스로 복귀 하기 전
2. 시스템 콜 핸들링 후
  : 시스템 콜 함수를 처리한 후 유저 공간으로 복귀하기 직전

선점 스케줄링은 2가지 상황에서만 시작합니다.

우리는 그 동안 schedule() 함수를 호출했을때만 스케줄링이 실행하는지 알고 있습니다. 하지만 인터럽트가 발생했을 때 선점 스케줄링이 시작합니다.

| 인터럽트란 비동기적인 전기 신호로 볼 수도 있는데 소프트웨어 관점으로 보면 비동기적인 이벤트라고 볼 수 있습니다. 여러분들은 모두 휴대폰을 갖고 있을 겁니다. 언제 휴대폰으로 문자나 전화라 올 지 모릅니다. 이와 비슷한 상황을 인터럽트라고 말할 수 있습니다. |


"혹시 궁금한 점이 있으면 댓글로 질문 남겨주세요. 아는 한 성실히 답변 올려드리겠습니다!" 

Thanks,
Austin Kim(austindh.kim@gmail.com)

Reference(프로세스 스케줄링)

스케줄링 소개
프로세스 상태 관리
   어떤 함수가 프로세스 상태를 바꿀까?
스케줄러 클래스
런큐
CFS 스케줄러
   CFS 관련 세부 함수 분석  
선점 스케줄링(Preemptive Scheduling)   
프로세스는 어떻게 깨울까?
스케줄링 핵심 schedule() 함수 분석
컨택스트 스위칭
스케줄링 디버깅
   스케줄링 프로파일링
     CPU에 부하를 주는 테스트   
     CPU에 부하를 주지 않는 테스트 


# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2



 



핑백

덧글

댓글 입력 영역