it-source

fork()의 목적은 무엇입니까?

criticalcode 2022. 11. 19. 11:33
반응형

fork()의 목적은 무엇입니까?

에서 man page, man page, man page를 사용한 를 보았습니다.fork()를할 필요가 는 무엇입니까?fork()리고 그그 ?적 적? ???

fork() Unix 로 새로운 입니다.했을 때fork독자적인 주소 공간을 가지는 독자적인 프로세스의 카피를 작성합니다.이를 통해 여러 태스크가 각각 컴퓨터에 대한 전체 메모리를 가지고 있는 것처럼 서로 독립적으로 실행될 수 있습니다.

사용법이 몇 있습니다.fork:

  1. 셸은fork명령줄에서 호출하는 프로그램을 실행합니다.
  2. Apache와 같은 웹 서버 사용fork여러 서버 프로세스를 만듭니다.이 프로세스는 각각 자체 주소 공간에서 요청을 처리합니다.한쪽이 정지하거나 메모리 누수가 발생해도 다른 한쪽은 영향을 받지 않기 때문에 폴트 톨러런스 메커니즘으로 기능합니다.
  3. Google Chrome은fork개별 프로세스 내에서 각 페이지를 처리합니다.이것에 의해, 1 페이지의 클라이언트측 코드가 브라우저 전체를 다운시키는 것을 방지할 수 있습니다.
  4. fork일부 병렬 프로그램(MPI를 사용하여 작성된 프로그램 등)에서 프로세스를 생성하는 데 사용됩니다.이는 자체 주소 공간이 없고 프로세스 내에 존재하는 스레드를 사용하는 것과는 다릅니다.
  5. 에서는 「」를 사용합니다.fork간접적으로 하위 프로세스를 시작합니다.예를 들어 Python과 같은 명령을 사용할 때마다fork하위 프로세스와 그 출력을 읽습니다.이것에 의해, 프로그램이 함께 동작할 수 있습니다.

fork뭇매를 맞다

int child_process_id = fork();
if (child_process_id) {
    // Fork returns a valid pid in the parent process.  Parent executes this.

    // wait for the child process to complete
    waitpid(child_process_id, ...);  // omitted extra args for brevity

    // child process finished!
} else {
    // Fork returns 0 in the child process.  Child executes this.

    // new argv array for the child process
    const char *argv[] = {"arg1", "arg2", "arg3", NULL};

    // now start executing some other program
    exec("/path/to/a/program", argv);
}

、 음음 、 the the 、 using the using using using using using using 。exec완료되기를 기다린 후 자체 실행을 계속합니다.이런 식으로 포크를 사용할 필요는 없습니다.병렬 프로그램처럼 항상 많은 하위 프로세스를 생성할 수 있으며 각각 동시에 프로그램을 실행할 수도 있습니다.시스템에서 를 작성할 Unix를 합니다.fork()Windows 와 동등한 것에 대해서는, 을 참조해 주세요.

더 많은 예시와 더 긴 설명을 원한다면 위키피디아에 적절한 요약이 있습니다.여기에서는 프로세스, 스레드 및 동시성이 최신 운영 체제에서 어떻게 작동하는지 몇 가지 슬라이드를 보여 줍니다.

fork()는 UNIX가 새로운 프로세스를 작성하는 방법입니다.fork()를 호출한 시점에서 프로세스가 클로닝되어 2개의 다른 프로세스가 거기에서 실행을 계속합니다.그 중 하나(자녀)는 fork()가 0을 반환하도록 합니다.다른 한쪽의 부모에게는 fork()가 자녀의 PID(프로세스 ID)를 반환하도록 합니다.

예를 들어 셸에 다음 명령을 입력하면 셸 프로그램이 fork()를 호출한 후 전달한 명령어(이 경우 telnetd)를 자녀에게 실행합니다.부모는 프롬프트와 백그라운드프로세스의 PID를 나타내는 메시지를 다시 표시합니다.

$ telnetd &

새로운 프로세스를 생성하는 이유는 운영체제가 동시에 많은 작업을 수행할 수 있도록 하기 위함입니다.그렇기 때문에 프로그램을 실행할 수 있고 실행 중에 다른 창으로 전환하여 다른 작업을 수행할 수 있습니다.

fork()는 부모 프로세스와 동일한 새 자식 프로세스를 만듭니다.그 후 코드로 실행하는 모든 작업은 두 프로세스 모두에서 실행됩니다.예를 들어 서버가 있고 여러 요청을 처리하는 경우 매우 유용합니다.

fork으로 이하기 위해 됩니다.포크()를 호출할 때마다 포크()는 자식 ID에 대해 0을 반환합니다.

pid=fork()
if pid==0
//this is the child process
else if pid!=0
//this is the parent process

이를 통해 상위 및 하위 항목에 대해 서로 다른 작업을 제공하고 멀티스레딩 기능을 사용할 수 있습니다.

fork()는 하위 프로세스를 작성하기 위해 사용됩니다.fork() 함수가 호출되면 새로운 프로세스가 생성되고 fork() 함수 호출은 자녀와 부모에 대해 다른 값을 반환합니다.

반환값이 0이면 자신이 하위 프로세스이고 반환값이 하위 프로세스 ID인 경우 사용자가 상위 프로세스임을 나타냅니다(음수인 경우 포크가 실패하여 하위 프로세스가 생성되지 않았습니다).

http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html

시스템 콜 포크()는 프로세스를 작성하기 위해 사용됩니다.인수를 사용하지 않고 프로세스 ID를 반환합니다.fork()의 목적은 발신자의 자녀 프로세스가 되는 새로운 프로세스를 작성하는 것입니다.새로운 자 프로세스가 생성되면 두 프로세스 모두 fork() 시스템 호출에 이은 다음 명령을 수행합니다.그러므로 우리는 부모와 아이를 구분해야 한다.이를 수행하려면 반환된 fork() 값을 테스트합니다.

fork()가 음의 값을 반환하는 경우 하위 프로세스를 생성하지 못했습니다.fork()는 새로 생성된 자식 프로세스에 0을 반환합니다.fork()는 부모에게 자식 프로세스의 프로세스 ID인 양의 값을 반환합니다.반환되는 프로세스 ID는 sys/types.h에서 정의된 pid_t 유형입니다.일반적으로 프로세스 ID는 정수입니다.또한 프로세스는 함수 getpid()를 사용하여 이 프로세스에 할당된 프로세스 ID를 가져올 수 있습니다.따라서 시스템이 fork()에 호출한 후 간단한 테스트를 통해 어떤 프로세스가 자식인지 판별할 수 있습니다.UNIX는 부모의 주소 공간을 정확하게 복사하여 자녀에게 제공한다는 점에 유의하시기 바랍니다.따라서 부모 프로세스와 자녀 프로세스에는 별도의 주소 공간이 있습니다.

위의 점을 명확히 하기 위해 예를 들어 이해합시다.이 예에서는 상위 프로세스와 하위 프로세스를 구분하지 않습니다.

#include  <stdio.h>
#include  <string.h>
#include  <sys/types.h>

#define   MAX_COUNT  200
#define   BUF_SIZE   100

void  main(void)
{
     pid_t  pid;
     int    i;
     char   buf[BUF_SIZE];

     fork();
     pid = getpid();
     for (i = 1; i <= MAX_COUNT; i++) {
          sprintf(buf, "This line is from pid %d, value = %d\n", pid, i);
          write(1, buf, strlen(buf));
     } 
}

위의 프로그램이 fork()에 대한 호출 지점까지 실행된다고 가정합니다.

fork() 호출이 정상적으로 실행되면 Unix는 주소 공간의 동일한 복사본을 2개 만듭니다.하나는 부모용이고 다른 하나는 자녀용입니다.두 프로세스 모두 fork() 호출 후 다음 문에서 실행을 시작합니다.이 경우 두 프로세스 모두 할당 시 실행을 시작합니다.

pid = .....;

두 프로세스 모두 시스템콜 포크() 직후부터 실행을 시작합니다.두 프로세스 모두 동일하지만 별도의 주소 공간이 있기 때문에 fork() 호출 전에 초기화된 변수는 두 주소 공간에서 동일한 값을 가집니다.모든 프로세스에는 자체 주소 공간이 있기 때문에 수정은 다른 프로세스와는 무관합니다.즉, 부모가 변수 값을 변경할 경우 수정 내용은 부모 프로세스의 주소 공간에 있는 변수에만 영향을 미칩니다.fork() 콜에 의해 작성된 다른 주소 공간은 변수 이름이 동일하더라도 영향을 받지 않습니다.

printf가 아닌 write를 사용하는 이유는 무엇입니까?이는 printf()가 "buffered"이기 때문입니다.즉, printf()는 프로세스의 출력을 그룹화합니다.부모 프로세스의 출력을 버퍼링하는 동안 자녀는 printf를 사용하여 일부 정보를 출력할 수도 있습니다.이 정보도 버퍼링됩니다.그 결과, 출력은 곧바로 화면에 송신되지 않기 때문에, 예상한 결과의 올바른 순서를 얻을 수 없는 경우가 있습니다.게다가 2개의 프로세스로부터의 출력은, 이상한 방법으로 혼재하는 경우가 있습니다.이 문제를 해결하려면 "버퍼되지 않은" 쓰기를 사용하는 것이 좋습니다.

이 프로그램을 실행하면 화면에 다음과 같은 내용이 표시될 수 있습니다.

................
This line is from pid 3456, value 13
This line is from pid 3456, value 14
     ................
This line is from pid 3456, value 20
This line is from pid 4617, value 100
This line is from pid 4617, value 101
     ................
This line is from pid 3456, value 21
This line is from pid 3456, value 22
     ................

프로세스 ID 3456은 부모 또는 자녀에게 할당된 프로세스 ID일 수 있습니다.이들 프로세스는 동시에 실행되기 때문에 출력 라인이 다소 예측 불가능한 방법으로 혼재됩니다.또, 이러한 회선의 순서는 CPU 스케줄러에 의해서 결정됩니다.따라서 이 프로그램을 다시 실행하면 전혀 다른 결과가 나올 수 있습니다.

먼저 포크() 시스템 호출에 대해 이해해야 합니다.설명하겠습니다

  1. fork() system call은 부모 프로세스의 완전한 복제를 만듭니다.부모 스택, 힙, 초기화되지 않은 데이터, 초기화되지 않은 데이터의 복제를 생성하여 부모 프로세스와 읽기 전용 모드로 코드를 공유합니다.

  2. Fork system call은 Copy-on-write(쓰기 시 복사) 기준으로 메모리를 복사합니다.이는 복사가 필요할 때 자녀가 가상 메모리 페이지를 작성하는 것을 의미합니다.

이제 fork()의 목적:

  1. Fork()는 서버가 여러 클라이언트를 처리해야 하는 것처럼 작업분할이 있는 장소에서 사용할 수 있기 때문에 부모는 정기적으로 연결을 수락해야 합니다.따라서 서버는 각 클라이언트에 대해 읽기와 쓰기를 수행합니다.

fork()와 새로운 프로세스를 시작하기 위한 exec() 함수를 갖는 것에 대한 근거는 UNIX 스택 교환에 관한 유사한 질문에 대한 답변으로 설명되어 있습니다.

기본적으로 포크가 현재 프로세스를 복사하기 때문에 프로세스에 대해 가능한 다양한 옵션이 기본적으로 모두 설정되므로 프로그래머는 이러한 옵션을 제공하지 않습니다.

반면 윈도 운영체제에서는 프로그래머는 CreateProcess 함수를 사용해야 합니다.CreateProcess 함수는 훨씬 더 복잡하고 새로운 프로세스의 파라미터를 정의하기 위해 다양한 구조를 입력해야 합니다.

즉, 포킹(이그제큐티브가 아닌)의 이유는 새로운 프로세스를 간단하게 작성할 수 있기 때문입니다.

fork()하위 프로세스를 생성하기 위해 사용됩니다.일반적으로 스레드와 유사한 상황에서 사용되지만 차이가 있습니다.스레드와는 unlike드 unlike unlike unlike unlikefork() 개별 전체가 즉, 복사되어 있는 자녀와 부모가 서로 직접 복사되어 것을 의미합니다.fork()호출됩니다.이것들은 완전히 분리되어 있고, 다른 프로그램의 메모리에 액세스하기 위해서 통상적인 트러블을 일으키지 않고는 다른 프로그램의 메모리에 액세스 할 수 없습니다.

fork()는 일부 서버 응용 프로그램(대부분 *NIX 머신에서 루트로 실행되며 사용자 요청을 처리하기 전에 권한을 삭제하는 응용 프로그램)에서 여전히 사용됩니다.아직 몇 가지 다른 사용 사례가 있지만, 지금은 대부분 멀티스레딩으로 전환했습니다.

원서를 작성할 때는 일상 프로그래밍에서 포크를 사용할 필요가 없을 수도 있습니다.

비록 당신이 당신의 프로그램이 어떤 작업을 하기 위해 다른 프로그램을 시작하기를 원하더라도, C나 perl의 "system"과 같이 뒤에서 포크를 사용하는 다른 간단한 인터페이스들이 있습니다.

예를 들어 어플리케이션이 bc 등의 다른 프로그램을 실행하여 계산을 수행하도록 하려면 '시스템'을 사용하여 실행할 수 있습니다.시스템은 새로운 프로세스를 생성하기 위해 'fork'를 수행하고 그 프로세스를 bc로 변환하기 위해 'exec'을 수행합니다.bc가 완료되면 시스템에 의해 프로그램이 제어됩니다.

다른 프로그램도 비동기적으로 실행할 수 있는데, 어떻게 실행했는지 기억이 안 나요.

서버, 셸, 바이러스 또는 운영체제를 쓰는 경우 포크를 사용할 가능성이 높습니다.

Fork()는 모든 본문이 작성한 새로운 프로세스를 작성하기 위해 사용됩니다.

여기 바이너리 트리 형태로 프로세스를 생성하는 코드가 있습니다.바이너리 트리에서 프로세스를 생성할 수 있는 레벨의 수를 스캔하도록 요구됩니다.

#include<unistd.h> 
#include<fcntl.h> 
#include<stdlib.h>   
int main() 
{
int t1,t2,p,i,n,ab;
p=getpid();                
printf("enter the number of levels\n");fflush(stdout);
scanf("%d",&n);                
printf("root %d\n",p);fflush(stdout);
for(i=1;i<n;i++)    
{        
    t1=fork();

    if(t1!=0)
        t2=fork();        
    if(t1!=0 && t2!=0)        
        break;            
    printf("child pid %d   parent pid %d\n",getpid(),getppid());fflush(stdout);
}   
    waitpid(t1,&ab,0);
    waitpid(t2,&ab,0);
return 0;
}

산출량

  enter the number of levels
  3
  root 20665
  child pid 20670   parent pid 20665
  child pid 20669   parent pid 20665
  child pid 20672   parent pid 20670
  child pid 20671   parent pid 20670
  child pid 20674   parent pid 20669
  child pid 20673   parent pid 20669

Fork는 새로운 프로세스를 만듭니다.포크가 없으면 init만 실행할 수 있는 Unix 시스템이 됩니다.

멀티프로세싱은 컴퓨팅의 핵심입니다.예를 들어, IE 또는 Firefox는 사용자가 인터넷을 탐색하는 동안 파일을 다운로드하는 프로세스를 생성할 수 있습니다.또는 워드프로세서로 문서를 인쇄하는 동안에도 다른 페이지를 보고 편집할 수 있습니다.

Fork() 시스템 호출을 사용하여 하위 프로세스를 만듭니다.이것은 부모 프로세스의 정확한 복제입니다.부모로부터 스택 섹션, 힙 섹션, 데이터 섹션, 환경 변수, 명령줄 인수를 포크 복사합니다.

참조: http://man7.org/linux/man-pages/man2/fork.2.html

fork() 함수는 호출된 기존 프로세스를 복제하여 새 프로세스를 생성하기 위해 사용됩니다.이 함수가 호출된 기존 프로세스가 상위 프로세스가 되고 새로 생성된 프로세스가 하위 프로세스가 됩니다.이미 언급한 바와 같이 자녀는 부모의 복사본이지만 일부 예외가 있습니다.

  • 자녀는 운영 체제에서 실행되는 다른 프로세스와 마찬가지로 고유한 PID를 가집니다.

  • 는 부모 있으며 프로세스 ID는 "PID"의.
    생성 과정입니다.

  • 하위 프로세스에서는 리소스 사용률 및 CPU 시간 카운터가 0으로 재설정됩니다.

  • 자에 있는 보류 중인 신호 세트가 비어 있습니다.

  • 자녀는 부모로부터 타이머를 상속받지 않습니다.

예:

    #include <unistd.h>
    #include <sys/types.h>
    #include <errno.h>
    #include <stdio.h>
    #include <sys/wait.h>
    #include <stdlib.h>

    int var_glb; /* A global variable*/

int main(void)
{
    pid_t childPID;
    int var_lcl = 0;

    childPID = fork();

    if(childPID >= 0) // fork was successful
    {
        if(childPID == 0) // child process
        {
            var_lcl++;
            var_glb++;
            printf("\n Child Process :: var_lcl = [%d], var_glb[%d]\n", var_lcl, var_glb);
        }
        else //Parent process
        {
            var_lcl = 10;
            var_glb = 20;
            printf("\n Parent process :: var_lcl = [%d], var_glb[%d]\n", var_lcl, var_glb);
        }
    }
    else // fork failed
    {
        printf("\n Fork failed, quitting!!!!!!\n");
        return 1;
    }

    return 0;
}

위의 코드가 컴파일되어 실행되면 다음과 같이 됩니다.

$ ./fork

Parent process :: var_lcl = [10], var_glb[20]

Child Process :: var_lcl = [1], var_glb[1]

Fork()는 부모에게 메모리 상태의 복사본을 공유하는 다른 프로세스를 만드는 방법으로 작성되었습니다.이전에는 이 기능이 없었던 타임슬라이싱 메인프레임 시스템에서 뛰어난 스레드 기능을 얻기 위해 가능한 최소한의 변경만 가능했기 때문에 이 방식은 그대로 작동합니다.또한 프로그램은 멀티프로세스가 되기 위해 거의 수정이 필요하지 않았습니다.fork()는 단순히 적절한 위치에 추가할 수 있기 때문에 상당히 우아합니다.기본적으로 fork()는 저항이 가장 적은 경로입니다.

원래 부모 프로세스의 메모리 공간 전체를 복사해야 했습니다.가상 메모리의 등장으로 인해 가상 메모리는 해킹되어 보다 효율적으로 변경되었으며 Copy-on-Write 메커니즘으로 인해 실제로 메모리를 복사할 필요가 없어졌습니다.

그러나 현재 최신 시스템에서는 부모 프로세스의 실제 힙을 공유하는 실제 스레드를 생성할 수 있습니다.현대의 멀티스레딩 프로그래밍 패러다임과 고급 언어에서는 fork()가 실제로 프로세스를 메모리를 통해 직접 통신하지 못하게 하고 느린 메시지 전달 메커니즘을 사용하도록 강제하기 때문에 실질적인 이점을 제공하는지 의문입니다.

언급URL : https://stackoverflow.com/questions/985051/what-is-the-purpose-of-fork

반응형