`execve()`는 특수 시작 루틴과 main() 함수를 어떻게 호출합니까?

`execve()`는 특수 시작 루틴과 main() 함수를 어떻게 호출합니까?

C 프로그램이 커널에 의해 실행될 때 execve(),

  • 라는 기본 함수를 호출하기 전에 호출되는 특수 시작 루틴은 어디에 있습니까 execve()?crt0

  • execve()main 함수는 어디에서 호출되나요?

찾을 수 없어요https://elixir.bootlin.com/linux/latest/source/fs/exec.c.

Linux 커널을 이해하는 것부터 시작하여 execve()내부적으로 실행 파일을 로드할 수 있는 개체를 찾고 linux_binfmt해당 메서드를 호출하여 로드합니다. 또한 실행 파일에서 사용하는 공유 라이브러리를 로드하고 링크하기 위해 동적 링커를 로드합니다. 하지만 이 책에서는 프로그램의 시작 루틴을 호출한 다음 실행 파일에서 호출하는 방법을 설명하지 않습니다.load_binary()load_binary()execve()crt0main()

감사해요.

답변1

execve어떤 커널 코드도 이 함수 _start(호칭에 관계없이 실행 파일의 진입점)를 호출하지 않습니다.

서로 다른 곳에서 뛰기 때문이죠문맥; 마치 다른 컴퓨터에서 실행되는 것처럼 보입니다.

커널은 execve사용자 모드로 돌아갈 때 시스템 호출을 예약하고 IP(명령 포인터) 레지스터를 함수의 시작 부분을 가리키도록 설정 _start하고 SP(스택 포인터) 레지스터를 함수의 시작 부분을 가리키도록 설정합니다. argv + env 문자열 목록이므로 사용자 모드 관점에서 효과는 다음과 같습니다.누구이 함수를 _start다음과 같이 호출하세요.

_start(argc, argv0, argv1, ... , NULL, env0, env1, ... NULL)

모든 인수가 스택에 전달되는 호출 규칙에서.

물론 이런 일이 발생하기 전에 커널은 이미 이러한 argv + env를 올바른 위치에 복사하고 _start함수가 포함된 세그먼트를 매핑하는 등의 작업을 담당하고 있습니다.


argv + env 문자열은 모두 하나의 블록에 포함되어 있습니다.

"prog\0arg1\0arg2\0VAR1=foo\0VAR2=bar\0"

이 블록이 시작하고 끝나는 가상 주소는 /proc/PID/stat매뉴얼 procfs(5)페이지를 인용하여 액세스할 수 있습니다.

(48) arg_start  %lu  (since Linux 3.5)  [PT]
        Address  above  which  program  command-line arguments
        (argv) are placed.

(49) arg_end  %lu  (since Linux 3.5)  [PT]
        Address below program  command-line  arguments  (argv)
        are placed.

ps이 주소에 쓰면 출력에 나타나는 모든 내용이 수정됩니다 .

$ sleep 3600 3600 3600 3600 3600 3600 3600 &
[2] 4927
$ awk '{print $48,$49,$49-$48-1}' /proc/4927/stat
140735402952841 140735402952882 40
$ printf 'Somebody set up us the bomb Main screen turn on\0' | dd bs=1 count=40 of
=/proc/4927/mem seek=140735402952841 conv=notrunc
40+0 records in
40+0 records out
40 bytes copied, 0.000229779 s, 174 kB/s
$ ps 4927
  PID TTY      STAT   TIME COMMAND
 4927 pts/4    S      0:00 Somebody set up us the bomb Main screen

관련 정보