
소스를 살펴보면strace
CLONE_IDLETASK
나는 다음과 같이 설명된 복제 플래그의 사용을 발견했습니다 .
#define CLONE_IDLETASK 0x00001000 /* kernel-only flag */
자세히 살펴본 후 해당 플래그는 다루지 않았지만 man clone
실제로 부팅 프로세스 중에 커널이 머신의 각 CPU에 대해 유휴 프로세스(모두 PID 0을 가져야 함)를 생성하는 데 사용된다는 사실을 발견했습니다. 즉, 8개의 CPU가 있는 머신에는 "실행 중인" 프로세스가 최소 7개(아래 질문 참조) 있습니다(인용문 참고).
이제 이는 "유휴" 프로세스가 실제로 수행하는 작업에 대한 몇 가지 질문으로 이어집니다. 내 가정은 해당 기간이 끝날 때까지 NOP 작업을 계속 실행하고 커널이 실제 프로세스를 실행하도록 할당하거나 유휴 프로세스를 다시 한 번 할당한다는 것입니다(CPU가 사용되지 않는 경우). 그러나 그것은 완전한 추측입니다. 그래서:
예를 들어 CPU가 8개 있는 시스템에서는 이러한 유휴 프로세스가 7개 생성됩니까? (사용자 공간 작업을 수행하지 않는 동안 하나의 CPU는 커널 자체에 의해 유지됩니까?)
유휴 프로세스는 실제로 NOP 작업의 무한한 스트림에 불과합니까? (또는 동일한 작업을 수행하는 루프).
CPU 사용량(가령
uptime
)은 유휴 프로세스가 CPU에 있었던 시간과 특정 기간 동안 CPU에 없었던 시간으로 간단히 계산됩니까?
추신: 이 질문의 대부분은 제가 CPU 작동 방식을 완전히 이해하지 못하기 때문에 발생하는 것 같습니다. 즉, 어셈블리, 기간 및 인터럽트를 이해하지만 예를 들어 CPU가 실행 중인 작업에 따라 에너지를 더 많이 또는 더 적게 사용할 수 있는지는 알 수 없습니다. 누군가 나에게도 그 점을 알려줄 수 있다면 감사하겠습니다.
답변1
유휴 작업은 프로세스 계산 및 에너지 소비 감소에 사용됩니다. Linux에서는 모든 프로세서에 대해 하나의 유휴 작업이 생성되고 해당 프로세서에 고정됩니다. 해당 CPU에서 실행할 다른 프로세스가 없을 때마다 유휴 작업이 예약됩니다. 유휴 작업에 소요된 시간은 와 같은 도구에서 "유휴" 시간으로 표시됩니다 top
. (가동시간은 다르게 계산됩니다.)
유닉스는 항상 일종의 유휴 루프를 갖고 있었던 것 같습니다(그러나 반드시 실제 유휴 작업일 필요는 없습니다.질의 답변), 심지어 V1에서도그것은 WAIT
지시 를 사용했습니다인터럽트가 발생할 때까지 프로세서를 중지했습니다(“인터럽트 대기”를 나타냄). 일부 다른 운영 체제에서는 사용 중 루프, DOS,운영체제/2, 특히 초기 버전의 Windows. 꽤 오랫동안 CPU는 에너지 소비와 열 발생을 줄이기 위해 이러한 종류의 "대기" 명령을 사용해 왔습니다. 예를 들어 유휴 작업의 다양한 구현을 볼 수 있습니다.arch/x86/kernel/process.c
Linux 커널에서: 기본 커널은 다음을 호출합니다.HLT
, 인터럽트가 발생할 때까지 프로세서를 중지하고 C1 에너지 절약 모드를 활성화하는 반면, 다른 구현에서는 다양한 버그나 비효율성을 처리합니다(예를 들어MWAIT
일부 CPU 대신 사용 HLT
).
이 모든 것은 이벤트(I/O 등)를 기다리는 프로세스의 유휴 상태와 완전히 별개입니다.
답변2
프로세스 스케줄러의 교과서 설계에서 스케줄러에 예약할 프로세스가 없으면(즉, 모든 프로세스가 차단되어 입력을 기다리는 경우) 스케줄러는 프로세서 인터럽트를 기다립니다. 인터럽트는 주변 장치로부터의 입력(사용자 작업, 네트워크 패킷, 디스크 읽기 완료 등)을 나타내거나 프로세스에서 타이머를 트리거하는 타이머 인터럽트일 수 있습니다.
Linux의 스케줄러에는 할 일이 없는 경우를 위한 특수 코드가 없습니다. 대신, 할 일이 없는 경우를 특별한 프로세스인 유휴 프로세스로 인코딩합니다. 유휴 프로세스는 다른 프로세스를 예약할 수 없을 때만 예약됩니다(실질적으로 우선순위가 무한히 낮습니다). 유휴 프로세스는 실제로 커널의 일부입니다. 즉, 프로세스의 코드가 아니라 커널에서 코드를 실행하는 스레드인 커널 스레드입니다. (보다 정확하게는 각 CPU마다 하나의 스레드가 있습니다.) 유휴 프로세스가 실행되면 인터럽트 대기 작업을 수행합니다.
인터럽트 대기 작동 방식은 프로세서의 기능에 따라 다릅니다. 가장 기본적인 프로세서 설계에서는 바쁜 루프에 불과합니다.
nothing:
goto nothing
프로세서는 분기 명령을 계속해서 실행하지만 아무 것도 수행하지 않습니다. 대부분의 최신 OS는 더 나은 것이 없고 대부분의 프로세서에 더 나은 것이 있는 프로세서에서 실행되지 않는 한 이 작업을 수행하지 않습니다. 방을 난방하는 것 외에 아무것도 하지 않고 에너지를 낭비하는 것보다 이상적으로는 프로세서를 꺼야 합니다. 따라서 커널은 프로세서가 스스로 끄거나 적어도 대부분의 프로세서를 끄도록 지시하는 코드를 실행합니다. 전원이 켜져 있는 작은 부분, 즉 인터럽트 컨트롤러가 하나 이상 있어야 합니다. 주변 장치가 인터럽트를 트리거하면 인터럽트 컨트롤러는 프로세서의 주(일부)에 웨이크업 신호를 보냅니다.
실제로 Intel/AMD 및 ARM과 같은 최신 CPU에는 복잡한 전원 관리 설정이 많이 있습니다. OS는 프로세서가 유휴 모드에 머무는 시간을 예측할 수 있으며 이에 따라 다양한 저전력 모드를 선택합니다. 모드는 유휴 상태의 전력 사용량과 유휴 모드를 시작하고 종료하는 데 걸리는 시간 간에 서로 다른 절충안을 제공합니다. 일부 프로세서에서는 프로세스가 CPU 시간을 많이 소비하지 않는 것으로 확인되면 OS가 프로세서의 클럭 속도를 낮출 수도 있습니다.
답변3
아니요. 유휴 작업은 CPU 주기를 낭비하지 않습니다. 스케줄러는 실행을 위해 유휴 프로세스를 선택하지 않습니다. 유휴 프로세스는 계속될 수 있도록 일부 이벤트가 발생하기를 기다리고 있습니다. 예를 들어 시스템 호출에서 입력을 기다리고 있을 수 있습니다 read()
.
그런데 커널은 별도의 프로세스가 아닙니다. 커널 코드는 항상 프로세스의 컨텍스트에서 실행되므로(커널 스레드의 특별한 경우는 제외) "사용자 공간 작업을 수행하지 않는 동안 하나의 CPU가 커널 자체에 의해 유지됩니다"라고 말하는 것은 올바르지 않습니다.