2.6 커널 Linux의 포크 대 클론


37

포크와 클론에 대한 혼란이 있습니다. 나는 그것을 보았다 :

  • fork는 프로세스 용이고 clone은 스레드 용입니다.

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

이 중 하나가 정확합니까? 2.6 Linux 커널을 사용하는이 2 개의 syscall의 차이점은 무엇입니까?

답변:


52

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

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

이후 clone()상위 집합 시스템 호출의 구현입니다 fork()glibc는 실제로 통화에서 시스템 호출 래퍼 clone(), 그러나 이것은 프로그래머가에 대해 알아야 할 필요가 없습니다 구현 세부입니다. fork()이전 버전의 libc 또는 glibc 이외의 다른 libc를 사용하는 프로그램이이를 사용할 수 있기 때문에 실제 실제 시스템 호출은 여전히 ​​이전 버전과의 호환성을 위해 Linux 커널에 여전히 존재합니다.

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

휴대용 프로그램은 호출해야 fork()하고 pthread_create(),하지 clone().


2
posix_spawn은 몇 가지 방법으로 포크보다 이식성이 뛰어난 또 다른 관련 기능입니다.
Random832

10

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. 나는 strace리눅스 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)시스템 호출이 real 측면에서 구현 된 것으로 보입니다 . 진짜 사람-페이지 클론 인수의 다른 세트가 있습니다.clone()clone() clone()

간단히 말해서, 당신의 명백한 모순 된 진술에 관한 fork()그리고 clone()맞습니다. 그러나 관련된 "복제본"은 다릅니다.


9
"실제로 기본 clone () 시스템 호출 위에 계층화 된 라이브러리 함수입니다." — 일반적으로 모든 시스템 호출에 적용됩니다. 실제로 프로그래머는 사실상 항상 시스템 호출의 이름을 딴 libc의 함수를 호출합니다. C에서 직접 실제 시스템 호출을하려면 플랫폼 고유의 마법 (일반적으로 ABI에 따라 CPU 트랩을 강제 실행)과 libc에 위임 된 머신 코드가 필요하기 때문입니다.
Celada

1
@Celada-예, 동의했습니다. 그것은 단지의 man 2 clone문구 정확히 내가 생각했던 그런 식으로이 문제를 혼동하고, 좋은 답변을 얻기에서 질문자를 방지했다.
Bruce Ediger

2
나는 맨 수단이 나타 생각하는 그 인수 목록clone기본 시스템 호출에 의해 허용 인수 목록에서 실질적으로 라이브러리 기능 다릅니다. 특히 시스템 호출은 항상 기존 스택과 동일한 스택에서 두 번 반환됩니다 fork. 하위 스택과 관련된 모든 인수는 사용자 공간에서 엄격하게 처리됩니다. 예를 들어 sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/…
zwol

1
나는 그것이 당신의 대답에 최선의 대답을하고 싶었지만 바위에 흔들렸다. 그녀는 응답 시간에 대한 점수를 얻습니다. 설명해 주셔서 감사합니다.
Gregg Leventhal

6

fork()시스템 호출에 대한 특정 플래그 집합입니다 clone(). clone()"프로세스"또는 "스레드"또는 프로세스와 스레드 사이에있는 이상한 것들 (예 : 동일한 파일 디스크립터 테이블을 공유하는 다른 "프로세스")을 작성하기에 충분합니다.

기본적으로 커널의 실행 컨텍스트와 관련된 모든 "유형"정보에 대해 clone()해당 정보의 별칭을 지정하거나 정보를 복사 할 수 있습니다. 스레드는 앨리어싱에 해당하고 프로세스는 복사에 해당합니다. 에 플래그의 중간 조합을 지정하여 clone()스레드 나 프로세스가 아닌 이상한 것을 만들 수 있습니다. 당신은 보통 이것을하지 말아야한다. 나는 리눅스 커널을 개발하는 동안 이와 같은 일반적인 메커니즘을 허용해야하는지에 대한 논쟁이 있었다고 생각한다 clone().

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.