sigaction(7): siginfo_t의 si_code 멤버의 의미 체계

sigaction(7): siginfo_t의 si_code 멤버의 의미 체계

신호 11(세그먼트 위반)에서 자주 종료되는 장기 실행 프로그램(daemon(3) 호출을 통해 데몬화됨)이 있습니다. 이유는 모르겠습니다. 따라서 sigaction()시스템 호출을 사용하여 설정하는 SIGSEGV 핸들러를 작성했습니다. 다음과 같은 프로토타입을 갖도록 핸들러 함수를 설정했습니다. 이는 형식 매개변수로 구조에 대한 포인터를 void (*sa_sigaction)(int, siginfo_t *, void *)얻는다는 의미입니다 .siginfo_t

신비한 SIGSEGV가 발생하면 si_code요소 siginfo_t값은 0x80입니다. sigaction 매뉴얼 페이지에 따르면 이는 "커널"이 신호를 보냈다는 것을 의미합니다. 이는 Red Hat RHEL 시스템에 있습니다.Linux blahblah 2.6.18-308.20.1.el5 #1 SMP Tue Nov 6 04:38:29 EST 2012 x86_64 x86_64 x86_64 GNU/Linux

커널이 SIGSEGV를 보내는 이유는 무엇입니까? 이것은 유명한 OOM-Killer에서 나온 것입니까, 아니면 SIGSEGV를 얻는 다른 이유가 있습니까? 이 시스템의 일반 사용자로서 나는 그것을 볼 수 없으며 /var/log/message시스템 관리자는 아마도 Windows 배경에서 왔기 때문에 약간 냉담합니다.

의도적으로 생성된 SIGSEGV(NULL 포인터 역참조)는 si_code0x80 값을 얻지 않고 "주소가 개체에 매핑되지 않음"을 의미하는 0x1 값을 얻습니다.

답변1

si_code = SI_KERNEL문서화되지 않은 with의 의미는 si_errno = 0다음과 같습니다.

  1. 프로세서별 트랩
  2. 커널 세그먼트 메모리 위반(세마포어 액세스 제외)
  3. ELF 파일 형식 위반
  4. 스택 위반.

다른 모든 은 0이 아닌 값으로 SIGSEGV설정되어야 합니다 . si_errno자세한 내용을 알아보려면 계속 읽어보세요.

커널은 사용자 공간 프로세스를 설정할 때 프로세스에 대한 가상 메모리 페이지 테이블을 정의합니다. 커널 스케줄러는 프로세스를 실행할 때 프로세스의 페이지 테이블을 기반으로 CPU의 메모리 관리 장치(MMU)를 재구성합니다.

사용자 공간 프로세스가 페이지 테이블 외부의 메모리에 액세스하려고 시도하면 CPU MMU가 이 위반을 감지하고 예외를 생성합니다. 이런 일이 발생하니 참고하세요하드웨어등급. 커널은 아직 다루어지지 않았습니다.

커널은 MMU 예외를 처리하도록 구성되었습니다. 페이지 테이블 외부의 메모리에 액세스하려고 시도하는 실행 중인 프로세스로 인해 발생한 예외를 포착합니다. 그런 다음 커널은 do_page_fault()이를 호출하여 SIGSEGV 신호를 프로세스에 보냅니다. 이것이 바로 신호가 프로세스 자체나 다른 프로세스에서 나오는 것이 아니라 커널에서 나오는 이유입니다.

물론 이것은 매우 단순화된 설명이다. 내가 본 가장 간단한 설명은 William Gatliff의 훌륭한 기사의 "페이지 오류" 섹션에 있습니다.Linux 커널 메모리 관리 장치 API.

Blackfin MPU와 같이 MMU가 없는 CPU에서는 Linux 사용자 공간 프로세스가 일반적으로 액세스할 수 있습니다.어느메모리. 즉, 메모리 위반에 대한 SIGSEGV 신호가 없으며(스택 오버플로와 같은 트랩에만 해당) 메모리 액세스 문제를 디버깅하는 것이 까다로울 수 있습니다.

나는 ulimit코어 파일을 설정하고 확인하는 것에 대한 jordanm의 의견 에 동의합니다 gdb. 셸에서 프로세스를 실행하는 경우 명령줄에서 작업을 수행하거나 ulimit -c unlimited프로그램에서 libc setrlimit시스템 호출 래퍼( )를 사용할 수 있습니다. man setrlimitin file 을 통해 코어 파일의 이름과 위치를 설정할 수 있습니다 /proc/sys/kernel/core_pattern. 이에 대한 AP Lawrence의 훌륭한 설명을 참조하십시오.제어 코어 파일(Linux). 코어파일에서 사용 하려면 gdb이 작은 콘텐츠를 참조하세요.지도 시간steve.org에서

SEGV_MAPERR(0x1)에 대한 분할 위반은 si_code널 포인터 역참조, 존재하지 않는 메모리(예: 0xfffffc0000004000) 액세스 또는 malloc기타 free문제일 수 있습니다. man getrlimit힙이 손상되거나 프로세스가 런타임 제한을 초과하는 경우 malloc, 이중 해제 또는 할당되지 않은 주소 해제의 경우 free. 더 많은 단서를 보려면 이 요소를 확인하세요 si_errno.

TASK_SIZE한도를 초과하는 가상 메모리에 액세스하는 사용자 공간 프로세스로 인해 발생하는 분할 위반으로 인해 분할 si_code위반이 발생합니다 SI_KERNEL. 즉, TASK_SIZE제한은 모든 프로세스가 액세스할 수 있는 가장 높은 가상 주소입니다. 커널이 높은 메모리 지원을 위해 구성되지 않은 경우 일반적으로 3GB입니다. 한계 위의 영역을 TASK_SIZE"커널 세그먼트"라고 합니다. linux-2.6//arch/x86/mm/fault.c:__bad_area_nosemaphore(...)그것이 어디에 있는지 보십시오 force_sig_info_fault(...).

각 아키텍처에는 SIEGV로 이어지는 여러 가지 특정 함정이 있습니다 SI_KERNEL. x86의 경우 linux-2.6//arch/x86/kernel/traps.c.

linux-2.6//mm/oom_kill.c:oom_kill_process(...)OOM 핸들러는 함수의 라인 498 주위에 표시된 것처럼 SIGSEGV 대신 SIGKILL을 보냅니다.

do_send_sig_info(SIGKILL, SEND_SIG_FORCED, p, true);

관련 프로세스 및 라인 503의 경우:

do_send_sig_info(SIGKILL, SEND_SIG_FORCED, victim, true);

이 프로세스는 OOM의 가장 직접적인 원인입니다.

wait상위 프로세스에서 종료된 프로세스의 상태를 확인하거나 dmesg커널 로그를 구성하고 확인하여 더 많은 정보를 얻을 수 있습니다 .

관련 정보