저는 장치 드라이버와 커널 프로그래밍을 배우고 있습니다. Jonathan Corbet의 책에 따르면 장치 드라이버에는 기능이 없습니다 main()
.
그래서 두 가지 질문이 있습니다.
main()
장치 드라이버에 기능이 필요하지 않은 이유는 무엇입니까 ?- 커널 자체에
main()
기능이 있습니까?
누구든지 나에게 이것을 설명해 줄 수 있습니까?
답변1
사용자 공간 프로그램에서는 main()
프로그램의 진입점입니다.libc 초기화 코드에 의해 호출됨바이너리가 실행될 때. 커널 코드는 libc에 의존할 여유가 없습니다. 왜냐하면 libc 자체는 메모리 할당, I/O, 프로세스 관리 등을 위해 커널 시스템 호출 인터페이스에 의존하기 때문입니다.
main()
즉, 커널 코드에서는 와 동일합니다 start_kernel()
.부트로더에 의해 호출됨커널 이미지를 로드한 후 이를 메모리에 추출하고 필요한 하드웨어 및 메모리 페이징을 설정합니다. start_kernel()
대부분의 시스템 설정을 수행하고 궁극적으로 init 프로세스를 생성합니다.
Linux 커널 모듈의 진입점은 매크로를 호출하여 커널에 등록하는 init 함수입니다 module_init()
. 그러면 등록된 모듈 초기화 함수는 다음과 같습니다.커널 코드에 의해 호출됨do_initcalls()
커널 시작 중에 이 함수를 통과했습니다.
답변2
커널에는 main
기능이 없습니다. main
C언어의 개념이다. 커널은 C와 어셈블리 언어로 작성되었습니다. 커널의 진입 코드는 어셈블리 언어로 작성됩니다.
시동 순서는 다음과 같이 구성됩니다.
- BIOS는 일반적으로 부트 블록 장치에서 부트 로더를 로드합니다. 요즘 인기 있는 부트로더는 grub입니다.
- Grub은 커널 이미지를 RAM에 로드하고 초기 루트 장치(
initrd
)를 사용할 수 있습니다. 그런 다음 특정 주소에서 코드를 실행합니다. - 커널 이미지에는 파일 시스템 모듈 및 장치 드라이버와 같은 일부 커널 모듈이 있습니다. 커널 이미지는 파일 시스템 모듈을 사용하여 루트 파일 시스템을 마운트합니다. 이제 커널은 디스크에서 모든 커널 모듈을 로드하고 실행할 수 있습니다.
- 커널은 초기화 작업을 실행합니다. 예: PCI 버스를 탐색하여 모든 PCI 장치를 찾고 모든 장치 드라이버를 초기화합니다.
- 마지막으로 커널은 프로세스 0과 프로세스 1(process
init
)을 생성하고 CPU 컨텍스트를 링 0에서 링 3으로 전환한 다음 init 프로세스(프로세스 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 프로젝트에서 제공됩니다.
답변3
예를 들어 main() 함수가 있습니다.아치/x86/boot/main.c리얼 모드에서 보호 모드로 전환하기 위해 시스템을 준비하는 데 사용되지만 다른 아키텍처에는 이러한 코드가 없습니다. 좋은 것이 있습니다개요x86 플랫폼에서 Linux 커널 2.6.x 부팅이 작동하는 방식. 정말 읽어볼 가치가 있습니다.
문서에 따르면Linux 커널 개발을 수행하는 방법, 리눅스 커널은
표준 C 라이브러리에 의존하지 않으므로 C 표준의 일부 부분을 지원하지 않는 독립형 C 환경입니다.
그건 그렇고, C 표준에 따르면 무엇을 하는가?
독립형 환경의 프로그램이 "주" 기능을 정의해야 하는지 여부는 구현에 따라 정의됩니다.