Google 에서이 4 가지의 차이점을 찾고 있었고이 정보에 대한 많은 양의 정보가있을 것으로 예상했지만 실제로는 4 개의 통화 사이에 확실한 비교가 없었습니다.
이러한 시스템 호출의 차이점을 살펴보면 일종의 기본 개요를 한눈에 살펴볼 수 있습니다. 이 모든 정보가 정확합니까 / 중요한 것이 누락 되었습니까?
Fork
: 포크 호출은 기본적으로 현재 프로세스의 복제본을 거의 모든 방식으로 동일하게 만듭니다 (예를 들어, 일부 구현에서 자원 제한과 같은 모든 것이 복사되지는 않지만 가능한 한 사본을 가깝게 만드는 아이디어입니다).
새 프로세스 (자식)는 다른 프로세스 ID (PID)를 가져오고 이전 프로세스 (부모)의 PID를 상위 PID (PPID)로 갖습니다. 두 프로세스가 이제 정확히 동일한 코드를 실행하고 있기 때문에 fork의 리턴 코드를 통해 어떤 프로세스가 어떤 것인지 알 수 있습니다. 하위는 0이되고 상위는 하위의 PID를 가져옵니다. 이것은 물론 포크 호출이 작동한다고 가정합니다. 그렇지 않으면 자식이 생성되지 않고 부모가 오류 코드를 얻습니다.
Vfork
: vfork와 fork의 기본 차이점은 vfork ()를 사용하여 새 프로세스를 만들 때 부모 프로세스가 일시적으로 중단되고 자식 프로세스가 부모의 주소 공간을 빌릴 수 있다는 것입니다. 이 이상한 상황은 자식 프로세스가 종료되거나 execve ()를 호출 할 때까지 계속되며,이 때 부모 프로세스는 계속됩니다.
즉, vfork ()의 자식 프로세스는 부모 프로세스의 변수를 예기치 않게 수정하지 않도록주의해야합니다. 특히, 자식 프로세스는 vfork () 호출을 포함하는 함수에서 리턴해서는 안되며 exit ()를 호출하지 않아야합니다 (종료해야하는 경우 _exit ()를 사용해야합니다. 실제로, 이는 자식에 대해서도 마찬가지입니다. 일반 포크 ()).
Exec :
exec 호출은 기본적으로 현재 프로세스 전체를 새로운 프로그램으로 대체하는 방법입니다. 프로그램을 현재 프로세스 공간으로로드하고 진입 점에서 실행합니다. exec ()는 현재 프로세스를 함수가 가리키는 실행 파일로 바꿉니다. exec () 오류가 없으면 컨트롤은 원래 프로그램으로 돌아 가지 않습니다.
Clone :
클론은 포크로서 새로운 프로세스를 만듭니다. 포크와는 달리, 이러한 호출을 통해 하위 프로세스는 메모리 공간, 파일 디스크립터 테이블 및 신호 핸들러 테이블과 같은 실행 컨텍스트의 일부를 호출 프로세스와 공유 할 수 있습니다.
자식 프로세스가 clone으로 생성되면 함수 응용 프로그램 fn (arg)이 실행됩니다. (이것은 원래 포크 호출 시점부터 자식에서 실행이 계속되는 포크와 다릅니다.) fn 인수는 실행 시작시 자식 프로세스가 호출하는 함수에 대한 포인터입니다. arg 인수는 fn 함수로 전달됩니다.
fn (arg) 함수 응용 프로그램이 리턴되면 하위 프로세스가 종료됩니다. fn에 의해 리턴 된 정수는 하위 프로세스의 종료 코드입니다. 하위 프로세스는 exit (2)를 호출하거나 치명적 신호를 수신 한 후 명시 적으로 종료 될 수도 있습니다.
입수 한 정보 :
- 포크와 exec의 차이점
- http://www.allinterview.com/showanswers/59616.html
- http://www.unixguide.net/unix/programming/1.1.2.shtml
- http://linux.about.com/library/cmd/blcmdl2_clone.htm
이것을 읽어 주셔서 감사합니다! 🙂
답변
-
vfork()
사용되지 않는 최적화입니다. 좋은 메모리 관리 전에fork()
부모 메모리의 전체 사본을 만들었으므로 꽤 비쌌습니다. 많은 경우에 현재 메모리 맵을 버리고 새로운 맵을 생성하는 afork()
가 뒤에exec()
오기 때문에 불필요한 비용이 들었습니다. 요즘에는fork()
메모리를 복사하지 않습니다. 그것은 단순히 때문에, “쓰기 복사”로 설정되어fork()
+는exec()
효율적으로 그냥vfork()
+exec()
. -
clone()
에서 사용하는 syscallfork()
입니다. 일부 매개 변수를 사용하면 새 프로세스를 만들고 다른 매개 변수를 사용하면 스레드를 만듭니다. 이들의 차이점은 메모리 공간, 프로세서 상태, 스택, PID, 열린 파일 등의 데이터 구조가 공유되는지 여부입니다.
답변
execve()
현재 실행 가능 이미지를 실행 파일에서로드 된 다른 이미지로 대체합니다.fork()
자식 프로세스를 만듭니다.vfork()
의 최적화 된 이전 버전fork()
으로을 (를)execve()
바로 다음에 호출 할 때 사용됩니다fork()
. MMU가 아닌 시스템 (fork()
효율적인 방식으로 작동 할 수없는 곳 )과fork()
작은 메모리 공간을 가진 프로세스를 작은 프로그램을 실행하기 위해 처리 할 때 잘 작동하는 것으로 나타났습니다 (Java 생각Runtime.exec()
). POSIX는posix_spawn()
이 후자를 두 가지 더 현대적인 용도로 대체하도록 표준화했습니다vfork()
.posix_spawn()
는 afork()/execve()
와 동등하며 일부 fd 사이에서 저글링을 허용합니다.fork()/execve()
주로 비 MMU 플랫폼의 경우을 대체해야합니다 .pthread_create()
새로운 스레드를 만듭니다.clone()
는 Linux 전용 호출이며에서fork()
까지 구현하는 데 사용할 수 있습니다pthread_create()
. 그것은 많은 통제권을줍니다. 에 영감을 받았습니다rfork()
.rfork()
Plan-9 전용 통화입니다. 전체 프로세스와 스레드간에 여러 수준의 공유를 허용하는 일반 호출이어야합니다.
답변
fork()
-부모 프로세스의 완전한 복사 본인 새 자식 프로세스를 만듭니다. 자식 프로세스와 부모 프로세스는 서로 다른 가상 주소 공간을 사용하며 처음에는 동일한 메모리 페이지로 채워집니다. 그런 다음 두 프로세스가 실행될 때 운영 체제가이 두 프로세스 중 하나에 의해 작성되는 메모리 페이지의 지연 복사를 수행하고 수정 된 페이지의 독립적 인 사본을 할당하기 때문에 가상 주소 공간이 점점 더 달라지기 시작합니다. 각 프로세스에 대한 메모리. 이 기술을 COW (Copy-On-Write)라고합니다.vfork()
-부모 프로세스의 “빠른”복사 본인 새 자식 프로세스를 만듭니다. 시스템 호출과 달리fork()
자식 프로세스와 부모 프로세스는 동일한 가상 주소 공간을 공유합니다. 노트! 동일한 가상 주소 공간을 사용하면 부모와 자식 모두 클래식의 경우와 동일한 스택, 스택 포인터 및 명령 포인터를 사용합니다fork()
! 동일한 스택을 사용하는 부모와 자식 간의 원치 않는 간섭을 방지하기 위해 자식 프로세스가 호출exec()
(새 가상 주소 공간 생성 및 다른 스택으로의 전환) 또는_exit()
프로세스 실행 종료 까지 부모 프로세스 실행이 고정됩니다. ). “fork-and-exec”모델vfork()
의 최적화입니다fork()
.fork()
와 달리 4-5 배 빠르게 수행 할 수 있습니다 .fork()
(COW를 염두에두고도)vfork()
시스템 호출 구현 에는 새 주소 공간 작성 (새 페이지 디렉토리의 할당 및 설정)이 포함되지 않습니다.clone()
-새로운 자식 프로세스를 만듭니다. 이 시스템 호출의 다양한 매개 변수는 상위 프로세스의 어떤 부분이 하위 프로세스에 복사되어야하는지와 그 사이에서 공유 될 부분을 지정합니다. 결과적으로이 시스템 호출을 사용하여 스레드에서 시작하여 완전히 독립적 인 프로세스로 마무리하는 모든 종류의 실행 엔터티를 만들 수 있습니다. 실제로,clone()
시스템 호출은 시스템 호출의pthread_create()
모든 패밀리 및 구현에 사용되는 기본입니다fork()
.exec()
-프로세스의 모든 메모리를 재설정하고 지정된 실행 가능한 바이너리를로드 및 구문 분석하고 새 스택을 설정하고로드 된 실행 파일의 시작점으로 제어를 전달합니다. 이 시스템 호출은 호출자에게 제어를 리턴하지 않으며 기존 프로그램에 새 프로그램을로드하는 데 사용됩니다. 시스템 호출과fork()
함께이 시스템 호출은 “fork-and-exec”라는 고전적인 UNIX 프로세스 관리 모델을 형성합니다.
답변
fork (), vfork () 및 clone ()은 모두 실제 작업을 수행하기 위해 do_fork ()를 호출하지만 매개 변수는 다릅니다.
asmlinkage int sys_fork(struct pt_regs regs)
{
return do_fork(SIGCHLD, regs.esp, ®s, 0);
}
asmlinkage int sys_clone(struct pt_regs regs)
{
unsigned long clone_flags;
unsigned long newsp;
clone_flags = regs.ebx;
newsp = regs.ecx;
if (!newsp)
newsp = regs.esp;
return do_fork(clone_flags, newsp, ®s, 0);
}
asmlinkage int sys_vfork(struct pt_regs regs)
{
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0);
}
#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */
#define CLONE_VM 0x00000100 /* set if VM shared between processes */
SIGCHLD means the child should send this signal to its father when exit.
포크의 경우 자식과 아버지는 독립적 인 VM 페이지 테이블을 가지지 만 효율성 때문에 포크는 실제로 페이지를 복사하지 않으므로 쓰기 가능한 모든 페이지를 자식 프로세스의 읽기 전용으로 설정합니다. 따라서 자식 프로세스가 해당 페이지에 무언가를 쓰려고 할 때 페이지 예외가 발생하고 커널은 이전 페이지에서 복제 된 새 페이지를 쓰기 권한으로 할당합니다. 이를 “쓰기시 복사”라고합니다.
vfork의 경우 가상 메모리는 정확히 자녀와 아버지에 의한 것입니다. 그 때문에 아버지와 자녀는 서로 영향을 미치기 때문에 동시에 깨울 수 없습니다. 따라서 아버지는 “do_fork ()”의 끝에서 자고 자식이 exit () 또는 execve ()를 호출하면 새 페이지 테이블을 소유 할 때 깨어납니다. 아버지가 자고있는 코드 (do_fork ())가 있습니다.
if ((clone_flags & CLONE_VFORK) && (retval > 0))
down(&sem);
return retval;
다음은 아버지를 깨우는 exit () 및 execve ()에 의해 호출 된 mm_release () 코드입니다.
up(tsk->p_opptr->vfork_sem);
sys_clone ()의 경우 clone_flags를 입력 할 수 있으므로 더 유연합니다. 따라서 pthread_create ()는 많은 clone_flags로이 시스템 호출을 호출합니다.
int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_SYSVSEM);
요약 : fork (), vfork () 및 clone ()은 아버지 프로세스와 다른 공유 자원 마운트로 하위 프로세스를 작성합니다. vfork ()와 clone ()은 VM 페이지 테이블을 아버지 프로세스와 공유하기 때문에 스레드를 생성 할 수 있다고 말할 수 있습니다.
답변
fork ()에서는 자식 또는 부모 프로세스가 CPU 선택에 따라 실행됩니다. 그러나 vfork ()에서는 반드시 자식이 먼저 실행됩니다. 자식이 종료되면 부모가 실행됩니다.