Fork (فراخوان سیستمی)

در مباحث سیستم‌عامل، وقتی که یک فرایند منشعب  می‌شود، فرایند مورد نظر یک کپی از خودش ایجاد می‌کند. در سیستم‌عامل‌های شبه یونیکس این کار با استفاده از فراخوان سیستمی fork() انجام می‌شود. فرایند اصلی که fork() را صدا می‌زند فرایند پدر نامیده می‌شود و فرایند جدیدی که ایجاد شده فرایند فرزند نامیده می‌شود. این دو فرایند به غیر از موارد زیر دقیقاً مشابه یکدیگر هستند:
* فرایند فرزند یک شماره منحصربه‌فرد (PID) یکتا دارد که با فرایند والد متفاوت است.
* فرایند فرزند شماره PPID متفاوت با فرایند والد دارد. PPID نشان دهنده PID والد می‌باشد. بنابراین PPID فرایند فرزند با PID فرایند والد یکسان است.
* فرایند فرزند توصیف‌گرهای فایل مخصوص به خود را دارد که البته آنها را از فرایند پدر به ارث می‌برد. این توصیف‌گرها هر دو به یک شی اشاره می‌کنند و بنابراین اگر فرایند فرزند lseek(2) را بر روی یک توصیف‌گر فایل اجرا کند، این کار اجرای read(2) یا write(2) در فرایند پدر را تحت‌الشعاع قرار می‌دهد.
* تمام تایمرها صفر می‌شوند.

## بررسی fork()
این فراخوان سیستمی که در فایل unistd.h تعریف شده، به محض اجرا سه نوع مقدار برمی‌گرداند.
* در صورتی که عملیات با شکست مواجه شود و فرایندها نتوانند منشعب شوند، مقدار -۱ برگشت داده می‌شود.
* در صورتی که مقدار صفر برگردد، یعنی عملیات با موفقیت انجام شده و پروسه فرزند شروع به اجرا شدن می‌کند.
* در صورتی که مقداری بزرگتر از صفر برگردد، یعنی عملیات با موفقیت انجام شده و پروسه والد شروع به اجرا شدن می‌کند. در این حالت مقدار برگشتی در حقیقت همان PID پروسه فرزند است.

این مقادیر برگشتی باید با یک شرط if کنترل شوند تا بتوان تشخیص داد که کدام پروسه (فرزند یا پدر) در حال اجراست. اینکه کدام پروسه در ابتدا اجرا شود، بستگی به زمان‌بند سیستم‌عامل دارد. اما می‌توان با بررسی کردن مقدار برگشتی fork() تعیین کرد که پروسه فرزند بعد از ایجاد شدن چه کاری را انجام دهد.

## مثال از اجرای fork()

```c
#include <stdio.h>   /* printf, stderr, fprintf */
#include <sys/types.h> /* pid_t */
#include <unistd.h>  /* _exit, fork */
#include <stdlib.h>  /* exit */
#include <errno.h>   /* errno */

int main(void)
{
   pid_t  pid;

   /* Output from both the child and the parent process
    * will be written to the standard output,
    * as they both run at the same time.
    */
   pid = fork();

   if (pid == -1)
   {
      /* Error:
       * When fork() returns -1, an error happened
       * (for example, number of processes reached the limit).
       */
      fprintf(stderr, "can't fork, error %d\n", errno);
      exit(EXIT_FAILURE);
   }
   else if (pid == 0)
   {
      /* Child process:
       * When fork() returns 0, we are in
       * the child process.
       */
      int  j;
      for (j = 0; j <10; j++)
      {
         printf("child: %d\n", j);
         sleep(1);
      }
      _exit(0);  /* Note that we do not use exit() */
   }
   else
   {
      /* When fork() returns a positive number, we are in the parent process
       * (the fork return value is the PID of the newly created child process)
       * Again we count up to ten.
       */
      int  i;
      for (i = 0; i <10; i++)
      {
         printf("parent: %d\n", i);
         sleep(1);
      }
      exit(0);
   }
   return 0;
}
```


## جستارهای وابسته
* فورک بمب
* exec (فراخوان سیستمی) تصویر فرایند فعلی را با برنامه‌ای دیگر جایگزین می‌کند.

## منابع
ویکی انگلیسی

رده:فراخوان‌های سیستمی
رده:فرایند (رایانه)
رده:کتابخانه پازیکس سی