your programing

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

lovepro 2020. 10. 7. 08:02
반응형

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


Linux의 많은 프로그램과 man 페이지에서 fork(). 우리는 왜 사용해야 fork()하며 그 목적은 무엇입니까?


fork()Unix에서 새로운 프로세스를 만드는 방법입니다. 전화를 걸면 fork자체 주소 공간 이있는 자체 프로세스의 복사본을 만드는 것 입니다. 이를 통해 여러 작업이 마치 각자가 시스템의 전체 메모리를 가지고있는 것처럼 서로 독립적으로 실행할 수 있습니다.

다음은의 몇 가지 사용 예입니다 fork.

  1. 귀하의 사용은 fork명령 줄에서 호출하는 프로그램을 실행합니다.
  2. Apache 와 같은 웹 서버는 fork각각 자체 주소 공간에서 요청을 처리하는 여러 서버 프로세스를 만드는 데 사용 됩니다. 하나가 죽거나 메모리가 누수 되더라도 나머지는 영향을받지 않으므로 내결함성을위한 메커니즘으로 작동합니다.
  3. Google 크롬fork별도의 프로세스 내에서 각 페이지를 처리 하는 데 사용 합니다. 이렇게하면 한 페이지의 클라이언트 측 코드가 전체 브라우저를 다운시키는 것을 방지 할 수 있습니다.
  4. forkMPI를 사용하여 작성된 것과 같은 일부 병렬 프로그램에서 프로세스를 생성하는 데 사용됩니다 . 이는 자체 주소 공간이없고 프로세스 내에 존재 하는 스레드 사용과 다릅니다 .
  5. 스크립팅 언어는 fork간접적으로 자식 프로세스를 시작합니다. 예를 들어 subprocess.PopenPython에서 와 같은 명령을 사용할 때마다 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);
}

셸은를 사용하여 자식 프로세스를 생성하고 exec완료 될 때까지 기다린 다음 자체 실행을 계속합니다. 이런 식으로 포크를 사용할 필요는 없습니다. 병렬 프로그램이 할 수있는 것처럼 항상 많은 자식 프로세스를 생성 할 수 있으며 각 프로세스는 동시에 프로그램을 실행할 수 있습니다. 기본적으로 Unix 시스템에서 새 프로세스를 만들 때마다 fork(). Windows에 해당하는 경우 CreateProcess.

더 많은 예와 더 긴 설명을 원한다면 Wikipedia 에 적절한 요약이 있습니다. 그리고 여기에 몇 가지 슬라이드는 어떻게 여기에 현대적인 운영 시스템의 프로세스, 스레드 및 동시 작동합니다.


fork ()는 유닉스가 새로운 프로세스를 만드는 방법입니다. fork ()를 호출 한 시점에서 프로세스가 복제되고 두 개의 다른 프로세스가 거기에서 실행을 계속합니다. 그 중 하나 인 자식은 fork ()가 0을 반환합니다. 다른 하나 인 부모는 fork ()가 자식의 PID (프로세스 ID)를 반환합니다.

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

$ telnetd &

새 프로세스를 만드는 이유는 운영 체제가 동시에 많은 작업을 수행 할 수있는 방법입니다. 프로그램을 실행할 수 있고, 실행 중일 때 다른 창으로 전환하여 다른 작업을 수행 할 수있는 이유입니다.


fork ()는 자식 프로세스를 만드는 데 사용됩니다. fork () 함수가 호출되면 새 프로세스가 생성되고 fork () 함수 호출은 자식과 부모에 대해 다른 값을 반환합니다.

반환 값이 0이면 자신이 자식 프로세스이고 반환 값이 숫자 (하위 프로세스 ID)이면 부모임을 알 수 있습니다. (음수이면 포크가 실패하고 자식 프로세스가 생성되지 않았습니다)

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


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


fork ()는 기본적으로이 함수를 호출하는 프로세스에 대한 자식 프로세스를 만드는 데 사용됩니다. fork ()를 호출 할 때마다 자식 ID에 대해 0을 반환합니다.

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

이를 통해 부모와 자식에 대해 서로 다른 작업을 제공하고 멀티 스레딩 기능을 사용할 수 있습니다.


응용 프로그램을 작성하는 경우 일상적인 프로그래밍에서 포크를 사용할 필요가 없습니다.

프로그램이 어떤 작업을 수행하기 위해 다른 프로그램을 시작하도록하려는 경우에도 C 및 Perl의 "system"과 같이 배후에서 포크를 사용하는 다른 간단한 인터페이스가 있습니다.

예를 들어, 응용 프로그램이 bc와 같은 다른 프로그램을 시작하여 계산을 수행하도록하려면 'system'을 사용하여 실행할 수 있습니다. 시스템은 새로운 프로세스를 생성하기 위해 '포크'를 수행 한 다음 해당 프로세스를 bc로 전환하기 위해 'exec'를 수행합니다. BC가 완료되면 시스템이 프로그램에 제어권을 반환합니다.

다른 프로그램을 비동기 적으로 실행할 수도 있지만 방법을 기억할 수 없습니다.

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


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


System call fork() is used to create processes. It takes no arguments and returns a process ID. The purpose of fork() is to create a new process, which becomes the child process of the caller. After a new child process is created, both processes will execute the next instruction following the fork() system call. Therefore, we have to distinguish the parent from the child. This can be done by testing the returned value of 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는 두 개의 동일한 주소 공간 복사본을 만듭니다. 하나는 부모 용이고 다른 하나는 자식 용입니다. 두 프로세스 모두 fork () 호출 다음에 오는 다음 문에서 실행을 시작합니다. 이 경우 두 프로세스 모두 할당에서 실행을 시작합니다.

pid = .....;

두 프로세스 모두 시스템 호출 fork () 직후에 실행을 시작합니다. 두 프로세스 모두 동일하지만 별도의 주소 공간이 있으므로 fork () 호출 전에 초기화 된 변수는 두 주소 공간에서 동일한 값을 갖습니다. 모든 프로세스에는 고유 한 주소 공간이 있으므로 수정 사항은 다른 프로세스와 독립적입니다. 즉, 부모가 변수의 값을 변경하면 수정은 부모 프로세스의 주소 공간에있는 변수에만 영향을줍니다. fork () 호출에 의해 생성 된 다른 주소 공간은 동일한 변수 이름을 가지고 있어도 영향을받지 않습니다.

printf 대신 쓰기를 사용하는 이유는 무엇입니까? 이는 printf ()가 "버퍼링"되어 있기 때문입니다. 이는 printf ()가 프로세스의 출력을 함께 그룹화한다는 것을 의미합니다. 부모 프로세스에 대한 출력을 버퍼링하는 동안 자식은 또한 printf를 사용하여 버퍼링 될 일부 정보를 인쇄 할 수 있습니다. 결과적으로 출력이 즉시 화면으로 전송되지 않으므로 예상 결과의 올바른 순서를 얻지 못할 수 있습니다. 더 나쁜 것은 두 프로세스의 출력이 이상한 방식으로 혼합 될 수 있다는 것입니다. 이 문제를 극복하기 위해 "언 버퍼 드"쓰기 사용을 고려할 수 있습니다.

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

................
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은 상위 또는 하위에 할당 된 것일 수 있습니다. 이러한 프로세스가 동시에 실행되기 때문에 출력 라인이 예측할 수없는 방식으로 혼합됩니다. 또한 이러한 행의 순서는 CPU 스케줄러에 의해 결정됩니다. 따라서이 프로그램을 다시 실행하면 완전히 다른 결과를 얻을 수 있습니다.


다중 처리는 컴퓨팅의 핵심입니다. 예를 들어, IE 또는 Firefox는 인터넷을 검색하는 동안 파일을 다운로드하는 프로세스를 생성 할 수 있습니다. 또는 워드 프로세서에서 문서를 인쇄하는 동안에도 여전히 다른 페이지를 보면서 일부 편집 작업을 수행 할 수 있습니다.


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()자식 프로세스를 생성하는 데 사용됩니다. 일반적으로 스레딩과 비슷한 종류의 상황에서 사용되지만 차이점이 있습니다. 스레드와 달리 fork()전체 분리 된 프로세스를 생성합니다. 즉, fork()호출 된 지점에서 자식과 부모가 서로의 직접 복사 본인 동안 완전히 분리되어 있고 다른 사람의 메모리 공간에 액세스 할 수 없습니다 (정상적인 문제로 이동하지 않음). 다른 프로그램의 메모리에 액세스합니다).

fork() is still used by some server applications, mostly ones that run as root on a *NIX machine that drop permissions before processing user requests. There are some other usecases still, but mostly people have moved to multithreading now.


First one needs to understand what is fork () system call. Let me explain

  1. fork() system call creates the exact duplicate of parent process, It makes the duplicate of parent stack, heap, initialized data, uninitialized data and share the code in read-only mode with parent process.

  2. Fork system call copies the memory on the copy-on-write basis, means child makes in virtual memory page when there is requirement of copying.

Now Purpose of fork():

  1. Fork() can be used at the place where there is division of work like a server has to handle multiple clients, So parent has to accept the connection on regular basis, So server does fork for each client to perform read-write.

Fork() system call use to create a child process. It is exact duplicate of parent process. Fork copies stack section, heap section, data section, environment variable, command line arguments from parent.

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


The fork() function is used to create a new process by duplicating the existing process from which it is called. The existing process from which this function is called becomes the parent process and the newly created process becomes the child process. As already stated that child is a duplicate copy of the parent but there are some exceptions to it.

  • The child has a unique PID like any other process running in the operating system.

  • The child has a parent process ID which is same as the PID of the
    process that created it.

  • Resource utilization and CPU time counters are reset to zero in child process.

  • Set of pending signals in child is empty.

  • Child does not inherit any timers from its parent

Example :

    #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;
}

Now, when the above code is compiled and run :

$ ./fork

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

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

The rationale behind fork() versus just having an exec() function to initiate a new process is explained in an answer to a similar question on the unix stack exchange.

Essentially, since fork copies the current process, all of the various possible options for a process are established by default, so the programmer does not have supply them.

In the Windows operating system, by contrast, programmers have to use the CreateProcess function which is MUCH more complicated and requires populating a multifarious structure to define the parameters of the new process.

So, to sum up, the reason for forking (versus exec'ing) is simplicity in creating new processes.

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

반응형