The fork() function in C is used for creating a new process in Linux and Unix systems. It allows you to create a child process that runs concurrently with the process that makes the fork() call (which is the parent process). 

Here’s the basic syntax:

#include <unistd.h> 
 pid_t fork(void);

The unistd.h header file, commonly used in C and C++ programming languages, provides access to the POSIX operating system API. Let’s break down its significance:

Definition and Purpose:
unistd.h stands for “Unix Standard Header”.
It serves as a bridge between your program and the underlying operating system, enabling interaction with system resources and services.
The header file contains function prototypes, macros, and constants that allow your program to communicate with the operating system.
Functionality:The interface defined by unistd.h includes various system call wrapper functions and I/O primitives.
Some notable functions and features provided by unistd.h:
fork: Creates a new process by duplicating the address space of the parent process.
pipe: Establishes inter-process communication via a pipe.
read and write: Perform input and output operations.
close: Closes a file descriptor.
dup and dup2: Duplicate file descriptors.
chdir and fchdir: Change the working directory.
getpid: Retrieves the process ID.
link and linkat: Create hard links.
lseek: Reposition the read/write file offset.
pipe2: Creates a pipe with additional options.  And more...............

The fork() function takes no parameters and returns an integer value.
The possible return values are as follows:
Negative Value: The creation of a child process was unsuccessful.
Zero: Returned to the newly created child process.
Positive Value: Returned to the parent or caller. The value contains the process ID (PID) of the newly created child process.
Here’s how it works:
The fork() system call creates a new process by duplicating the address space of the original process.
The existing process becomes the parent process, and the newly created process is called the child process.
The child process inherits the same code, data, and file descriptors from the parent process.
After forking, you can use the exec() family of functions to replace the child process’s memory space with a new program.
The exec() function loads a new program into the child process, effectively replacing its code and data.
This technique allows you to create a new process with different functionality from the parent process.
Example:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
    pid_t p = fork();

    if (p < 0) {
        perror("fork failed");
        exit(1);
    } else if (p == 0) {
        printf("Hello from Child! (PID: %d)\n", getpid());
    } else {
        printf("Hello from Parent! (Child PID: %d)\n", p);
    }
    return 0;
}
Output:
Hello from Parent! (Child PID: 12345) 
Hello from Child! (PID: 12346)

In this example, the parent process creates a child process using fork(). The child process runs concurrently with the parent process, and both print their respective messages along with their process IDs.
Remember that the fork() system call creates a child process with an exact copy of the address space, including the program counter, CPU registers, and open files. The child process then continues executing from where the fork() call occurred.
