😎 κ³΅λΆ€ν•˜λŠ” μ§•μ§•μ•ŒνŒŒμΉ΄λŠ” μ²˜μŒμ΄μ§€?

[ν”„λ‘œμ„ΈμŠ€μ™€ μŠ€λ ˆλ“œ 닀쀑 처리] ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œμ™€ 생성, μ’…λ£Œ λŒ€κΈ° λ³Έλ¬Έ

πŸ‘©‍πŸ’» IoT (Embedded)/Raspberry Pi

[ν”„λ‘œμ„ΈμŠ€μ™€ μŠ€λ ˆλ“œ 닀쀑 처리] ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œμ™€ 생성, μ’…λ£Œ λŒ€κΈ°

μ§•μ§•μ•ŒνŒŒμΉ΄ 2024. 1. 11. 18:25
728x90
λ°˜μ‘ν˜•

<μ„œμ˜μ§„ λ‹˜μ˜ 사물인터넷을 μœ„ν•œ λ¦¬λˆ…μŠ€ ν”„λ‘œκ·Έλž˜λ° with λΌμ¦ˆλ² λ¦¬νŒŒμ΄ μ„œμ μ„ μ°Έκ³ ν•΄μ„œ μž‘μ„±ν•˜μ˜€μŠ΅λ‹ˆλ‹€ :-)>

 

⭐ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œ

Cμ–Έμ–΄μ˜ main() ν•¨μˆ˜λŠ” int ν˜•μ˜ λ°˜ν™˜κ°’ κ°–λŠ”λ‹€

μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ’…λ£Œλ˜λ©΄ μ‹€ν–‰ κ²°κ³Όλ₯Ό μš΄μ˜μ²΄μ œμ— λ°˜ν™˜ν•˜κ³  κ·Έ μš΄μ˜μ²΄μ œλŠ” κ·Έ ν”„λ‘œμ„ΈμŠ€κ°€ μ—΄μ—ˆλ˜ (open ν•¨μˆ˜) 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό λͺ¨λ‘ λ‹«λŠ”λ‹€ (close ν•¨μˆ˜)

ν”„λ‘œμ„ΈμŠ€κ°€ μ°¨μ§€ν•˜κ³  μžˆλ–€ λ©”λͺ¨λ¦¬λ₯Ό κ°€μš© λ©”λͺ¨λ¦¬ ν’€ (pool) 둜 λ°˜ν™˜ν•˜κ²Œ λœλ‹€

 

μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ’…λ£Œν•  λ•Œ main() ν•¨μˆ˜μ—μ„œ return 으둜 λ°˜ν™˜ν•˜λŠ” 경우 μžλ™μ μœΌλ‘œ exit() ν•¨μˆ˜κ°€ ν˜ΈμΆœλœλ‹€

exit() ν•¨μˆ˜λŠ” 파일 μŠ€νŠΈλ¦Όμ— λŒ€ν•΄μ„œλ„ λ™μΌν•œ μž‘μ—…μ„ μˆ˜ν–‰, μ—΄λ € μžˆλŠ” 파일의 μŠ€νŠΈλ¦Όμ— λŒ€ν•΄μ„œλŠ” fclose() ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•΄μ„œ 버퍼에 남은 데이터λ₯Ό λͺ¨λ‘ 좜λ ₯ (flush) ν•œλ‹€

 

⭐ ν”„λ‘œμ„ΈμŠ€μ˜ 생성

λ¦¬λˆ…μŠ€κ°€ 처음 λΆ€νŒ…λ˜λ©΄, λ¦¬λˆ…μŠ€ 컀널이 직접 처음 ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•œ ν›„ λ‹€μŒ ν”„λ‘œμ„ΈμŠ€λΆ€ν„°λŠ” 이전 ν”„λ‘œμ„ΈμŠ€λ₯Ό λ³΅μ‚¬ν•΄μ„œ μ‚¬μš©λœλ‹€

fork() ν•¨μˆ˜λŠ” ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•˜λŠ”λ°, ν˜ΈμΆœν•œ ν”„λ‘œμ„ΈμŠ€μ™€ λ™μΌν•œ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒˆλ‘œ μƒμ„±ν•˜μ—¬ μƒˆλ‘œμš΄ ν”„λ‘œμ„ΈμŠ€ ID λ₯Ό ν• λ‹Ήν•œλ‹€

μƒˆλ‘œ μƒμ„±ν•œ ν”„λ‘œμ„ΈμŠ€λŠ” λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λ₯Ό κ°€μ§€κ²Œ λ˜λŠ”λ°, 자기 μžμ‹ μ€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ λœλ‹€

exec() ν•¨μˆ˜λŠ” ν”„λ‘œμ„ΈμŠ€μ˜ 곡간에 μƒˆλ‘œμš΄ ν”„λ‘œκ·Έλž¨μ˜ λ°”μ΄λ„ˆλ¦¬ μ½”λ“œλ₯Ό μ˜¬λ €μ„œ, ν”„λ‘œμ„ΈμŠ€μ˜ λ‚΄μš©μ„ μƒˆλ‘œ λ³€κ²½ν•˜μ§€λ§Œ ν”„λ‘œμ„ΈμŠ€ ID λŠ” λ³€κ²½λ˜μ§€ μ•ŠλŠ”λ‹€

 

β˜‘οΈ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ λ©”λͺ¨λ¦¬ 곡간

컀널은 μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μƒμ„±λ˜λ©΄ ν”„λ‘œμ„ΈμŠ€ ν…Œμ΄λΈ”μ— λ“±λ‘ν•˜κ³  λ©”λͺ¨λ¦¬λ₯Ό ν• λ‹Ήν•œλ‹€

ν”„λ‘œμ„ΈμŠ€κ°€ μƒμ„±λ˜λ©΄, μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” ν…μŠ€νŠΈ μ˜μ—­μ€ κ³΅μœ ν•˜κ³  데이터, νž™, μŠ€νƒ μ˜μ—­μ€ 볡사함

fork() ν•¨μˆ˜λ₯Ό μˆ˜ν–‰ν•œ 후에 λ°”λ‘œ exec() ν•¨μˆ˜κ°€ 호좜되기 λ•Œλ¬Έμ— λŒ€λΆ€λΆ„μ˜ μ‹œμŠ€ν…œμ—μ„œ fork() ν•¨μˆ˜ μˆ˜ν–‰ μ‹œ 데이터, νž™, μŠ€νƒ, μ˜μ—­μ„ λ°”λ‘œ λ³΅μ‚¬ν•˜μ§€ μ•ŠλŠ”λ‹€

μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ λ‚΄μš©μ΄ 변경될 λ•Œ λ‚˜λ¨Έμ§€ μ˜μ—­μ„ λ³΅μ‚¬ν•˜λŠ” 방법 ν†΅ν•΄μ„œ μ‹€ν–‰ 속도λ₯Ό 높일 수 μžˆλŠ”λ°, 이λ₯Ό λ³€ν˜• μ‹œμ— 볡사 (Copy On-Write, COW) 라고 ν•œλ‹€

 

β˜‘οΈ fork()

μƒˆλ‘œμš΄ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•˜λŠ”λ°, λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ™€ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μƒμ„±λœλ‹€

λ°˜ν™˜κ°’μΈ pid_t μ΄μš©ν•΄μ„œ ꡬ뢄이 λ˜λŠ”λ°, λ°˜ν™˜λœ PID κ°€ μ–‘μˆ˜μ΄λ©΄ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€! 0이면 μžμ‹ ν”„λ‘œμ„ΈμŠ€!

 

싀행이 μ‹€νŒ¨ν•œ κ²½μš°μ—λŠ” -1을 λ°˜ν™˜, errno 에 μ—λŸ¬ λ‚΄μš© μ €μž₯함

EAGAIN: μ‹œμŠ€ν…œμ—μ„œ ν—ˆμš©ν•˜λŠ” μ΅œλŒ€ ν”„λ‘œμ„ΈμŠ€μ˜ 수 초과

ENOMEM: μƒˆλ‘œμš΄ ν”„λ‘œμ„ΈμŠ€λ₯Ό μœ„ν•œ λ©”λͺ¨λ¦¬μ™€ μŠ€μ™‘ 곡간 뢀쑱함

 

싀행이 μ„±κ³΅ν•œ κ²½μš°μ—λŠ” μƒμ„±λœ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€ λͺ¨λ‘ λ™μΌν•œ ν”„λ‘œκ·Έλž¨ μ½”λ“œ 가짐

fork() ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄ μ „μ—­ λ³€μˆ˜λΏλ§Œ μ•„λ‹ˆλΌ μ—΄λ¦° 파일 λ””μŠ€ν¬λ¦½ν„°λ„ ν•¨κ»˜ κ³΅μœ λœλ‹€

ν˜ΈμΆœν•˜κΈ° 전에 open() ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•œ ν›„ λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•˜λ©΄ μ‚¬μš©μž ꡬ쑰의 파일 λ””μŠ€ν¬λ¦½ν„° ν…Œμ΄λΈ”μ΄ λ³΅μ‚¬λ˜μ–΄ 같은 μ˜€ν”„μ…‹μ„ 가진닀

 

fork() ν•¨μˆ˜λŠ” λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ text μ˜μ—­μ„ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ‘œ λ³΅μ‚¬ν•œλ‹€

exec() ν•¨μˆ˜λ₯Ό μˆ˜ν–‰ν•˜λ©΄ text μ˜μ—­μ„ λ‹€λ₯Έ ν”„λ‘œκ·Έλž¨μ˜ λ°”μ΄λ„ˆλ¦¬λ‘œ μ±„μš°κΈ° λ•Œλ¬Έμ—, fork() ν•¨μˆ˜ μˆ˜ν–‰ ν›„ exec() ν•¨μˆ˜λ₯Ό λ°”λ‘œ ν˜ΈμΆœν•œλ‹€λ©΄ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ text μ˜μ—­μ„ λ³΅μ‚¬ν•˜λŠ” μž‘μ—…μ€ λΆˆν•„μš”ν•˜λ‹€

// fork() ν•¨μˆ˜λ‘œ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•˜μž
#include <stdio.h>
#include <unistd.h>

static int g_var = 1; 	/* data μ˜μ—­μ˜ μ΄ˆκΈ°ν™”λœ λ³€μˆ˜ */
char str[ ] = "PID";

int main(int argc, char **argv)
{
    int var; 		/* stack μ˜μ—­μ˜ 지역 λ³€μˆ˜ */
    pid_t pid;

    var = 92;

    if((pid = fork()) < 0) { 	/* fork( ) ν•¨μˆ˜μ˜ μ—λŸ¬ μ‹œ 처리 */
        perror("[ERROR] : fork()");
    } else if(pid == 0) { 	/* μžμ‹ ν”„λ‘œμ„ΈμŠ€μ— λŒ€ν•œ 처리 */
        g_var++; 		/* λ³€μˆ˜μ˜ κ°’ λ³€κ²½ */
        var++;
        printf("Parent %s from Child Process(%d) : %d\n",
                                     str, getpid(), getppid());
    } else { 			/* λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ— λŒ€ν•œ 처리 */
        printf("Child %s from Parent Process(%d) : %d\n", str, getpid(), pid);
        sleep(1);
    }

    /* λ³€μˆ˜μ˜ λ‚΄μš©μ„ 좜λ ₯ */
    printf("pid = %d, Global var = %d, var = %d\n", getpid(), g_var, var);

    return 0;
}

/*
μ „μ—­ λ³€μˆ˜μ™€ 지역 λ³€μˆ˜λ₯Ό ν•œ 개 μƒμ„±ν•˜κ³ , fork() ν•¨μˆ˜ μ΄μš©ν•΄μ„œ 2개의 ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•œλ‹€
fork() ν•¨μˆ˜λ₯Ό μˆ˜ν–‰ν•˜λ©΄ ν”„λ‘œμ„ΈμŠ€λŠ” 2개의 ν”„λ‘œμ„ΈμŠ€λ‘œ λΆ„ν• λ˜μ–΄μ„œ μ‹€ν–‰λœλ‹€
pid_t 의 λ°˜ν™˜κ°’μœΌλ‘œ 0이면 μžμ‹, μ–‘μˆ˜λ©΄ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ΄λ‹€

λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€ μžμ‹ μ˜ pid λ₯Ό 좜λ ₯ν•˜λŠ”λ°, μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ PID λŠ” fork() ν•¨μˆ˜μ—μ„œ λ°˜ν™˜ν•˜λŠ” κ°’ μ΄μš©ν•¨
λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œλŠ” 1μ΄ˆκ°„ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œλ₯Ό κΈ°λ‹€λ¦° ν›„ μ•žμ˜ λ³€μˆ˜λ“€μ„ κ·ΈλŒ€λ‘œ 좜λ ₯ ν›„ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” μ’…λ£Œλœλ‹€
λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€λ³΄λ‹€ λ¨Όμ € μ’…λ£Œν•˜λ©΄ μ•ˆλ˜λŠ”λ°, λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ λ¨Όμ € μ’…λ£Œλ˜λŠ” κ²½μš°μ—λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” κ³ μ•„ ν”„λ‘œμ„ΈμŠ€κ°€ λœλ‹€
μ‹œμŠ€ν…œμ—μ„œ 주기적으둜 κ³ μ•„ ν”„λ‘œμ„ΈμŠ€λ₯Ό μ°Ύμ•„μ„œ init ν”„λ‘œμ„ΈμŠ€μ˜ μžμ‹μœΌλ‘œ ν¬ν•¨μ‹œμΌœμ€€λ‹€

μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” λ³€μˆ˜μ˜ 값듀을 1μ”© μ¦κ°€μ‹œν‚¨ ν›„ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ™€ μžμ‹ μ˜ pid λ₯Ό 좜λ ₯ν•˜λŠ”λ°, λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ PID κ΅¬ν•˜κΈ° μœ„ν•΄ getppid() μ‚¬μš©ν•œλ‹€

@gani0325 ➜ /workspaces/IoT_Linux_RaspberryPi/Process_Signal (main) $ gcc -o fork fork.c
@gani0325 ➜ /workspaces/IoT_Linux_RaspberryPi/Process_Signal (main) $ ./fork
*/
gcc -o fork fork.c
./fork

 

β˜‘οΈ vfork()

So, vfork() ν•¨μˆ˜λŠ” exec() ν•¨μˆ˜λ₯Ό ν†΅ν•΄μ„œ μƒˆλ‘œμš΄ ν”„λ‘œκ·Έλž¨μ„ μ‹€ν–‰μ‹œν‚¬ λͺ©μ μœΌλ‘œ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό 생성할 λ•Œ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ λ©”λͺ¨λ¦¬ μ˜μ—­μ„ λͺ¨λ‘ λ³΅μ‚¬ν•˜μ§€ μ•ŠλŠ”λ‹€

 

μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” exec(), exit() ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•ŒκΉŒμ§€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ λ©”λͺ¨λ¦¬ μ˜μ—­μ—μ„œ μ‹€ν–‰λ˜λ©°, λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” 싀행을 λ©ˆμΆ°λ„ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ 항상 λ¨Όμ € μ‹€ν–‰λ˜λŠ” 것을 보μž₯ν•œλ‹€

// vfork() 둜 ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•΄λ³΄μž
#include <stdio.h>
#include <unistd.h>

static int g_var = 1; 	/* μ΄ˆκΈ°ν™”λœ data μ˜μ—­μ˜ μ „μ—­ λ³€μˆ˜ */
char str[ ] = "PID";

int main(int argc, char **argv)
{
    int var; 		/* μŠ€νƒ(stack) μ˜μ—­μ˜ μžλ™ λ³€μˆ˜ */

    pid_t pid;
    var = 88;

    if((pid = vfork()) < 0) { 	/* fork() ν•¨μˆ˜ 호좜 μ—λŸ¬ */
        perror("vfork()");
    } else if(pid == 0) { 	/* μžμ‹ ν”„λ‘œμ„ΈμŠ€ */
        g_var++; 		/* λ³€μˆ˜μ˜ κ°’ λ³€κ²½ */
        var++;
        printf("Parent %s from Child Process(%d) : %d\n",
        str, getpid(), getppid());
        printf("pid = %d, Global var = %d, var = %d\n", getpid(), g_var, var);
        _exit(0);
    } else { 			/* λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€ */
        printf("Child %s from Parent Process(%d) : %d\n", str, getpid(), pid);
    }

    printf("pid = %d, Global var = %d, var = %d\n", getpid(), g_var, var);

    return 0;
}

/*
vfork() ν•¨μˆ˜λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•˜κ³  λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” λŒ€κΈ°ν•˜κ³  있기 λ•Œλ¬Έμ—
μžμ‹ λΆ€ν„° 좜λ ₯되고, λΆ€λͺ¨ λ‚΄μš©μ΄ 좜λ ₯λœλ‹€

μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—μ„œ λ³€κ²½ν•œ μ „μ—­ λ³€μˆ˜μ™€ 지역 λ³€μˆ˜μ˜ λ‚΄μš©μ΄ λͺ¨λ‘ λ³€κ²½λ˜μ–΄ μžˆλ‹€
두 ν”„λ‘œμ„ΈμŠ€κ°€ 같은 곡간을 μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— fork() 와 λ‹€λ₯΄κ²Œ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ 변경이 λΆ€λͺ¨μ—λ„ 영ν–₯을 μ€€λ‹€
μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” _exit() ν•¨μˆ˜λ₯Ό ν†΅ν•΄μ„œ μ’…λ£Œν•΄μ•Ό ν•˜λŠ”λ°, return 문으둜 μ’…λ£Œλ˜λŠ” 경우 ν”„λ‘œμ„Έλ“€ 사이에 곡유된 ν•¨μˆ˜μ˜
μŠ€νƒλ„ μ‚­μ œλ˜λ―€λ‘œ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œ μ‹œ μ—λŸ¬λ₯Ό 좜λ ₯ν•œλ‹€

@gani0325 ➜ /workspaces/IoT_Linux_RaspberryPi/Process_Signal (main) $ gcc -o vfork vfork.c
@gani0325 ➜ /workspaces/IoT_Linux_RaspberryPi/Process_Signal (main) $ ./vfork 
*/
gcc -o vfork vfork.c
./vfork

 

⭐ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œ λŒ€κΈ°: wait() 와 waitpid() ν•¨μˆ˜

μžμ‹ ν”„λ‘œμ„ΈμŠ€λ“€μ€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λ“€μ΄ κ΄€λ¦¬ν•΄μ•Όν•˜λŠ”λ°, μžμ‹ ν”„λ‘œμ„ΈμŠ€λ“€μ΄ μ’…λ£Œλ˜κΈ° 전에 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λ“€μ΄ μ’…λ£Œλ˜λ©΄ μ•ˆλœλ‹€

μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œν•˜λ©΄ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—κ²Œ SIGCHLD μ‹œκ·Έλ„μ„ μ „λ‹¬ν•˜μ—¬ λŒ€κΈ° (block) μƒνƒœλ₯Ό ν•΄μ œν•œλ‹€

 

μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œλœ ν›„ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μƒνƒœλ₯Ό wait() λ‚˜ waitpid() ν•¨μˆ˜ λ“±μœΌλ‘œ μ’…λ£Œ μƒνƒœμ— λŒ€ν•œ λ°˜ν™˜κ°’μ„ 읽고 이와 κ΄€λ ¨λœ λ¦¬μ†ŒμŠ€λ₯Ό ν•΄μ œν•˜κΈ° μœ„ν•΄μ„œ λŒ€κΈ°ν•œλ‹€

컀널이 ν”„λ‘œμ„ΈμŠ€μ˜ ν”„λ‘œμ„ΈμŠ€ ID, μ’…λ£Œ μƒνƒœ κ°’, CPU μ‚¬μš© μ‹œκ°„ λ“± 정보λ₯Ό μœ μ§€ν•˜κ³  있기 λ•Œλ¬Έμ— 이λ₯Ό ν•΄μ œν•˜μ§€ μ•ŠμœΌλ©΄ μ‹œμŠ€ν…œμ— λ©”λͺ¨λ¦¬κ°€ λΆ€μ‘±ν•΄μ§€λŠ” ν˜„μƒμ΄ λ°œμƒν•œλ‹€

μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” μ’…λ£Œν–ˆμ§€λ§Œ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ wait() λ“±μ˜ μ²˜λ¦¬κ°€ λλ‚˜μ§€ μ•Šμ•„μ„œ μ’…λ£Œκ°€ λ˜μ–΄ μžˆμ–΄λ„ μ‚­μ œκ°€ λ˜μ§€ μ•Šκ³  λ‚¨μ•„μžˆλŠ” ν”„λ‘œμ„ΈμŠ€λ₯Ό μ’€λΉ„ ν”„λ‘œμ„ΈμŠ€λΌκ³  ν•œλ‹€

init ν”„λ‘œμ„ΈμŠ€λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œλ  λ•Œλ§ˆλ‹€ wait() ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•΄μ„œ ν”„λ‘œμ„ΈμŠ€μ˜ μ’€λΉ„ μƒνƒœλ₯Ό ν•΄μ œν•œλ‹€

 

wait() ν•¨μˆ˜λŠ” λͺ¨λ“  μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ‹€ν–‰λ˜κ³  μžˆλŠ” λ™μ•ˆ λŒ€κΈ°(block) ν•˜κ³  있고, μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œν•˜λ©΄ μ’…λ£Œ μƒνƒœ κ°’κ³Ό ν•¨κ»˜ μ¦‰μ‹œ λ°˜ν™˜λœλ‹€

wait() ν•¨μˆ˜λŠ” λͺ¨λ“  μžμ‹ ν”„λ‘œμ„ΈμŠ€λ“€μ„ λŒ€κΈ°ν•  λ•Œ μ‚¬μš©ν•˜λŠ”λ°, μ—¬λŸ¬ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ“€μ΄ μžˆλŠ” κ²½μš°μ— 그쀑 ν•˜λ‚˜λ§Œ μ’…λ£Œν•΄λ„ λ°˜ν™˜λœλ‹€

waitpid() ν•¨μˆ˜λŠ” νŠΉμ • μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό μ§€μ •ν•΄μ„œ λŒ€κΈ°ν•  수 μžˆλŠ”λ°, 첫 번째 인자 (pid) λ₯Ό μ΄μš©ν•΄μ„œ νŠΉμ • ν”„λ‘œμ„ΈμŠ€λ‚˜ μ—¬λŸ¬ κ·Έλ£Ή ν”„λ‘œμ„ΈμŠ€λ“€μ˜ λŒ€κΈ°λ₯Ό 지정할 수 μžˆλ‹€. μ„Έλ²ˆ μ§Έ 인자둜 λ‹¨μˆœ λŒ€κΈ°μ˜ λ°©μ§€λ‚˜ μž‘μ—… μ œμ–΄ 지원을 μ˜΅μ…˜μœΌλ‘œ μ„€μ •ν•œλ‹€

 

⭐ λ‹€λ₯Έ ν”„λ‘œκ·Έλž¨μ˜ μ‹€ν–‰: exec() ν•¨μˆ˜

exec() ν•¨μˆ˜λŠ” μ‹€ν–‰ νŒŒμΌμ„ 찾으면 기계어 μ½”λ“œμΈμ§€ ν™•μΈν•˜κ³ , 기계어 μ½”λ“œμΈ κ²½μš°μ—λŠ” 직접 μ‹€ν–‰ν•˜κ³ 

기계어 μ½”λ“œκ°€ μ•„λ‹Œ κ²½μš°μ—λŠ” μ…Έ 슀크립트둜 인식해 "/bin/sh" 을 μ‹€ν–‰ν•˜κ³  주어진 μ‹€ν–‰ νŒŒμΌμ„ μ…Έμ˜ 인자둜 ν•΄μ„œ μ…Έ 슀크립트λ₯Ό μˆ˜ν–‰ν•œλ‹€

 

β˜‘οΈ system() ν•¨μˆ˜

λ¦¬λˆ…μŠ€μ—μ„œ μ™ΈλΆ€ ν”„λ‘œκ·Έλž¨μ„ μ‹€ν–‰μ‹œν‚€κ³  싢은 경우 μ‚¬μš©ν•œλ‹€

fork(), exec(), waitpid() ν•¨μˆ˜λ‘œ κ΅¬μ„±λ˜μ–΄ 있으며

fork() μ‹€νŒ¨ν•˜κ±°λ‚˜ waitpid() κ°€ EINTR μ΄μ™Έμ˜ 값을 λ°˜ν™˜ν•˜λ©΄, system() ν•¨μˆ˜λŠ” errno 에 값을 μ„€μ •ν•˜κ³  -1 λ°˜ν™˜ν•¨

exec() ν•¨μˆ˜κ°€ μ‹€νŒ¨ν•œ κ²½μš°μ—λŠ” μƒμ„±ν•œ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œ μƒνƒœ κ°’μœΌλ‘œ 127을 λ°˜ν™˜ν•œλ‹€

μ„Έ ν•¨μˆ˜κ°€ λͺ¨λ‘ μ„±κ³΅ν•˜λ©΄ waitpid 둜 μ–»μ–΄λ‚Έ μ…Έ μ’…λ£Œ μƒνƒœ 값을 λ°˜ν™˜ν•œλ‹€

 

fork() ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄μ„œ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•˜κ³  execl() ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄μ„œ μ‚¬μš©μžκ°€ μž…λ ₯ν•œ λͺ…령을 μˆ˜ν–‰ν•œλ‹€
sh μ…Έ λͺ…λ Ήμ–΄λ‘œ μˆ˜ν–‰ν•  μˆ˜ μžˆλ„둝 /bin/sh μ˜ μΈμžλ‘œ λͺ…λ Ήμ–΄λ₯Ό μž…λ ₯ν•˜μ˜€κ³ 
λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” waitpid() ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄μ„œ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μˆ˜ν–‰μ„ κΈ°λ‹€λ¦¬λ„둝 ν•œλ‹€

main() ν•¨μˆ˜μ˜ 3번째 μΈμžλ‘œ ν˜„μž¬ μ„€μ •λœ ν™˜κ²½ λ³€μˆ˜λ“€μ˜ λͺ©λ‘μ„ κ°€μ Έμ˜¬ μˆ˜ μžˆλ‹€
ν™˜κ²½ λ³€μˆ˜μ˜ μ‚¬μš©μ„ μœ„ν•΄ main() ν•¨μˆ˜μ˜ 3번째 μΈμžλ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  κ΄‘μ—­ λ³€μˆ˜ environ μ„ μ‚¬μš©ν•  μˆ˜ μžˆλ‹€

ν˜„μž¬ μ„€μ •λœ ν™˜κ²½ λ³€μˆ˜λ“€μ΄ ν™”면에 μΆœλ ₯되고, who λͺ…λ Ήμ–΄μ˜ κ²°κ³Όκ°€ μΆœλ ₯된 ν›„ nocommand λΌλŠ” λͺ…λ Ήμ–΄κ°€ μ—†μœΌλ―€λ‘œ μ—λŸ¬κ°€ μΆœλ ₯λœλ‹€
cal λͺ…령어에 λŒ€ν•œ κ²°κ³Όκ°€ μΆœλ ₯λœλ‹€

// system() ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•˜λ©΄μ„œ fork(), exec(), waitpid() ν•¨μˆ˜ μ‚¬μš©ν•˜κΈ°
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>

int system(const char *cmd) 	/* fork(), exec(), waitpid() ν•¨μˆ˜λ₯Ό μ‚¬μš© */
{
    pid_t pid;
    int status;

    if((pid = fork()) < 0) { 	/* fork( ) ν•¨μˆ˜ μˆ˜ν–‰ μ‹œ μ—λŸ¬κ°€ λ°œμƒν–ˆμ„ λ•Œμ˜ 처리 */
        status = -1;
    } else if(pid == 0) { 	/* μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ 처리 */
        execl("/bin/sh", "sh", "-c", cmd, (char *)0);
        _exit(127); 		/* execl( ) ν•¨μˆ˜μ˜ μ—λŸ¬ 사항 */
    } else { /* λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ 처리 */
        while(waitpid(pid, &status, 0) < 0) 	/* μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œ λŒ€κΈ° */
        if(errno != EINTR) { 	/* waitpid( ) ν•¨μˆ˜μ—μ„œ EINTR이 μ•„λ‹Œ 경우의 처리 */
            status = -1;
            break;
        }
    }

    return status;
}

int main(int argc, char **argv, char **envp)
{
    while(*envp) 		/* ν™˜κ²½ λ³€μˆ˜λ₯Ό 좜λ ₯ν•œλ‹€. */
        printf("%s\n", *envp++);

    system("who"); 		/* who μœ ν‹Έλ¦¬ν‹° μˆ˜ν–‰ */
    system("nocommand"); 	/* 였λ₯˜μ‚¬ν•­μ˜ μˆ˜ν–‰ */
    system("cal"); 		/* cal μœ ν‹Έλ¦¬ν‹° μˆ˜ν–‰ */

    return 0;
}

/*
fork() ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄μ„œ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•˜κ³  execl() ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄μ„œ μ‚¬μš©μžκ°€ μž…λ ₯ν•œ λͺ…령을 μˆ˜ν–‰ν•œλ‹€
sh μ…Έ λͺ…λ Ήμ–΄λ‘œ μˆ˜ν–‰ν•  수 μžˆλ„λ‘ /bin/sh 의 인자둜 λͺ…λ Ήμ–΄λ₯Ό μž…λ ₯ν•˜μ˜€κ³ 
λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” waitpid() ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄μ„œ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μˆ˜ν–‰μ„ 기닀리도둝 ν•œλ‹€

main() ν•¨μˆ˜μ˜ 3번째 인자둜 ν˜„μž¬ μ„€μ •λœ ν™˜κ²½ λ³€μˆ˜λ“€μ˜ λͺ©λ‘μ„ κ°€μ Έμ˜¬ 수 μžˆλ‹€
ν™˜κ²½ λ³€μˆ˜μ˜ μ‚¬μš©μ„ μœ„ν•΄ main() ν•¨μˆ˜μ˜ 3번째 인자λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  κ΄‘μ—­ λ³€μˆ˜ environ 을 μ‚¬μš©ν•  수 μžˆλ‹€

ν˜„μž¬ μ„€μ •λœ ν™˜κ²½ λ³€μˆ˜λ“€μ΄ 화면에 좜λ ₯되고, who λͺ…λ Ήμ–΄μ˜ κ²°κ³Όκ°€ 좜λ ₯된 ν›„ nocommand λΌλŠ” λͺ…λ Ήμ–΄κ°€ μ—†μœΌλ―€λ‘œ μ—λŸ¬κ°€ 좜λ ₯λœλ‹€
cal λͺ…령어에 λŒ€ν•œ κ²°κ³Όκ°€ 좜λ ₯λœλ‹€

gani@gani:~/raspi/Process_Signal $ gcc -o system system.c
gani@gani:~/raspi/Process_Signal $ ./system 
*/
gcc -o system system.c
./system

 

β˜‘οΈ posix_spawn() ν•¨μˆ˜

fork() & exec() μ„ μ‚¬μš©ν•˜λŠ” κ²ƒλ³΄λ‹€ posix_spawn() ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λŠ” κ²ƒμ„ κ°•λ ₯히 κΆŒμž₯함
system() ν•¨μˆ˜λ₯Ό posix_spawn() ν•¨μˆ˜λ‘œ λ§Œλ“€λ©΄ κ°„λ‹¨ν•˜κ²Œ μž‘μ„±ν•  μˆ˜ μžˆμŒ

posix_spawn() ν•¨μˆ˜μ˜ μ²« λ²ˆμ§Έ μΈμžλ‘œ fork() ν•¨μˆ˜μ™€ κ°™μ΄ ν”„λ‘œμ„ΈμŠ€λ₯Ό κ΅¬λΆ„ν•  μˆ˜ μžˆλŠ” pid_t
두 λ²ˆμ§Έ μΈμžλ‘œ exec() ν•¨μˆ˜μ™€ κ°™μ΄ μ‹€ν–‰ν•  ν”„λ‘œκ·Έλž¨μ˜ κ²½λ‘œλ₯Ό λ„£μ–΄μ€€λ‹€
μ„Έ λ²ˆμ§Έ, λ„€ λ²ˆμ§Έ μΈμžλ₯Ό μ΄μš©ν•΄μ„œ posix_spawn() ν•¨μˆ˜μ˜ μ†μ„±μ„ λ„£λŠ”λ‹€ (κΈ°λ³Έκ°’μœΌλ‘œ NULL)
λ‹€μ„― λ²ˆμ§Έ μΈμžλŠ” λ‘ λ²ˆμ§Έ μΈμžλ‘œ λ„£μ–΄μ„œ μ‹€ν–‰ν•  ν”„λ‘œκ·Έλž¨μ—μ„œ μ‚¬μš©ν•˜λŠ” μΈμž
λ§ˆμ§€λ§‰μœΌλ‘œλŠ”ν™˜κ²½ λ³€μˆ˜

μ‹€ν–‰ν•˜λ©΄ fork() & exec() 와 λ™μΌν•˜κ²Œ λ™μž‘λœλ‹€
posix_spawn() ν•¨μˆ˜μ˜ μ†μ„± λ“±μ„ μ΄μš©ν•˜λ©΄ waitpid() ν•¨μˆ˜ μ—†μ΄ λΉ„동기적 ν”„λ‘œκ·Έλž˜λ°μ„ ν•  μˆ˜ μžˆλ‹€

// posix_spawan() ν•¨μˆ˜λŠ” system() ν•¨μˆ˜μ²˜λŸΌ κ°„λ‹¨νžˆ ν”„λ‘œκ·Έλž¨μ„ μ‹€ν–‰ν•  수 있음
#include <stdio.h>
#include <sys/wait.h>
#include <spawn.h>

extern char **environ;

int system(char *cmd) 		/* posix_spawn() ν•¨μˆ˜λ₯Ό μ‚¬μš© */
{
    pid_t pid;
    int status;

    char *argv[] = {"sh", "-c", cmd, NULL};
    posix_spawn(&pid, "/bin/sh", NULL, NULL, argv, environ);
    waitpid(pid, &status, 0);

    return status;
}

int main(int argc, char **argv, char **envp)
{
    while( *envp) 		/* ν™˜κ²½ λ³€μˆ˜λ₯Ό 좜λ ₯ν•œλ‹€. */
        printf( "%s\n", *envp++);

    system("who"); 		/* who μœ ν‹Έλ¦¬ν‹° μˆ˜ν–‰ */
    system("nocommand"); 	/* 였λ₯˜μ‚¬ν•­μ˜ μˆ˜ν–‰ */
    system("cal"); 		/* cal μœ ν‹Έλ¦¬ν‹° μˆ˜ν–‰ */

    return 0;
}

/*
fork() & exec() 을 μ‚¬μš©ν•˜λŠ” 것보닀 posix_spawn() ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λŠ” 것을 κ°•λ ₯히 ꢌμž₯함
system() ν•¨μˆ˜λ₯Ό posix_spawn() ν•¨μˆ˜λ‘œ λ§Œλ“€λ©΄ κ°„λ‹¨ν•˜κ²Œ μž‘μ„±ν•  수 있음

posix_spawn() ν•¨μˆ˜μ˜ 첫 번째 인자둜 fork() ν•¨μˆ˜μ™€ 같이 ν”„λ‘œμ„ΈμŠ€λ₯Ό ꡬ뢄할 수 μžˆλŠ” pid_t
두 번째 인자둜 exec() ν•¨μˆ˜μ™€ 같이 μ‹€ν–‰ν•  ν”„λ‘œκ·Έλž¨μ˜ 경둜λ₯Ό λ„£μ–΄μ€€λ‹€
μ„Έ 번째, λ„€ 번째 인자λ₯Ό μ΄μš©ν•΄μ„œ posix_spawn() ν•¨μˆ˜μ˜ 속성을 λ„£λŠ”λ‹€ (κΈ°λ³Έκ°’μœΌλ‘œ NULL)
λ‹€μ„― 번째 μΈμžλŠ” 두 번째 인자둜 λ„£μ–΄μ„œ μ‹€ν–‰ν•  ν”„λ‘œκ·Έλž¨μ—μ„œ μ‚¬μš©ν•˜λŠ” 인자
λ§ˆμ§€λ§‰μœΌλ‘œλŠ”ν™˜κ²½ λ³€μˆ˜

μ‹€ν–‰ν•˜λ©΄ FORK() & exec() 와 λ™μΌν•˜κ²Œ λ™μž‘λœλ‹€
posix_spawn() ν•¨μˆ˜μ˜ 속성 등을 μ΄μš©ν•˜λ©΄ waitpid() ν•¨μˆ˜ 없이 비동기적 ν”„λ‘œκ·Έλž˜λ°μ„ ν•  수 μžˆλ‹€

gani@gani:~/raspi/Process_Signal $ gcc -o spawn spawn.c
gani@gani:~/raspi/Process_Signal $ ./spawn 
*/
gcc -o spawn spawn.c
./spawn

728x90
λ°˜μ‘ν˜•
Comments