리눅스는 프로세스를 어떻게 “죽이는가”? 풍미로) 여러 번 사용하는 동안 어떻게 명령이

수십 년 동안 컴퓨터와 10 년 동안 리눅스를 전문적으로 사용해 왔지만 실제로는 OS와는 달리 마술과는 달리 블랙 박스로 취급한다고 생각합니다.

오늘 저는 그 kill명령 에 대해 생각했고 , 하루에 여러 번 ( ‘정상적인’ -9풍미 와 풍미로) 여러 번 사용하는 동안 어떻게 명령이 배후에서 작동하는지 전혀 모른다는 것을 인정해야합니다.

내 관점에서, 실행중인 프로세스가 “중지”되면 killPID를 호출 한 다음 갑자기 더 이상 실행되지 않습니다. 마법!

실제로 어떤 일이 발생합니까? 맨 페이지는 “신호”에 대해 이야기하지만 반드시 추상화 일뿐입니다. kill -9프로세스로 전송 하는 것은 신호 처리와 같은 프로세스의 협력이 필요하지 않으며 프로세스를 종료시킵니다.

  • 리눅스는 어떻게 프로세스가 CPU 시간을 계속 차지하지 못하게합니까?
  • 예약에서 제거 되었습니까?
  • 열린 파일 핸들에서 프로세스를 분리합니까?
  • 프로세스의 가상 메모리는 어떻게 릴리스됩니까?
  • 리눅스가 프로세스가 차지하는 모든 리소스에 대한 참조를 유지하는 메모리에 글로벌 테이블과 같은 것이 있습니까? 프로세스를 “킬”할 때 Linux는 단순히 해당 테이블을 통과하고 리소스를 하나씩 해제합니다.

정말 모든 것을 알고 싶습니다!



답변

프로세스에 kill -9를 전송하면 프로세스의 협력 (예 : 신호 처리)이 필요하지 않으며 프로세스를 종료합니다.

일부 신호는 포착되어 무시 될 수 있기 때문에 모두 협력이 필요하다고 가정합니다. 그러나에 따르면 man 2 signal” SIGKILL 및 SIGSTOP 신호 는 포착하거나 무시할 수 없습니다”. SIGTERM이 포착 될 수 있습니다. 이것이 평범한 kill것이 항상 효과적인 것은 아닙니다. 일반적으로 이것은 프로세스 처리기의 무언가가 잘못되었음을 의미합니다. 1

프로세스가 주어진 신호에 대한 핸들러를 정의 할 수 없거나 정의 할 수없는 경우 커널은 기본 동작을 수행합니다. SIGTERM 및 SIGKILL의 경우 프로세스가 종료됩니다 (PID가 1이 아니고 커널이 종료되지 않는 한 init) 2 파일 핸들이 닫히고 메모리가 시스템 풀로 리턴되고 상위가 SIGCHILD, 고아를 수신함을 의미합니다. 자식은 마치 호출 한 것처럼 init 등으로 상속됩니다 exit(참조 man 2 exit). 좀비로 끝나지 않는 한 프로세스는 더 이상 존재하지 않습니다.이 경우 프로세스는 여전히 커널의 프로세스 테이블에 몇 가지 정보와 함께 나열됩니다. 그것은 부모가하지 않을 때 발생wait이 정보를 올바르게 처리하십시오. 그러나 좀비 프로세스에는 더 이상 할당 된 메모리가 없으므로 계속 실행할 수 없습니다.

리눅스가 프로세스가 차지하는 모든 리소스에 대한 참조를 유지하고 프로세스를 “킬”할 때 리눅스가 단순히 해당 테이블을 통과하고 리소스를 하나씩 해제하는 전역 테이블과 같은 것이 있습니까?

나는 그것이 정확하다고 생각합니다. 실제 메모리는 페이지 (일반적으로 4KB 청크와 같은 한 페이지)별로 추적되며 해당 페이지는 전역 풀에서 가져 와서 반환됩니다. 포함 된 데이터가 다시 필요한 경우 (즉, 기존 파일에서 읽은 데이터) 사용 가능한 일부 페이지가 캐시되는 것이 조금 더 복잡합니다.

맨 페이지는 “신호”에 대해 이야기하지만 반드시 추상화 일뿐입니다.

물론 모든 신호는 추상화입니다. 그것들은 “프로세스”와 같은 개념입니다. 나는 의미론을 약간 연주하고 있지만 SIGKILL이 SIGTERM과 질적으로 다르다는 것을 의미한다면, 그렇습니다. 잡을 수 없다는 의미에서 그렇습니다. 그러나 둘 다 신호라는 의미에서는 아닙니다. 유사하게, 사과는 오렌지가 아니지만 사과와 오렌지는 선입관에 따르면 과일입니다. SIGKILL은 잡을 수 없기 때문에 추상적 인 것처럼 보이지만 여전히 신호입니다. SIGTERM 처리의 예는 다음과 같습니다.

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>

void sighandler (int signum, siginfo_t *info, void *context) {
    fprintf (
        stderr,
        "Received %d from pid %u, uid %u.\n",
        info->si_signo,
        info->si_pid,
        info->si_uid
    );
}

int main (void) {
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_sigaction = sighandler;
    sa.sa_flags = SA_SIGINFO;
    sigaction(SIGTERM, &sa, NULL);
    while (1) sleep(10);
    return 0;
}

이 과정은 영원히 잠들 것입니다. 당신은 터미널에서 그것을 실행하고 함께 SIGTERM을 보낼 수 있습니다 kill. 그것은 다음과 같은 것들을 뱉어냅니다.

Received 15 from pid 25331, uid 1066.

1066은 내 UID입니다. PID kill는 실행 되는 쉘 의 PID이거나 포크하면 킬의 PID입니다 ( kill 25309 & echo $?).

다시 말하지만 SIGKILL의 핸들러는 작동하지 않기 때문에 아무런 의미가 없습니다. 3 내가 kill -9 25309프로세스를 종료합니다. 그러나 그것은 여전히 ​​신호입니다. 커널은 누가 신호 를 보냈 는지, 어떤 종류의 신호 인지 등에 대한 정보를 가지고 있습니다 .


1. 가능한 신호 목록을 보지 않은 경우을 참조하십시오 kill -l.

2. Tim Post가 아래에 언급 한 것처럼 또 다른 예외는 무정전 수면 프로세스에 적용됩니다 . 근본적인 문제가 해결 될 때까지 깨울 수 없으므로 지속 기간 동안 모든 신호 (SIGKILL 포함)가 지연됩니다. 그러나 프로세스는 이러한 상황을 의도적으로 만들 수 없습니다.

3. 이것이 kill -9실제로 사용 하는 것이 더 좋은 것을 의미하지는 않습니다 . 내 예제 핸들러는로 이어지지 않는다는 점에서 나쁜 것입니다 exit(). SIGTERM 핸들러의 실제 목적은 프로세스에 임시 파일 정리와 같은 작업을 수행 한 다음 자발적으로 종료하는 것입니다. 를 사용 kill -9하면이 기회를 얻지 못하므로 “자발적으로 종료”한 부분이 실패한 것만 가능합니다.


답변

각 프로세스는 예약 된 시간 동안 실행 된 다음 하드웨어 타이머에 의해 중단되어 다른 작업에 CPU 코어를 제공합니다. 그렇기 때문에 CPU 코어보다 훨씬 많은 프로세스가 있거나 단일 코어 CPU에서 많은 프로세스로 모든 운영 체제를 실행할 수 있습니다.

프로세스가 중단 된 후 제어는 커널 코드로 돌아갑니다. 그런 다음 해당 코드는 프로세스 측의 협조없이 중단 된 프로세스의 실행을 재개하지 않기로 결정할 수 있습니다. kill -9는 프로그램의 모든 라인에서 실행될 수 있습니다.


답변

다음은 프로세스 종료 방법에 대한 이상적인 설명입니다. 실제로 모든 유닉스 변형에는 많은 추가 합병증과 최적화가 있습니다.

커널은 각 프로세스에 대한 데이터 구조를 가지고 있으며, 매핑하는 메모리, 가지고있는 스레드 및 예약 된 시간, 열려있는 파일 등에 대한 정보를 저장합니다. 커널이 프로세스를 종료하기로 결정한 경우 프로세스가 종료 될 프로세스의 데이터 구조 (및 각 스레드의 데이터 구조)

프로세스의 스레드 중 하나가 현재 다른 CPU에서 예약 된 경우 커널은 다른 CPU에서 인터럽트를 트리거하여 해당 스레드의 실행이 더 빨리 중지되도록 할 수 있습니다.

스케줄러가 스레드가 종료되어야하는 프로세스에 있음을 발견하면 더 이상 스케줄하지 않습니다.

프로세스의 스레드가 더 이상 예약되지 않으면 커널은 프로세스의 리소스 (메모리, 파일 설명자 등)를 해제하기 시작합니다. 커널이 리소스를 해제 할 때마다 소유자가 여전히 라이브 리소스를 가지고 있는지 확인합니다. 프로세스에 더 이상 라이브 리소스 (메모리 매핑, 열린 파일 설명자 등)가 없으면 프로세스 자체의 데이터 구조를 해제하고 해당 항목을 프로세스 테이블에서 제거 할 수 있습니다.

일부 리소스는 즉시 해제 될 수 있습니다 (예 : I / O 작업에서 사용하지 않는 메모리 할당 해제). 다른 리소스 (예 : I / O 작업이 진행되는 동안 ( DMA 가 진행 중이거나 액세스중인 메모리가 사용 중이며 DMA 를 취소하는 동안) I / O 작업을 설명하는 데이터를 해제 할 수 있어야합니다. 주변 장치에 접촉). 그러한 자원의 운전자에게 통지하고 취소를 서두르려고 시도 할 수 있습니다. 작업이 더 이상 진행되지 않으면 드라이버는 해당 리소스 해제를 완료합니다.

(프로세스 테이블의 항목은 실제로 프로세스가 종료 되고 부모가 이벤트를 승인하면 해제되는 상위 프로세스에 속하는 자원입니다 .)