programing

fork()가 내부적으로 clone()을 호출한다는 것이 사실입니까?

firstcheck 2022. 7. 26. 22:21
반응형

fork()가 내부적으로 clone()을 호출한다는 것이 사실입니까?

Robert Love(ISBN:0-672-32720-1)의 "Linux Kernel Development, Second Edition" 제3장에서 다음과 같은 내용을 읽었습니다.clonesystem call은 Linux에서 스레드를 작성하기 위해 사용됩니다.이제 의 구문은clone시작 루틴/기능 주소를 전달해야 하는 경우입니다.

그러나 같은 페이지에 다음과 같이 쓰여 있다.forkclone내부적으로그래서 제 질문은, 어떻게 아이 프로세스가fork다음 코드 부분의 실행을 시작합니다.fork호출, 즉 어떻게 시작점으로 기능이 필요하지 않은가?

제공된 링크에 잘못된 정보가 있을 경우 더 나은 링크/리소스로 안내해 주십시오.

이런 질문은 항상 소스코드를 읽어주세요.

glibc에서nptl/sysdeps/unix/sysv/linux/fork.c(기트허브) (nptl= Linux용 기본 Posix 스레드)의 구현을 확인할 수 있습니다.fork()syscall이 아닌, 우리는 마법이 그 안에서 일어나는 것을 볼 수 있다.ARCH_FORKmacro: 이 매크로를 인라인콜로 정의합니다.clone()nptl/sysdeps/unix/sysv/linux/x86_64/fork.c(깃허브).하지만 잠시 기다려 주십시오. 이 버전의 에 함수 또는 스택 포인터가 전달되지 않습니다.clone()그래, 무슨 일이야?

그럼 다음 구현에 대해 살펴보겠습니다.clone()그럼 glibc로.안에 있다sysdeps/unix/sysv/linux/x86_64/clone.S(깃허브).기능 포인터를 자녀의 스택에 저장하고 클론 syscall을 호출하면 새로운 프로세스가 함수를 스택에서 불러온 후 호출하는 것을 알 수 있습니다.

다음과 같이 동작합니다.

clone(void (*fn)(void *), void *stack_pointer)
{
    push fn onto stack_pointer
    syscall_clone()
    if (child) {
        pop fn off of stack
        fn();
        exit();
    }
}

그리고.fork()그건...

fork()
{
    ...
    syscall_clone();
    ...
}

요약

실제의clone()syscall은 함수 인수를 받지 않고 반환점부터 계속됩니다.fork()그래서 둘 다clone()그리고.fork() 라이브러리의 함수는, 그 주변의 랩퍼입니다.clone()시스템

문서

설명서의 복사본은 좀 더 솔직합니다.clone()는 라이브러리 기능과 시스템콜입니다하지만, 저는 약간 오해를 살 수 있다고 생각합니다.clone()섹션 2와 섹션3이 아닌 섹션2에 있습니다.man 페이지부터:

#include <sched.h>

int clone(int (*fn)(void *), void *child_stack,
          int flags, void *arg, ...
          /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );

/* Prototype for the raw system call */

long clone(unsigned long flags, void *child_stack,
          void *ptid, void *ctid,
          struct pt_regs *regs);

그리고.

이 페이지에서는 양쪽 glibc에 대해 설명합니다.clone()래퍼 함수와 그 기반이 되는 시스템콜.메인 텍스트에서는 래퍼 기능에 대해 설명합니다.원시 시스템콜의 차이는 이 페이지의 마지막에 설명되어 있습니다.

마침내.

★★★clone()은 " "에 더 " 에 합니다.fork(2)을 사용하다같이 및 .clone()이치노또한 인수 순서가 변경됩니다.

@Dietrich는 실장을 보면서 설명을 잘했다.대박이다!어쨌든, 그것을 발견할 수 있는 또 다른 방법이 있습니다.그것은, 「스니프」의 콜을 보는 것입니다.

할 수 요.fork(2)해 주세요).fork시스콜

#define WRITE(__fd, __msg) write(__fd, __msg, strlen(__msg))

int main(int argc, char *argv[])
{
  pid_t pid;

  switch (pid = fork()) {
    case -1:
      perror("fork:");
      exit(EXIT_FAILURE);
      break;
    case 0:
      WRITE(STDOUT_FILENO, "Hi, i'm the child");
      exit(EXIT_SUCCESS);
    default:
      WRITE(STDERR_FILENO, "Heey, parent here!");
      exit(EXIT_SUCCESS);
  }

  return EXIT_SUCCESS;
}

그럼 그 해 .clang -Wall -g fork.c -o fork.out 다음 을 사용해서 실행해보세요.strace:

strace -Cfo ./fork.strace.log ./fork.out

수신됩니다.-f 아이의 수신합니다).그 후, 그을 「」, 「」, 「」, 「」, 「」에 넣습니다../fork.trace.log-c옵션을 선택하면 마지막에 요약이 표시됩니다).Ubuntu 14.04, x86_64 Linux 3.16)입니다.

6915  arch_prctl(ARCH_SET_FS, 0x7fa001a93740) = 0
6915  mprotect(0x7fa00188c000, 16384, PROT_READ) = 0
6915  mprotect(0x600000, 4096, PROT_READ) = 0
6915  mprotect(0x7fa001ab9000, 4096, PROT_READ) = 0
6915  munmap(0x7fa001a96000, 133089)    = 0
6915  clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fa001a93a10) = 6916
6915  write(2, "Heey, parent here!", 18) = 18
6916  write(1, "Hi, i'm the child", 17 <unfinished ...>
6915  exit_group(0)                     = ?
6916  <... write resumed> )             = 17
6916  exit_group(0)                     = ?
6915  +++ exited with 0 +++
6916  +++ exited with 0 +++
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 24.58    0.000029           4         7           mmap
 17.80    0.000021           5         4           mprotect
 14.41    0.000017           9         2           write
 11.02    0.000013          13         1           munmap
 11.02    0.000013           4         3         3 access
 10.17    0.000012           6         2           open
  2.54    0.000003           2         2           fstat
  2.54    0.000003           3         1           brk
  1.69    0.000002           2         1           read
  1.69    0.000002           1         2           close
  0.85    0.000001           1         1           clone
  0.85    0.000001           1         1           execve
  0.85    0.000001           1         1           arch_prctl
------ ----------- ----------- --------- --------- ----------------
100.00    0.000118                    28         3 total

'아니오'는 .fork 요 전 요 。 그냥 날것만clone, 설정되어 있다.syscall, "syscall", "syscall", "syscall", "syscall" 등의 명령어를 합니다.

언급URL : https://stackoverflow.com/questions/18904292/is-it-true-that-fork-calls-clone-internally

반응형