Study · 운영체제 · 명령 실행 · 프로세스
셸은 명령을 실행하지 않는다 — 자기를 복제한 뒤 그 자리에 명령을 덮어쓴다
장면
ls 한 번에 프로세스가 몇 개 만들어질까? 셸은 왜 자기를 복제한 뒤에야 ls 를 띄울까?
$ ls -l
$ echo $$ # 셸의 PID
$ strace -f ls # fork · exec 가 보인다
아래 재생기의 ▶를 누르면 한 스텝씩 진행된다. 금색 테두리가 지금 이야기하는 곳이고, 캡션이 무슨 일이 일어났는지 말해 준다. 굵게 밑줄 친 말은 누르면 뜻이 나온다. 빨간 딱지는 그때 벌어지는 일의 이름이고, 캡션 바로 위 회색 글자는 지금 스텝이 속한 묶음의 이름이다.
카드 아래 회색 줄은 그 일이 실제로 적혀 있는 소스의 파일 이름 : 줄 번호와 함수 이름이다. 글 안에 (:669)처럼 줄 번호만 적힌 것은 바로 앞에 적은 파일의 그 줄이라는 뜻이다. 캡션 한가운데 박힌 긴 영어 이름과 괄호 속 파일 · 줄 번호도 같다 — 건너뛰고 한글만 읽어도 뜻이 통하게 써 두었다.
장면 · 셸은 명령을 실행하지 않는다 — 자기를 복제한 뒤 그 자리에 명령을 덮어쓴다
0 / 11
▶ 를 누르면 ls -l 한 번에 무슨 일이 벌어지는지 따라간다. 셸이 ls 를 그냥 「실행」하는 걸음은 없다. 셸은 자기를 똑같이 한 벌 복제하고, 그 복제본이 스스로를 ls 로 덮어쓴다. 그래서 새로 생기는 프로세스는 하나뿐이다.
키보드 · ← → 한 스텝 · Space 재생/멈춤 · Home 처음
셸은 명령을 실행하지 않는다. 자기를 똑같이 복제하고, 그 복제본이 자기를 명령으로 덮어쓴다. 그동안 셸은 잠들어 기다린다.
어떻게 확인했나
소스 어디를 보고 적었는지와 무엇을 돌려서 쟀는지를 남긴 자리다. 처음 읽을 때는 건너뛰어도 된다.
- kernel_clone(kernel/fork.c:2715) → copy_process(:2012) 가 dup_task_struct(:2133) 로 task_struct 를 통째로 베낀 뒤, copy_files(:1660) · copy_fs · copy_mm(:1568) 이 차례로 돈다. 셋 다 CLONE_FILES · CLONE_VM 플래그가 켜져 있으면 부모 것을 공유하고 꺼져 있으면 새 벌을 뜬다. fork(:2850) 는 exit_signal = SIGCHLD 만 넣고 공유 플래그를 하나도 켜지 않는다.
- fork 는 메모리를 복사하지 않는다. dup_mmap(mm/mmap.c:1708) → copy_page_range(mm/memory.c:1589) 가 페이지 표를 옮기면서 __copy_present_ptes(mm/memory.c:1190) 에서 부모 · 자식 양쪽의 쓰기 비트를 뗀다.
- exec 가 메모리 지도를 갈아 끼우는 자리는 exec_mmap(fs/exec.c:843) 이다. tsk->mm 에 새 주소 공간을 꽂고 옛 것을 놓는다. 그 앞 begin_new_exec(fs/exec.c:1135) 이 bprm->point_of_no_return = true(:1160) 를 놓아, 이 뒤의 실패는 되돌리지 않고 SIGSEGV 로 끝낸다.
- exec 는 프로세스를 만들지 않는다. PID 는 alloc_pid(kernel/fork.c:2326) 가 fork 때 준 것 그대로이고, ELF 로더는 START_THREAD(fs/binfmt_elf.c:1376) 로 레지스터만 새 진입점에 맞춘다.
- 셸이 기다리는 자리는 do_wait(kernel/exit.c:1747) 다. TASK_INTERRUPTIBLE 로 바꾸고 schedule() 을 부른다. 끝난 자식은 exit_notify(kernel/exit.c:774) 에서 EXIT_ZOMBIE(:786) 가 되어 부모가 거둘 때까지 남는다.
- strace -f 로 bash -c 'ls -l' 을 잡으니 clone 이 한 번(109 → 110)이고, 부모는 wait4 로 기다리고, 자식이 execve("/usr/bin/ls") 를 부른다. 새로 생기는 프로세스는 하나뿐이다.
항목 지도목차 ›
- 계정과 권한
- 1 로그인 — 로그인하면 무슨 일이 일어나나
- 2 계정 만들기 — 계정을 만들면 어디에 무엇이 쓰이나
- 3 권한 주기 — chmod 가 바꾸는 것은 어디에 있나
- 4 권한 검사 — 파일을 열 때 권한을 언제 보나
- 파일과 디렉터리
- 5 파일 만들기 — 파일을 만들면 무엇이 생기나
- 6 디렉터리 — 디렉터리를 만들면 무엇이 생기나
- 7 파일 읽기 — 파일을 읽으면 어디를 거치나
- 8 파일 지우기 — 파일을 지우면 정말 사라지나
- 프로세스
- 9 명령 실행 — 명령 하나를 치면 무슨 일이 벌어지나
- 10 파일 디스크립터 — 프로세스가 파일을 열면 무엇이 늘어나나
- 11 CPU 나누기 — CPU 하나를 여럿이 어떻게 나눠 쓰나
- 메모리
- 12 메모리 요청 — 메모리를 달라고 하면 바로 주나
- 13 페이지 폴트 — 처음 건드릴 때 무슨 일이 일어나나
- 14 OOM — 메모리가 모자라면 누가 죽나
- 네트워크
- 15 소켓 만들기 — 소켓을 만들면 무엇을 받나
- 16 연결 받기 — 연결이 들어오면 누가 먼저 받나
- 17 주고받기 — 데이터가 오갈 때 무엇이 움직이나