소스를 봐strace
CLONE_IDLETASK
다음과 같이 설명된 clone 플래그의 사용을 발견했습니다 .
#define CLONE_IDLETASK 0x00001000 /* kernel-only flag */
더 깊이 파고들어 이 플래그가 다루어지지 않았지만 man clone
부팅 중에 커널이 실제로 머신의 각 CPU에 대한 유휴 프로세스를 생성하는 데 사용된다는 사실을 발견했습니다(모두 PID가 0이어야 함). 즉, 8개의 CPU가 있는 시스템에는 이러한 프로세스가 "실행 중"(인용부호 참고) 이상 7개(아래 질문 참조)가 있습니다.
이제 "유휴" 프로세스가 실제로 수행하는 작업에 대해 몇 가지 질문이 제기됩니다. 내 가정은 시간 범위가 끝날 때까지 계속해서 NOP 작업을 수행하고 커널이 실행할 실제 프로세스를 할당하거나 (CPU가 사용되지 않는 경우) 유휴 프로세스를 다시 할당한다는 것입니다. 그러나 이것은 전적으로 추측입니다. 그래서:
8개의 CPU가 있는 시스템에서 이러한 유휴 프로세스가 7개 생성됩니까? (그리고 하나의 CPU는 사용자 공간 작업을 수행하지 않는 동안 커널 자체가 차지하게 될까요?)
유휴 프로세스는 실제로 NOP 작업의 무한한 흐름에 불과합니까? (또는 동일한 작업을 수행하는 루프).
CPU 사용량(예:
uptime
)은 단순히 CPU에서 유휴 프로세스가 실행된 시간과 특정 기간 동안 유휴 프로세스가 존재하지 않은 시간으로 계산됩니까?
PS 이 문제는 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
프로세서는 분기 명령을 영원히 실행하고 아무 작업도 수행하지 않습니다. 대부분의 최신 운영 체제는 더 나은 기능이 없고 대부분의 프로세서에 더 나은 기능이 있는 프로세서에서 실행되지 않는 한 이 작업을 수행하지 않습니다. 이상적으로는 방을 가열하는 것 외에는 아무것도 하지 않고 프로세서를 종료해야 합니다. 따라서 커널은 프로세서에 자체 종료를 지시하거나 적어도 대부분의 프로세서를 종료하도록 코드를 실행합니다. 최소한 작은 부품에는 전원이 계속 공급되어야 합니다. 즉, 컨트롤러를 중단해야 합니다. 주변 장치가 인터럽트를 트리거하면 인터럽트 컨트롤러는 메인(부분) 프로세서에 웨이크업 신호를 보냅니다.
실제로 Intel/AMD 및 ARM과 같은 최신 CPU에는 복잡한 전원 관리 설정이 많이 있습니다. 운영 체제는 프로세서가 유휴 모드로 유지되는 시간을 추정하고 이를 기반으로 다른 저전력 모드를 선택할 수 있습니다. 이러한 모드는 유휴 상태에서의 전력 소비와 유휴 모드를 시작하고 종료하는 데 필요한 시간 간에 서로 다른 절충안을 제공합니다. 일부 프로세서에서는 운영 체제가 프로세스가 너무 많은 CPU 시간을 소비하지 않는 것을 발견하면 프로세서의 클럭 속도를 줄일 수도 있습니다.
답변3
아니요, 유휴 작업은 CPU 주기를 낭비하지 않습니다. 스케줄러는 실행을 위해 유휴 프로세스를 선택하지 않습니다. 유휴 프로세스가 계속될 수 있도록 일부 이벤트가 발생하기를 기다리고 있습니다. 예를 들어 read()
시스템 호출에서 입력을 기다릴 수 있습니다 .
그런데 커널은 별도의 프로세스가 아닙니다. 커널 코드는 항상 프로세스의 컨텍스트에서 실행되므로(물론 커널 스레드의 특별한 경우는 제외) "사용자 공간 작업을 수행하지 않는 동안 하나의 CPU는 커널 자체에 의해 점유됩니다"라는 설명은 올바르지 않습니다.