
fork(): 프로세스 생성 시 사용하는 함수이다.
기존 프로세스(부모)를 복제하여 새로운 프로세스(자식)를 만듭니다. fork 사용을 위해서는 <unistd.h> 를 include 해야 합니다. fork 함수는 unistd.h 파일에 system call로 정의되어 있습니다. 그리고 fork 함수 호출 이후 코드부터 각자의 메모리를 사용하여 실행됩니다.
처음에는 페이지를 공유하다가, 수정이 발생할 때 실제로 복사합니다.
따라서 파일 오프셋(lseek 위치), 파일 상태 플래그 등을 공유
목적: 하나의 작업을 둘로 나누어 동시에 처리 (속도 향상).
시나리오: 부모는 데이터를 수집하고, 자식은 수집된 데이터를 DB에 기록함.
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t pid = fork();
if (pid == 0) {
// [Child] 무거운 연산 담당
printf("[Child] 데이터 분석 중... (PID: %d)\n", getpid());
sleep(2); // 연산 시뮬레이션
printf("[Child] 분석 완료!\n");
} else if (pid > 0) {
// [Parent] 사용자 입력 대기 또는 UI 갱신
printf("[Parent] 다른 작업 수행 중... (PID: %d)\n", getpid());
}
return 0;
}

목적: 현재 프로세스를 유지하면서 다른 바이너리(ls, grep 등)를 실행.
시나리오: 쉘(Shell)이 명령어를 입력받아 실행하는 방식 (fork + exec).
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t pid = fork();
if (pid == 0) {
// [Child] 현재 메모리를 비우고 'ls' 명령어로 덮어씀
printf("[Child] 'ls -l' 실행\n");
execl("/bin/ls", "ls", "-l", NULL);
perror("execl failed"); // 실패 시만 실행됨
} else {
// [Parent] 자식이 끝날 때까지 대기
wait(NULL);
printf("[Parent] 자식 프로세스(명령어) 종료 확인 완료.\n");
}
return 0;
}

목적: 여러 클라이언트의 요청을 동시에 처리.
시나리오: 웹 서버(Apache 등)가 클라이언트가 접속(accept)할 때마다 전담 자식 프로세스를 생성.
// (의사 코드 - 핵심 로직 위주)
int server_fd = socket(...);
bind(server_fd, ...);
listen(server_fd, 5);
while(1) {
// 1. 클라이언트 연결 수락 (Blocking)
int client_fd = accept(server_fd, ...);
// 2. 연결 들어오면 즉시 fork
if (fork() == 0) {
// [Child] 이 클라이언트만 전담 처리
close(server_fd); // 자식은 듣기 소켓 필요 없음
process_request(client_fd);
close(client_fd);
exit(0); // 처리 후 자식 소멸
} else {
// [Parent] 즉시 다시 listen 모드로 복귀 (다른 클라이언트 받으러 감)
close(client_fd); // 부모는 핸들링 안 하므로 닫음
}
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <semaphore.h>
#define MAX_COUNT 100000
int main() {
int * g_count = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
sem_t * locker = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
*g_count = 0;
sem_init(locker, 1, 1);
printf("=== [Start] count를 시작합니다 (PID: %d) ===\n", getpid());
// 1. 여기서 프로세스가 복제됨 (세포 분열)
pid_t pid = fork();
// 2. 분기 처리 (복제된 직후)
if (pid < 0) {
perror("Fork 실패");
return 1;
}
if (pid == 0) {
for (int i = 0; i < MAX_COUNT; i++) {
sem_wait(locker);
(*g_count)++;
sem_post(locker);
}
printf("자식 실행 종료\n");
exit(0);
} else {
for (int i = 0; i < MAX_COUNT; i++) {
sem_wait(locker);
(*g_count)++;
sem_post(locker);
}
printf("자식이 끝날때까지 대기\n");
waitpid(pid, NULL, 0);
printf("자식 종료 확인\n");
printf("%d\n",*g_count);
munmap(g_count, sizeof(int));
munmap(locker, sizeof(sem_t));
}
return 0;
}

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <stdatomic.h>
#define MAX_COUNT 100000000
//spin lock방식으로 메모리 접근 제한
void lock(int* locker){
//lock이 1이면 무한 반복
while(*locker == 1){
}
//빠져나오면 자신이 lock을 검
*locker = 1;
}
void freelock(int* locker){
*locker = 0;
}
int main() {
atomic_int *g_count = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
int * locker = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
*g_count = 0;
*locker = 0;
printf("=== [Start] count를 시작합니다 (PID: %d) ===\n", getpid());
// 1. 여기서 프로세스가 복제됨 (세포 분열)
pid_t pid = fork();
// 2. 분기 처리 (복제된 직후)
if (pid < 0) {
perror("Fork 실패");
return 1;
}
if (pid == 0) {
for (int i = 0; i < MAX_COUNT; i++) {
(*g_count)++;
}
printf("자식 실행 종료\n");
exit(0);
} else {
for (int i = 0; i < MAX_COUNT; i++) {
(*g_count)++;
}
printf("자식이 끝날때까지 대기\n");
waitpid(pid, NULL, 0);
printf("자식 종료 확인\n");
printf("%d\n",*g_count);
munmap(g_count, sizeof(int));
munmap(locker, sizeof(int));
}
return 0;
}

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/mman.h>
#define MAX_COUNT 100000
/*
Q. 전역변수 int g_count=0;을 만들고, fork()를 이용 하여 2개의 프로세스가 전역변수를 같이 1씩 증가 시키려면?
- MAX_COUNT=100,000;
- 예상 결과값 : 100,000 ~200,000
*/
int g_count=0;
int main() {
int pipefd[2];
pipe(pipefd);
pid_t pid1= fork();
pid_t pid2= fork();
if (pid1 == 0 && pid2>0)
{
// [Child] 무거운 연산 담당
printf("[Child1] g_count++ 중... (PID: %d)\n", getpid());
while(1){
g_count++;
if(g_count>=MAX_COUNT) break;
}
printf("child1 > g_count=%d\n",g_count);
printf("[Child1] 완료!\n");
int my_count=g_count;
write(pipefd[1], &my_count, sizeof(int));
}
else if(pid1 >0 && pid2==0)
{
printf("[Child2] g_count++ 중... (PID: %d)\n", getpid());
while(1){
g_count++;
if(g_count>=MAX_COUNT) break;
}
printf("child2 > g_count=%d\n",g_count);
printf("[Child2] 완료!\n");
int my_count=g_count;
write(pipefd[1], &my_count, sizeof(int));
}
else if(pid1 >0 && pid2 >0)
{
// [Parent] 사용자 입력 대기 또는 UI 갱신
wait(NULL);
wait(NULL);
int child1_count, child2_count;
read(pipefd[0], &child1_count, sizeof(int));
read(pipefd[0], &child2_count, sizeof(int));
g_count = child1_count + child2_count;
printf("[Parent] 자식 프로세스 대기중 (PID: %d)\n", getpid());
printf("\n==========< 최종 parent > g_count=%d >============\n",g_count);
}
return 0;
}

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/mman.h>
#define MAX_COUNT 100000
/*
Q. 전역변수 int g_count=0;을 만들고, fork()를 이용 하여 2개의 프로세스가 전역변수를 같이 1씩 증가 시키려면?
- MAX_COUNT=100,000;
- 예상 결과값 : 100,000 ~200,000
*/
int g_count = 0;
int main()
{
int pipefd[2];
pipe(pipefd);
pid_t pid1 = fork();
if (pid1 == 0)
{
// [Child] 무거운 연산 담당
printf("[Child1] g_count++ 중... (PID: %d)\n", getpid());
while (1)
{
g_count++;
if (g_count >= MAX_COUNT)
break;
}
printf("child1 > g_count=%d\n", g_count);
printf("[Child1] 완료!\n");
int my_count = g_count;
write(pipefd[1], &my_count, sizeof(int));
}
else if (pid1 > 0)
{
pid_t pid2 = fork();
if (pid2 == 0)
{
printf("[Child2] g_count++ 중... (PID: %d)\n", getpid());
while (1)
{
g_count++;
if (g_count >= MAX_COUNT)
break;
}
printf("child2 > g_count=%d\n", g_count);
printf("[Child2] 완료!\n");
int my_count = g_count;
write(pipefd[1], &my_count, sizeof(int));
}
else
{
// [Parent] 사용자 입력 대기 또는 UI 갱신
wait(NULL);
wait(NULL);
int child1_count, child2_count;
read(pipefd[0], &child1_count, sizeof(int));
read(pipefd[0], &child2_count, sizeof(int));
g_count = child1_count + child2_count;
printf("[Parent] 자식 프로세스 대기중 (PID: %d)\n", getpid());
printf("\n==========< 최종 parent > g_count=%d >============\n", g_count);
}
}
return 0;
}

풀이 3 방법이 내가 풀었던 방법인데,
pid_t pid1= fork();
pid_t pid2= fork();
을 했을때, 프로세스가 4개 생성된다는 것을 이해를 못했다. 프로그램의 부모 pid까지 출력하고, sleep(500)을 건 다음, ps --ppid [부모 프로세스 pid] 를 통해 자식 프로세스를 확인해보았다.


확인해보니 프로세스가 4개 나와야 하지만 어떻게 설정하든 2개밖에 안 나와서 부모 프로세스 1개 + 자식 프로세스 2개 = 총 3개의 프로세스 이렇게 생성되는건가 헷갈렸으나,
처음에는 프로세스가 총 4개인게 맞고, 만들어진 프로세스 중에 조건에 해당되지 않는 프로세스는 코드 상에서 할 일이 없으니 빠르게 return 0;을 통해 종료되어 ps --ppid 명령어에 안 보인것이라고 한다.
기존 코드는 아래 과정을 통해 4개 생성
pid_t pid1 = fork(); // A → A, B (2개)
pid_t pid2 = fork(); // A, B 둘 다 fork → A, B, C, D (4개)
프로세스를 총 3개 만들기 위해서는
pid_t pid1 = fork(); // A → A, B (2개)
if (pid1 == 0) {
// 자식1(B)은 여기서 끝
}
else {
pid_t pid2 = fork(); // 부모(A)만 fork → A, B, C (3개)
}
이렇게 if-else 구조를 통해 자식1이 두 번째 fork()를 실행하지 않고, 부모만 자식2를 생성하므로 총 3개 프로세스만 생성된다.