C에서 _start () 사용은 무엇입니까? 작성하지 않고도 C 프로그램을

동료로부터 main()함수 를 작성하지 않고도 C 프로그램을 작성하고 실행할 수 있다는 것을 배웠습니다 . 다음과 같이 할 수 있습니다.

my_main.c

/* Compile this with gcc -nostartfiles */

#include <stdlib.h>

void _start() {
  int ret = my_main();
  exit(ret);
}

int my_main() {
  puts("This is a program without a main() function!");
  return 0;
}

다음 명령으로 컴파일하십시오.

gcc -o my_main my_main.c nostartfiles

다음 명령으로 실행하십시오.

./my_main

언제 이런 일을해야할까요? 이것이 유용한 실제 시나리오가 있습니까?



답변

기호 _start는 프로그램 의 진입 점 입니다. 즉, 해당 심볼의 주소는 프로그램 시작시 점프 한 주소입니다. 일반적으로 이름의 함수 는 C 런타임 환경의 시작 코드를 포함하는 _start라는 파일에서 제공됩니다 crt0.o. 몇 가지 항목을 설정하고 인수 배열을 채우고 argv거기에 몇 개의 인수가 있는지 계산 한 다음 main. main반환 후 exit호출됩니다.

프로그램이 C 런타임 환경을 사용하지 않으려면 _start. 예를 들어 Go 프로그래밍 언어의 참조 구현은 스택에 마법이 필요한 비표준 스레딩 모델이 필요하기 때문에 그렇게합니다. _start아주 작은 프로그램이나 틀에 얽매이지 않는 일을하는 프로그램을 작성하고 싶을 때 자신 만의 것을 제공하는 것도 유용합니다 .


답변

main프로그래머의 관점에서는 프로그램의 진입 점 이지만 _startOS 관점의 일반적인 진입 점입니다 (프로그램이 OS에서 시작된 후 실행되는 첫 번째 명령).

일반적인 C 및 특히 C ++ 프로그램에서는 실행이 main에 들어가기 전에 많은 작업이 수행되었습니다. 특히 전역 변수 초기화와 같은 것입니다. 여기에 당신이 사이에 일어나는 모든 일의 좋은 설명 찾을 수 있습니다 _start()그리고 main()또한 주가 (아래 설명을 참조) 다시 종료 된 후입니다.
이를 위해 필요한 코드는 일반적으로 시작 파일에서 컴파일러 작성자가 제공하지만 플래그를 사용 –nostartfiles하면 기본적으로 컴파일러에 다음 과 같이 알 수 있습니다. “표준 시작 파일을 제공하는 데 신경 쓰지 마십시오. 스타트”.

이것은 때때로 필요하며 종종 임베디드 시스템에서 사용됩니다. 예를 들어 OS가없고 전역 개체를 초기화하기 전에 메모리 시스템의 특정 부분 (예 : 캐시)을 수동으로 활성화해야하는 경우.


답변

다음이전에 프로그램을 시작하는 동안 발생하는 일에 대한 좋은 개요입니다 main. 특히__start 입니다 실제 진입 점 OS의 관점에서 프로그램에.

이 주소는 명령어 포인터 가 프로그램에서 카운트를 시작할 .

거기에있는 코드는 일부 하우스 키핑을 수행하기 위해 C 런타임 라이브러리 루틴을 호출 한 다음을 호출 main한 다음 작업을 중단하고 반환 된 exit종료 코드 main로 호출 합니다.


사진은 천 단어의 가치가 있습니다.


추신 :이 답변은 SO가 도움이되는 다른 질문 에서 이식 된 것입니다.


답변

언제 이런 일을해야할까요?

프로그램에 대한 자체 시작 코드를 원할 때.

main C 프로그램의 첫 번째 항목이 아닙니다. _start 의 첫 번째 항목이 아니라 커튼 뒤의 첫 번째 항목입니다.

Linux의 예 :

_start: # _start is the entry point known to the linker
    xor %ebp, %ebp            # effectively RBP := 0, mark the end of stack frames
    mov (%rsp), %edi          # get argc from the stack (implicitly zero-extended to 64-bit)
    lea 8(%rsp), %rsi         # take the address of argv from the stack
    lea 16(%rsp,%rdi,8), %rdx # take the address of envp from the stack
    xor %eax, %eax            # per ABI and compatibility with icc
    call main                 # %edi, %rsi, %rdx are the three args (of which first two are C standard) to main

    mov %eax, %edi    # transfer the return of main to the first argument of _exit
    xor %eax, %eax    # per ABI and compatibility with icc
    call _exit        # terminate the program

이것이 유용한 실제 시나리오가 있습니까?

당신이 의미한다면, 우리 자신을 구현하십시오 _start:

예, 제가 함께 작업 한 대부분의 상업용 임베디드 소프트웨어에서 _start특정 메모리 및 성능 요구 사항과 관련하여 자체적으로 구현해야합니다 .

의미하는 경우 main함수를 삭제 하고 다른 것으로 변경하십시오.

아니요, 그렇게하면 어떤 이점도 보지 못합니다.