2.6 커널 리눅스에서의 포크와 복제

2.6 커널 리눅스에서의 포크와 복제

포크와 복제에 대해 약간 혼란 스럽습니다. 나는 그것을 이미 보았다:

  • 포크는 프로세스에 사용되고 클론은 스레드에 사용됩니다.

  • 포크는 단지 클론을 호출하고, 클론은 모든 프로세스와 스레드에 사용됩니다.

이것이 정확합니까? 이 두 가지 시스템 호출과 2.6 Linux 커널의 차이점은 무엇입니까?

답변1

fork()원래 UNIX 시스템 호출입니다. 스레드가 아닌 새 프로세스를 생성하는 데에만 사용할 수 있습니다. 게다가 휴대성이 좋다.

Linux에서는 clone()새로운 실행 스레드를 생성하는 데 사용할 수 있는 새로운 다기능 시스템 호출입니다. 전달된 옵션에 따라 새 실행 스레드는 UNIX 프로세스, POSIX 스레드, 그 사이의 의미 체계 또는 완전히 다른 의미 체계(예: 다른 컨테이너)를 따를 수 있습니다. 메모리, 파일 설명자, 다양한 네임스페이스, 신호 처리기 등을 공유할지 아니면 복사할지 결정하는 다양한 옵션을 지정할 수 있습니다.

상위 집합 시스템 호출이므로 clone()glibc의 시스템 호출 래퍼 구현이 실제로 호출하지만 이는 프로그래머가 알 필요가 없는 구현 세부 사항입니다. 이전 버전과의 호환성 때문에 실제 시스템 호출은 여전히 ​​Linux 커널에 존재합니다. 하지만 매우 오래된 버전의 libc나 glibc 이외의 다른 libc를 사용하는 프로그램에서 사용할 수 있기 때문에 중복되어 있습니다.fork()clone()fork()

clone()pthread_create()스레드를 생성하는 POSIX 함수를 구현하는 데에도 사용됩니다 .

이식 가능한 프로그램은 대신 fork()and 를 호출해야 합니다 .pthread_create()clone()

답변2

clone()Linux 2.6에는 두 가지가 있는 것 같습니다.

시스템 호출이 있습니다:

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

이것이 "clone()"으로 설명되는 것입니다 man 2 clone.

매뉴얼 페이지를 주의 깊게 읽으면 다음 내용을 볼 수 있습니다.

It is actually a library function layered on top of the
underlying clone() system call.

분명히 동일한 이름의 혼란스러운 시스템 호출 위에 있는 "라이브러리 함수"를 사용하여 스레드를 구현해야 합니다.

나는 작은 프로그램을 작성했습니다.

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int
main(int ac, char **av)
{
    pid_t cpid;
    switch (cpid = fork()) {
    case 0:   // Child process
        break;
    case -1:  // Error
        break;
    default:  // parent process
        break;
    }
    return 0;
}

사용법: 컴파일 c99 -Wall -Wextra하고 실행하여 strace -f분기 시스템 호출이 실제로 수행하는 작업을 확인합니다. straceLinux 2.6.18 시스템(x86_64 CPU)에서 이것을 얻습니다 .

20097 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x2b4ee9213770) = 20098
20097 exit_group(0)                     = ?
20098 exit_group(0)

출력에는 "포크" 호출이 나타나지 않습니다 strace. 출력 clone()에 표시된 호출에는 strace매뉴얼 페이지 복제와 매우 다른 매개변수가 있습니다. child_stack=0첫 번째 매개변수가 와 다르기 때문입니다 int (*fn)(void *).

fork(2)시스템 호출이 다음과 같이 구현된 것 같습니다 .진짜 clone(), "라이브러리 함수" 구현과 같습니다 clone(). 이것진짜 clone()매뉴얼 페이지 복제와는 다른 매개변수 세트가 있습니다.

fork()간단히 말해서, 및 에 대한 명백히 모순되는 두 가지 진술은 clone()모두 정확합니다. 그러나 관련된 "클론"은 다릅니다.

답변3

fork()시스템 호출을 위한 특정 플래그 세트입니다 clone(). clone()"프로세스"나 "스레드"를 생성할 만큼 일반적이거나 프로세스와 스레드 사이의 이상한 것(예: 동일한 파일 설명자 테이블을 공유하는 서로 다른 "프로세스").

기본적으로 커널의 실행 컨텍스트와 관련된 각 정보 "유형"에 대해 clone()해당 정보에 별칭을 지정하거나 복사하도록 선택할 수 있습니다. 스레드는 별칭에 해당하고 프로세스는 복제에 해당합니다. flags 의 중간 조합을 지정하면 clone()스레드나 프로세스가 아닌 이상한 것을 만들 수 있습니다. 일반적으로 이렇게 해서는 안 됩니다. 제 생각에는 Linux 커널을 개발하는 동안 clone().

관련 정보