장치 드라이버와 커널 프로그래밍을 배우고 있습니다. Jonathan Corbet의 책에 따르면 main()
장치 드라이버 에는 기능 이 없습니다 .
그래서 두 가지 질문이 있습니다.
- 왜
main()
장치 드라이버에 기능이 필요하지 않습니까? - 커널 자체에
main()
기능이 있습니까?
누군가 나에게 이것을 설명 할 수 있습니까?
답변
사용자 공간 프로그램 에서 바이너리가 실행될 때 libc 초기화 코드에 의해 호출되는main()
프로그램의 진입 점 입니다. libc 자체는 메모리 할당, I / O, 프로세스 관리 등을 위해 커널 syscall 인터페이스에 의존하므로 커널 코드에는 libc에 의존 할 수있는 사치가 없습니다.
즉, main()
커널 코드에서 와 동등한 것은 커널 이미지를로드 한 후 부트 로더start_kernel()
가 호출하여 이를 이미지 압축을 풀고 필수 하드웨어 및 메모리 페이징을 설정합니다. start_kernel()
대부분의 시스템 설정을 수행하고 결국 init 프로세스를 생성합니다.
Linux 커널 모듈의 진입 점은 module_init()
매크로 를 호출하여 커널에 등록 된 초기화 기능입니다 . 등록 된 모듈 init 함수는 커널 시작 중에 함수를 통해 커널 코드에 의해 호출됩니다do_initcalls()
.
답변
커널에는 main
기능 이 없습니다 . main
C 언어의 개념입니다. 커널은 C와 어셈블리로 작성됩니다. 커널의 엔트리 코드는 어셈블리에 의해 작성됩니다.
부팅 순서는 다음과 같이 구성됩니다.
- BIOS는 일반적으로 부팅 블록 장치에서 부팅 로더를로드합니다. 현재 인기있는 부트 로더는 grub입니다.
- Grub은 초기 루트 장치 (
initrd
) 로 커널 이미지를 램에로드합니다 . 그런 다음 일부 주소의 코드가 실행됩니다. - 커널 이미지에는 파일 시스템 모듈, 장치 드라이버와 같은 일부 커널 모듈이 있습니다. 커널 이미지는 파일 시스템 모듈을 사용하여 루트 파일 시스템을 마운트합니다. 이제 커널은 디스크에서 모든 커널 모듈을로드하고 실행할 수 있습니다.
- 커널은 초기화 작업을 실행합니다. 예 : PCI 버스를 통과하고 모든 PCI 장치를 찾고 모든 장치 드라이버를 초기화하십시오.
- 마지막으로 커널은 프로세스 0과 프로세스 1 (
init
프로세스)을 작성하고 CPU 컨텍스트를 링 0에서 링 3으로 전환 한 다음 초기화 프로세스를 시작합니다 (프로세스 ID는 1 임). 이제 커널 부팅이 완료되었습니다! init
프로그램은 모두 초기화 스크립트를 실행합니다. 모든 서비스가 시작되었습니다. 쉘이 호출됩니다. 사용자는 로그인 할 수 있습니다.
main
함수 C의 함수이다. 실제로 주된 방법은 C 프로그램의 진입 점이 아닙니다. C 런타임은 전에 많은 함수를 호출합니다 main
. GCC에는 확장 기능인 생성자가 있습니다. “생성자”로 선언 된 함수가 전에 호출 main
됩니다.
예를 들면 다음과 같습니다.
/* This should not be used directly. Use block_init etc. instead. */
#define module_init(function, type) \
static void _attribute__((constructor)) do_qemu_init ## function(void) { \
register_module_init(function, type); \
}
이 매크로는 qemu 프로젝트에서 가져온 것입니다.
답변
예를 들어 arch / x86 / boot / main.c 에는 시스템을 실제 모드에서 보호 모드로 전환하도록 준비하기위한 main () 함수가 있지만 다른 아키텍처에는 그러한 코드가 없습니다. x86 플랫폼에서 Linux 커널 2.6.x 부팅이 작동하는 방법에 대한 좋은 개요 가 있습니다. 정말 읽을 가치가 있습니다.
하우투 리눅스 커널 개발 문서에 따르면 리눅스 커널은
표준 C 라이브러리에 의존하지 않는 독립형 C 환경이므로 C 표준의 일부는 지원되지 않습니다.
C 표준 BTW에 따르면
‘주’기능을 정의하기 위해 독립 환경의 프로그램이 필요한지 여부는 구현 정의입니다.