fork - whdlgp/system_programming_pra GitHub Wiki

λ¦¬λˆ…μŠ€ ν™˜κ²½μ—μ„œ λ©€ν‹° ν”„λ‘œμ„ΈμŠ€λ‘œ 돌리기

λ‚΄κ°€ 주둜 μ“°λ˜ RTOS ν™˜κ²½μ—μ„œλŠ” μ“°λž˜λ“œ(ν…ŒμŠ€ν¬) ν•˜λ‚˜λŠ” λ¬΄ν•œλ°˜λ³΅λ¬Έ μ΄μ—ˆκ³ , μŠ€μΌ€μ€„λŸ¬λŠ” μš°μ„ μˆœμœ„μ— μ˜ν•΄ μ–΄λ–€ ν…ŒμŠ€ν¬λ₯Ό μ‹€ν–‰μ‹œν‚¬μ§€ κ²°μ •ν•˜λŠ” λΉ„μ„ μ ν˜• 방식 μ΄μ—ˆλ‹€.

그런데 λ¦¬λˆ…μŠ€ ν™˜κ²½μ—μ„œ μ‚¬μš©ν•˜λŠ” forkλΌλŠ” λ…€μ„μ˜ λ™μž‘μ€ λ‚΄κ°€ μƒκ°ν•˜λ˜ λ©€ν‹° ν”„λ‘œμ„ΈμŠ€ ν”„λ‘œκ·Έλž˜λ° ν•˜κ³  쑰금 λŠλ‚Œμ΄ λ‹¬λžλ‹€. ν•˜λ‚˜μ˜ ν”„λ‘œμ„ΈμŠ€κ°€ λŒλ‹€κ°€, forkλΌλŠ” ν•¨μˆ˜λ₯Ό λ§Œλ‚  경우 μŠ¬λΌμž„λ§ˆλƒ₯ λΆ„μ—΄ν•œλ‹€. μ΄λ•Œ μ›λž˜ 돌던 ν”„λ‘œμ„ΈμŠ€λŠ” λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ 되고, λΆ„μ—΄λœ ν”„λ‘œμ„ΈμŠ€λŠ” λΆ„μ—΄μ „ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ 기얡을 가지고 μžˆλŠ” μžμ‹ν”„λ‘œμ„ΈμŠ€κ°€ λœλ‹€(μ§•κ·ΈλŸ½;).

fork의 리턴값은 λ‹€μŒκ³Ό κ°™λ‹€.

  • μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” 0의 리턴값을 λ°›λŠ”λ‹€.
  • λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ pid(ν”„λ‘œμ„ΈμŠ€ ID)λ₯Ό λ°›λŠ”λ‹€.
  • 뢄열이 잘 μ•ˆλ˜λ©΄ -1

fork1

#include <stdio.h>

int main(void)
{
	int pid;
	printf("[%d] process start \n", getpid());

	pid = fork();
	printf("[%d] process : return value %d \n", getpid(), pid);

	return 0;
}

μ‹€ν–‰ν•˜λ©΄ λŒ€μΆ© λ‹€μŒκ³Ό 같이 λ‚˜μ˜¨λ‹€.

[4044] process start 
[4044] process : return value 4045 
[4045] process : return value 0 

첫번째 printf λ¬Έμ—μ„œ ν˜„μ œ 돌고 μžˆλŠ” ν”„λ‘œμ„ΈμŠ€μ˜ pid 값을 보여쀀닀.
λ‘λ²ˆμ§Έ printf 문은 λΆ€λͺ¨, μžμ‹μ΄ λ‚˜λ‰˜μ–΄μ Έμ„œ, λΆ€λͺ¨μͺ½μ€ μžμ‹μͺ½(4045) pid 값을 fork의 λ¦¬ν„΄κ°’μœΌλ‘œ λ°›λŠ” 것을 λ³Ό 수 μžˆλ‹€. λΆ„μ—΄λœ μžμ‹μ€ 0의 리턴값을 λ°›λŠ”λ‹€.

fork2

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	int pid;

	pid = fork();

	if(pid == 0)//μžμ‹ ν”„λ‘œμ„ΈμŠ€
	{
		printf("[child] : Hello, world pid = %d \n", getpid());
	}
	else // λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€
	{
		printf("[parent] : Hello, world pid = %d \n", getpid());
	}

	return 0;
}
[parent] : Hello, world pid = 5243 
[child] : Hello, world pid = 5244 

μ΄λ²ˆμ—” fork의 리턴값을 μ‘μš©ν•˜μ—¬, λΆ€λͺ¨μ™€ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ„œλ‘œ λ‹€λ₯Έ 일을 ν•˜κ²Œλ” λ§Œλ“œλŠ” μ˜ˆμ œλ‹€. if 문을 μ΄μš©ν•˜μ—¬ fork의 리턴값이 0일땐 μžμ‹, λ‹€λ₯Έκ°’(μžμ‹ pid) 일땐 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ 일둜 λ‚˜λˆ΄λ‹€.

fork3

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
	int pid1, pid2;
	
	pid1 = fork();

	if(pid1 == 0)
	{
		printf("[child 1] Hello, world! pid = %d\n", getpid());
		exit(0);
	}

	pid2 = fork();
	
	if(pid2 == 0)
	{
		printf("[child 2] Hello, world! pid = %d\n", getpid());
		exit(0);
	}

	return 0;
}

μ΄λ²ˆμ—” forkλ₯Ό λ‘λ²ˆ μ‚¬μš©ν•˜μ˜€λ‹€.

[child 1] Hello, world! pid = 5368
[child 2] Hello, world! pid = 5369   

첫번째 fork ν›„ 첫번째 μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μƒμ„±λ˜μ–΄ printf λ¬Έ 좜λ ₯ν›„ μ’…λ£Œν•œλ‹€.
λ‘λ²ˆμ§Έ fork ν›„ λ‘λ²ˆμ§Έ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μƒμ„±λ˜μ–΄ printf λ¬Έ 좜λ ₯ν›„ μ’…λ£Œν•œλ‹€.
μ΄λ•Œ λ‘˜λ‹€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œ λΆ„μ—΄λœ ν”„λ‘œμ„ΈμŠ€μ΄λ‹€.

forkwait

μ΄λ²ˆμ—” λΆ€λͺ¨ μžμ‹κ°„μ˜ μ„ ν˜•ν™”(μ΄λ ‡κ²Œ ν‘œν˜„ν•΄λ„ λ˜λŠ”μ§€λŠ” λͺ¨λ₯΄κ² λ‹€.)λ₯Ό μœ„ν•΄ wait λΌλŠ” ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄ λ³Έλ‹€.
λΆ€λͺ¨, μžμ‹ ν”„λ‘œμ„ΈμŠ€λ‘œ λ‚˜λˆŒλ–„ λ§Œμ•½ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ λ¨Όμ € μ’…λ£Œλ  경우, μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” κ³ μ•„ ν”„λ‘œμ„ΈμŠ€κ°€ λœλ‹€κ³  ν•œλ‹€(히읡;). λ•Œλ¬Έμ— μ™ λ§Œν•˜λ©΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€ λΆ€ν„° 죽이고 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λ₯Ό μ£½μ΄λŠ”κ²Œ μ’‹λ‹€κ³  ν•œλ‹€. waitλŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ£½μ„λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦¬λŠ” ν•¨μˆ˜λΌκ³  보면 λœλ‹€.

wait 의 경우 κ°€μž₯ λ¨Όμ € 죽은 μžμ‹ ν”„λ‘œμ„ΈμŠ€ 순으둜 μ§„ν–‰λœλ‹€.

예제λ₯Ό λ³΄λŠ”κ²Œ λ‚«λ‹€.

#include <stdio.h>
#include <stdlib.h>
#include <wait.h>

int main(void)
{
	int pid, child, status;

	printf("[%d] parent process start\n", getpid());

	pid = fork();

	if(pid == 0)
	{
		printf("[%d] child process start\n", getpid());
		exit(1);
	}

	child = wait(&status);//1 -> 1 0000 0000 == 256
	printf("[%d] child process %d exit\n", getpid(), child);
	printf("\t exit code %d\n", status >> 8);
}
[5519] parent process start
[5520] child process start
[5519] child process 5520 exit
	 exit code 1

fork ν›„ μžμ‹ ν”„λ‘œμ„ΈμŠ€ κ΅¬κ°„μ—μ„œ exit(1)둜 exitλΌλŠ” ν•¨μˆ˜μ— 1을 λ„£μ–΄μ£Όκ³  μ’…λ£Œν–ˆλ‹€. λ„£μ–΄μ€€ 1은 wait ν•¨μˆ˜μ—μ„œ 인자 status둜 μ „λ‹¬ν•˜λŠ”λ°, μ „λ‹¬ν•˜λŠ” κ³Όμ •μ—μ„œ 쑰금 μ΄μƒν•˜κ²Œ μ „λ‹¬λœλ‹€. 1을 μ „λ‹¬ν•˜λ©΄ 1의 8승(1을 μ™Όμͺ½μœΌλ‘œ 8번 μ‰¬ν”„νŠΈ)의 값이 μ „λ‹¬λœλ‹€. 1μ£Όλ©΄ 256의 값이 status에 μ €μž₯λœλ‹€.

λ§Œμ•½ λ§ˆμ§€λ§‰

printf("\t exit code %d\n", status >> 8);

μ—μ„œ >> 8 을 해주지 μ•Šμ„ 경우 256이 좜λ ₯ 될 것이닀.

wait의 λ°˜ν™˜κ°’μ€ μ’…λ£Œλœ μžμ‹ ν”„λ‘œμ„ΈμŠ€ 이며, 잘 μ’…λ£Œκ°€ μ•ˆλ˜κ±°λ‚˜ ν•˜λ©΄ -1이 λ°˜ν™˜λœλ‹€.

wait와 waitpid

wait(μƒνƒœκ°’ μ €μž₯ν•  버퍼 포인터)

μž„μ˜λ‘œ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ€‘ μ•„λ¬΄κ±°λ‚˜ 죽으면 λ°˜ν™˜λ˜λŠ” ν•¨μˆ˜.
예둜 statusλΌλŠ” 버퍼에 μž„μ˜λ‘œ 죽은 μžμ‹μ˜ 값을 μ €μž₯ν•œλ‹€λ©΄

int status;

wait(&status);

와 같이 μ‚¬μš©ν•˜λ©΄ λœλ‹€.

waitpid(pidκ°’, μƒνƒœκ°’ μ €μž₯ν•  버퍼 포인터, μ˜΅μ…˜)

pidκ°’

  • 0 : ν˜„μ œ μžμ‹ μ˜ κ·Έλ£Ήκ³Ό 같은 μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό κΈ°λ‹€λ¦°λ‹€.
  • -1 : μž„μ˜λ‘œ 아무 μžμ‹ ν”„λ‘œμ„ΈμŠ€λ‚˜ μ£½λŠ”μ§€ κΈ°λ‹€λ¦°λ‹€.
  • μ–‘μˆ˜(pidκ°’) : 인자둜 λ„£μ–΄μ€€ pid λ₯Ό 가진 μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ£½λŠ”μ§€ κΈ°λ‹€λ¦°λ‹€.

μ˜΅μ…˜

  • 0 : μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ£½μ„λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦°λ‹€.
  • WNOHANG : μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ£½μ„λ•ŒκΉŒμ§€ 기닀리지 μ•ŠλŠ”λ‹€.
    μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ‚΄μ•„μžˆμœΌλ©΄ 0을 λ°˜ν™˜ν•œλ‹€.
    μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ£½μ—ˆμœΌλ©΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ pid 값을 λ°˜ν™˜ν•œλ‹€.
⚠️ **GitHub.com Fallback** ⚠️