답변:
fork()
원래 UNIX 시스템 호출이었습니다. 스레드가 아닌 새 프로세스를 만드는 데만 사용할 수 있습니다. 또한 휴대용입니다.
Linux에서 clone()
새로운 실행 스레드를 작성하는 데 사용할 수있는 새롭고 다양한 시스템 호출입니다. 전달 된 옵션에 따라 새 실행 스레드는 UNIX 프로세스의 의미, POSIX 스레드, 사이에 있거나 완전히 다른 것 (예 : 다른 컨테이너)을 준수 할 수 있습니다. 메모리, 파일 설명자, 다양한 네임 스페이스, 신호 처리기 등을 공유 또는 복사할지 여부를 결정하는 모든 종류의 옵션을 지정할 수 있습니다.
이후 clone()
상위 집합 시스템 호출의 구현입니다 fork()
glibc는 실제로 통화에서 시스템 호출 래퍼 clone()
, 그러나 이것은 프로그래머가에 대해 알아야 할 필요가 없습니다 구현 세부입니다. fork()
이전 버전의 libc 또는 glibc 이외의 다른 libc를 사용하는 프로그램이이를 사용할 수 있기 때문에 실제 실제 시스템 호출은 여전히 이전 버전과의 호환성을 위해 Linux 커널에 여전히 존재합니다.
clone()
pthread_create()
스레드 작성을위한 POSIX 함수 를 구현하는 데에도 사용됩니다 .
휴대용 프로그램은 호출해야 fork()
하고 pthread_create()
,하지 clone()
.
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()
맞습니다. 그러나 관련된 "복제본"은 다릅니다.
man 2 clone
문구 정확히 내가 생각했던 그런 식으로이 문제를 혼동하고, 좋은 답변을 얻기에서 질문자를 방지했다.
clone
기본 시스템 호출에 의해 허용 인수 목록에서 실질적으로 라이브러리 기능 다릅니다. 특히 시스템 호출은 항상 기존 스택과 동일한 스택에서 두 번 반환됩니다 fork
. 하위 스택과 관련된 모든 인수는 사용자 공간에서 엄격하게 처리됩니다. 예를 들어 sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/…
fork()
시스템 호출에 대한 특정 플래그 집합입니다 clone()
. clone()
"프로세스"또는 "스레드"또는 프로세스와 스레드 사이에있는 이상한 것들 (예 : 동일한 파일 디스크립터 테이블을 공유하는 다른 "프로세스")을 작성하기에 충분합니다.
기본적으로 커널의 실행 컨텍스트와 관련된 모든 "유형"정보에 대해 clone()
해당 정보의 별칭을 지정하거나 정보를 복사 할 수 있습니다. 스레드는 앨리어싱에 해당하고 프로세스는 복사에 해당합니다. 에 플래그의 중간 조합을 지정하여 clone()
스레드 나 프로세스가 아닌 이상한 것을 만들 수 있습니다. 당신은 보통 이것을하지 말아야한다. 나는 리눅스 커널을 개발하는 동안 이와 같은 일반적인 메커니즘을 허용해야하는지에 대한 논쟁이 있었다고 생각한다 clone()
.