Search
πŸ‘¨β€πŸ”§

pipex

Created
2021/06/28
tag
42μ„œμšΈ
42Seoul
pipex
Write a Shell in C
Redirection
Pipe

Subjects

β€’

1. External Functions

pipexλ₯Ό κ΅¬ν˜„ν•˜λŠ”λ° μžˆμ–΄μ„œ ν—ˆμš©λœ ν•¨μˆ˜λ“€μ€ μ•„λž˜μ™€ κ°™λ‹€.
β€’
open
β€’
close
β€’
read
β€’
write
β€’
malloc
β€’
free
β€’
access
β€’
unlink
β€’
fork
β€’
wait
β€’
waitpid
β€’
dup
β€’
dup2
β€’
pipe
β€’
execve
β€’
perror
β€’
strerror
β€’
exit
이 μ€‘μ—μ„œ 이전에 자주 μ‚¬μš©ν–ˆλ˜ open, close, read, write, malloc, freeλŠ” μ†Œκ°œλ₯Ό μƒλž΅ν•  것이닀. λ˜ν•œ perror, strerror, exit에 λŒ€ν•΄μ„œλŠ” miniRT 과제λ₯Ό μ†Œκ°œν•  λ•Œ 이미 μ•Œμ•„λ³Έ 적이 μžˆλ‹€. λ”°λΌμ„œ perror, strerror, exit에 λŒ€ν•΄μ„œλŠ” μ•„λž˜ 링크의 External Functionsλ₯Ό μ°Έκ³ ν•˜μž.
이번 κΈ€μ—μ„œλŠ” access, unlink, fork, wait, waitpid, dup, dup2, pipe, execveλ§Œμ„ μ•Œμ•„λ³Ό 것이닀. μ„€λͺ…λœ λ‚΄μš©μ—λŠ” Error에 λŒ€ν•œ μ–˜κΈ°κ°€ μ’…μ’… λ‚˜μ˜¨λ‹€. λ”°λΌμ„œ μœ„ 링크의 Error에 λŒ€ν•œ λ‚΄μš©μ„ κΌ­ λ¨Όμ € 읽고 였길 λ°”λž€λ‹€. 링크의 글이 λ„ˆλ¬΄ κΈΈλ‹€λ©΄ 적어도 errno에 λŒ€ν•΄μ„œλΌλ„ μ΄ν•΄ν•˜λŠ” 것을 κΆŒν•œλ‹€.

1) access

1. μ˜μ‘΄μ„±

#include <unistd.h>
C

2. ν•¨μˆ˜ μ›ν˜•

int access(const char *path, int mode);
C

3. ν•¨μˆ˜ μ„€λͺ…

access ν•¨μˆ˜λŠ” path에 ν•΄λ‹Ήν•˜λŠ” νŒŒμΌμ„ mode에 λ”°λΌμ„œ 확인을 ν•˜κ²Œ λœλ‹€. pathμ—λŠ” 일반 파일 외에 심볼릭 링크, 디렉토리 등을 ν¬ν•¨ν•˜μ—¬ λͺ¨λ“  νŒŒμΌμ„ 인자둜 μ‚¬μš©ν•  수 μžˆλ‹€. modeλŠ” <unistd.h>에 맀크둜λ₯Ό 톡해 값듀이 μ •μ˜λ˜μ–΄ μžˆλ‹€. access ν•¨μˆ˜λŠ” 인자둜 받은 mode에 λ§Œμ‘±ν•˜λ©΄ 0을 λ°˜ν™˜ν•˜κ³ , 그렇지 μ•ŠμœΌλ©΄ -1을 λ°˜ν™˜ν•œλ‹€.
μœ„ κ·Έλ¦Όμ—μ„œ λ³Ό 수 μžˆλ“―μ΄, modeλ₯Ό ν†΅ν•΄μ„œ 파일의 쑴재 유무 및 파일의 κΆŒν•œμ„ 확인할 수 μžˆλ‹€. mode둜 주어진 값듀은 λΉ„νŠΈλ₯Ό μ‰¬ν”„νŠΈ ν•œ κ°’λ“€λ‘œ μ •μ˜λ˜μ—ˆκΈ° λ•Œλ¬Έμ— Mask둜써 이용될 수 μžˆλ‹€. λ”°λΌμ„œ 파일의 쑴재 μœ λ¬΄μ™€ λ™μ‹œμ— 파일의 μ‹€ν–‰ κΆŒν•œμ΄ μžˆλŠ”μ§€ λ™μ‹œμ— ν™•μΈν•˜κ³  μ‹Άλ‹€λ©΄, | λΌλŠ” OR λΉ„νŠΈ 연산을 μ΄μš©ν•˜μ—¬ ν•œ λ²ˆμ— κ²€μ‚¬ν•˜λŠ” 것이 κ°€λŠ₯ν•˜λ‹€. 예λ₯Ό λ“€μ–΄, mode = F_OK | X_OK;와 같이 두고 access ν•¨μˆ˜μ˜ 인자둜 modeλ₯Ό 주게 되면 파일의 쑴재 μœ λ¬΄μ™€ 파일의 μ‹€ν–‰ κΆŒν•œμ„ λ™μ‹œμ— 확인할 수 μžˆλ‹€. 단, |λ₯Ό 톡해 λ™μ‹œμ— κ²€μ‚¬ν•˜λ €λŠ” 쑰건듀 쀑에 ν•˜λ‚˜λΌλ„ λ§Œμ‘±ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ λ°˜ν™˜ κ°’μœΌλ‘œ -1을 λ°›κ²Œ λ˜λ―€λ‘œ, |λŠ” μ—¬λŸ¬ 쑰건을 λ™μ‹œμ— λ§Œμ‘±ν•΄μ•Ό ν•˜λŠ” κ²½μš°μ—λ§Œ μ‚¬μš©ν•˜λ„λ‘ ν•œλ‹€.
cd, exitκ³Ό 같이 Shell의 Built-In λͺ…λ Ήμ–΄λ₯Ό μ œμ™Έν•˜κ³ , 파일둜 μœ μ§€ λ˜λŠ” λͺ…령어듀을 exec κ³„μ—΄μ˜ ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜μ—¬ μ‹€ν–‰ν•˜κΈ° 전에 access ν•¨μˆ˜λ₯Ό 톡해 μ„ ν–‰μ μœΌλ‘œ νŒŒμΌμ— λŒ€ν•œ 검사λ₯Ό μˆ˜ν–‰ν•  수 μžˆλ‹€.

4. μ˜ˆμ‹œ

#include <stdio.h> #include <unistd.h> int main(void) { int mode; mode = 0; mode |= F_OK; if (!access("test.txt", mode)) printf("File is existing\n"); else printf("File is not existing\n"); mode &= 0; mode |= X_OK; if (!access("test.txt", mode)) printf("File is executable\n"); else printf("File is not executable\n"); return (0); }
C

2) unlink

1. μ˜μ‘΄μ„±

#include <unistd.h>
C

2. ν•¨μˆ˜ μ›ν˜•

int unlink(const char *path);
C

3. ν•¨μˆ˜ μ„€λͺ…

unlink ν•¨μˆ˜λŠ” νŒŒμΌμ„ μ‚­μ œν•  λ•Œ μ‚¬μš©λœλ‹€. κ°„λ‹¨ν•˜κ²ŒλŠ” 파일의 μ‚­μ œμ΄μ§€λ§Œ, μ •ν™•ν•˜κ²ŒλŠ” ν•˜λ“œ 링크λ₯Ό λŠλŠ”λ° μ΄μš©λœλ‹€. λ”°λΌμ„œ unlink ν•¨μˆ˜λ₯Ό μ΄ν•΄ν•˜κΈ° 전에 ν•˜λ“œ 링크와 심볼릭 링크에 λŒ€ν•΄μ„œ 이해할 ν•„μš”κ°€ μžˆλ‹€.
일반적으둜 λ§ν•˜λŠ” νŒŒμΌμ€ μ‹€μ œλ‘œ λ””μŠ€ν¬ 상에 μœ„μΉ˜ν•œ 데이터에 λΆˆκ³Όν•˜λ‹€. 즉, νŒŒμΌμ„ μƒμ„±ν•˜κ³  μ‚­μ œν•œλ‹€λŠ” κ°œλ…μ€ λ””μŠ€ν¬ 상에 데이터λ₯Ό μƒμ„±ν•˜κ³  μ‚­μ œν•œλ‹€λŠ” 것과 일λ§₯μƒν†΅ν•˜λ‹€. 그리고 파일이라고 λΆˆλ¦¬λŠ” 이 데이터듀은 μœ λ‹‰μŠ€ κ³„μ—΄μ˜ μš΄μ˜μ²΄μ œμ—μ„œ λͺ¨λ‘ inode둜 κ΄€λ¦¬λœλ‹€. inodeμ—λŠ” 파일의 κΆŒν•œ, ν˜•νƒœ, 고유 번호, μ†Œμœ μž 및 κ·Έλ£Ή, 원본 λ°μ΄ν„°μ˜ μ£Όμ†Œ λ“± νŒŒμΌμ— λŒ€ν•œ λͺ¨λ“  것듀이 κΈ°λ‘λ˜μ–΄ μžˆλ‹€. 이에 λŒ€ν•΄μ„  μœ„ 그림을 톡해 쑰금 더 μ •ν™•νžˆ 이해할 수 μžˆλ‹€. 즉, inodeλ₯Ό 톡해 데이터듀을 보닀 μ‰½κ²Œ μ‘°μž‘ν•˜κ³  관리할 수 μžˆλ‹€λŠ” 것이닀. 이 λ•Œ μ‚¬μš©μžλŠ” 데이터λ₯Ό μ‹€ν–‰ν•˜κ±°λ‚˜ 읽고 μ“°λŠ” λ“± μ‘°μž‘μ„ ν•˜κ³ μž ν•œλ‹€λ©΄, ν•˜λ“œ 링크λ₯Ό μ΄μš©ν•˜μ—¬ inode에 μ ‘κ·Όν•˜κ³  μ›ν•˜λŠ” μž‘μ—…μ„ μˆ˜ν–‰ν•˜κ²Œ λœλ‹€. 즉, 일반적으둜 μ‚¬μš©μž κ³΅κ°„μ—μ„œ 확인할 수 μžˆλŠ” νŒŒμΌλ“€μ€ λͺ¨λ‘ ν•˜λ“œ 링크라고 λ³Ό 수 μžˆλ‹€.
μœ„μ—μ„œ ν™•μΈν•œ κ²ƒμ²˜λŸΌ 기본적으둜 파일이 μ‘΄μž¬ν•œλ‹€λŠ” 것은 λ””μŠ€ν¬ 상에 데이터가 μ‘΄μž¬ν•˜λŠ” 것이고, 이에 λŒ€ν•œ inodeκ°€ 무쑰건 μ‘΄μž¬ν•¨κ³Ό λ™μ‹œμ— inode에 μ ‘κ·Όν•  수 μžˆλŠ” ν•˜λ“œ 링크λ₯Ό 적어도 ν•˜λ‚˜ 이상 가지고 μžˆλŠ” 것을 μ˜λ―Έν•œλ‹€. 만일 inode에 μ ‘κ·Όν•  수 μžˆλŠ” ν•˜λ“œ 링크가 ν•˜λ‚˜λ„ μ—†κ²Œ 되면, 이것이 곧 파일의 μ‚­μ œλ‘œ 이어진닀.
κ·Έλ ‡λ‹€λ©΄ 기쑴에 μ‘΄μž¬ν•˜κ³  μžˆλŠ” ν•˜λ“œ 링크에 ln λͺ…λ Ήμ–΄λ₯Ό μ΄μš©ν•˜λ©΄ μ–΄λ–»κ²Œ 될까? ν•˜λ‚˜μ˜ 파일이 μΆ”κ°€μ μœΌλ‘œ μƒμ„±λ˜λŠ” 것을 λ³Ό 수 μžˆλŠ”λ°, μ‚¬μš©μžκ°€ λ³΄κΈ°μ—λŠ” λ³„λ„μ˜ 파일이 μƒμ„±λœ κ²ƒμ²˜λŸΌ λ³΄μ΄μ§€λ§Œ μ‹€μ œλ‘œλŠ” λ™μΌν•œ inodeλ₯Ό κ°€λ¦¬ν‚€λŠ” ν•˜λ“œ 링크에 λΆˆκ³Όν•˜λ‹€. 데이터λ₯Ό μ°Έμ‘°ν•˜κ³  μžˆλŠ” inodeλŠ” κ³ μœ ν•˜κ³ , ν•˜λ“œ 링크듀이 λͺ‡ κ°œκ°€ μžˆλ“  μœ„μ˜ κ·Έλ¦Όκ³Ό 같이 λͺ¨λ‘ λ™μΌν•œ inodeλ₯Ό μ°Έμ‘°ν•˜κ²Œ λœλ‹€. μ‹€μ œλ‘œ λ””μŠ€ν¬ 상에 μ‘΄μž¬ν•˜λŠ” 데이터λ₯Ό μˆ˜μ •ν•˜κ²Œ 되면, λͺ¨λ“  ν•˜λ“œ 링크듀이 영ν–₯을 λ°›λŠ” μ΄μœ κ°€ 이 λ•Œλ¬Έμ΄λ‹€. 그리고 λ™μΌν•œ inodeλ₯Ό μ°Έμ‘°ν•˜κ³  μžˆλŠ” ν•˜λ“œ 링크가 λ‹€μˆ˜ μ‘΄μž¬ν•˜μ—¬λ„ ν¬κΈ°λŠ” κ³ μœ ν•˜κ²Œ μ μœ λœλ‹€. ν•˜λ“œ 링크의 λŒ€ν‘œμ μΈ μ˜ˆλŠ” ν˜„μž¬ 디렉토리λ₯Ό μ˜λ―Έν•˜λŠ” .와 μƒμœ„ 디렉토리λ₯Ό μ˜λ―Έν•˜λŠ” ..이 μžˆλ‹€.
심볼릭 λ§ν¬λŠ” ln λͺ…λ Ήμ–΄μ˜ -s μ˜΅μ…˜μ„ μ΄μš©ν•˜μ—¬ 생성할 수 μžˆλŠ”λ°, 이λ₯Ό μ΄μš©ν•˜λ©΄ ν•˜λ“œ 링크와 λ™μΌν•˜κ²Œ 파일이 μΆ”κ°€μ μœΌλ‘œ μƒμ„±λ˜λŠ” 것을 λ³Ό 수 μžˆλ‹€. ν•˜μ§€λ§Œ inodeλ₯Ό 쑰사해보면 ν•˜λ“œ λ§ν¬μ™€λŠ” 달리 λ³„λ„μ˜ inodeλ₯Ό μ°Έμ‘°ν•˜λŠ” 것을 확인할 수 μžˆλ‹€. 즉, 심볼릭 링크λ₯Ό 톡해 μƒμ„±λœ νŒŒμΌμ€ ν•˜λ“œ 링크와 달리 ν•˜λ“œ 링크에 λŒ€ν•œ inodeλ₯Ό μ°Έμ‘°ν•˜μ§€ μ•ŠλŠ”λ‹€. 이와 같은 상황을 μœ„ 그림을 ν†΅ν•΄μ„œ μ•Œ 수 μžˆλ“―μ΄, 심볼릭 λ§ν¬λŠ” λ³„λ„μ˜ inodeλ₯Ό κ°–κ³  있고 λ””μŠ€ν¬ 상에 λ³„λ„μ˜ 데이터λ₯Ό μœ μ§€ν•˜κ³  있으며 λ””μŠ€ν¬ μƒμ˜ λ°μ΄ν„°λŠ” κ·Έμ € ν•˜λ“œ 링크의 inodeλ₯Ό μ°Έμ‘°ν•˜λ„λ‘ μ£Όμ†Œλ§Œμ„ 가지고 μžˆμ„ 뿐이닀. 이 λ•Œλ¬Έμ— 심볼릭 링크가 λ°”λ‘œ 가기와 같이 μž‘λ™ν•  수 있으며 ν•˜λ“œ 링크와 달리 λ³„λ„μ˜ 크기λ₯Ό κ°–λŠ” 것이닀. 심볼릭 링크둜 μƒμ„±λœ νŒŒμΌμ€ μ–΄λ–€ ν•˜λ“œ 링크λ₯Ό μ°Έμ‘°ν•˜λŠ” 포인터 λ§ν¬μ΄λ©΄μ„œ, λ™μ‹œμ— ν•˜λ‚˜μ˜ ν•˜λ“œ 링크이닀.
μœ„μ—μ„œ unlink ν•¨μˆ˜λŠ” ν•˜λ“œ 링크λ₯Ό λŠλŠ”λ° μ΄μš©λœλ‹€κ³  ν–ˆλŠ”λ°, μ΄λŠ” ν•˜λ“œ 링크의 이름을 μ‚­μ œν•˜λ©΄μ„œ inodeλ₯Ό μ°Έμ‘°ν•˜κ³  μžˆλŠ” ν•˜λ‚˜μ˜ ν•˜λ“œ 링크λ₯Ό λŠλŠ” 것이닀. 예λ₯Ό λ“€μ–΄ μœ„ κ·Έλ¦Όκ³Ό 같이 μ‚¬μš©μžμ˜ 곡간에 a, b, cκ°€ 있고, 3개의 ν•˜λ“œ λ§ν¬λŠ” λͺ¨λ‘ λ™μΌν•œ inodeλ₯Ό μ°Έμ‘°ν•˜κ³  μžˆλ‹€κ³  ν•΄λ³΄μž. λ§Œμ•½ unlink의 path 인자둜 aλΌλŠ” ν•˜λ“œ 링크λ₯Ό 주게 되면, μ‚¬μš©μžμ˜ κ³΅κ°„μ—μ„œ aλŠ” μ‚­μ œλ˜μ§€λ§Œ μ—¬μ „νžˆ κ·Έ νŒŒμΌμ€ μ‘΄μž¬ν•˜κ³  μžˆλ‹€. 즉, μ‚¬μš©μžκ°€ λ³΄μ•˜μ„ λ•ŒλŠ” νŒŒμΌμ„ μ‚­μ œν•˜λŠ” κ²ƒμ²˜λŸΌ λ³΄μ΄μ§€λ§Œ νŒŒμΌμ„ μ™„μ „νžˆ μ‚­μ œν•˜κΈ° μœ„ν•΄μ„  inodeλ₯Ό μ°Έμ‘°ν•˜λŠ” λͺ¨λ“  ν•˜λ“œ 링크λ₯Ό λŠμ–΄μ•Όλ§Œ λΉ„λ‘œμ†Œ 파일이 μ‚­μ œλœλ‹€. 이와 같은 λ™μž‘μ€ μœ λ‹‰μŠ€μ˜ rm λͺ…령어와 λ™μΌν•˜λ‹€. rm λͺ…λ Ήμ–΄μ˜ λŒ€μƒμ΄ 일반 파일이라면 μ΄λŠ” unlink ν•¨μˆ˜μ™€ λ™μΌν•˜κ²Œ μž‘λ™ν•˜κ³ , λŒ€μƒμ΄ 디렉토리라면 μ΄λŠ” rmdir λͺ…령어와 λ™μΌν•˜κ²Œ μž‘λ™ν•œλ‹€.
파일의 μ‚­μ œλΌλŠ” κ°œλ…κ³Ό ν•˜λ“œ 링크λ₯Ό λŠλŠ”λ‹€λŠ” 것에 λŒ€ν•œ μ •ν™•ν•œ 차이λ₯Ό μ΄ν•΄ν•˜κΈ° μœ„ν•΄ μ„€λͺ…이 κΈΈμ—ˆλŠ”λ°, μ—¬νŠΌ μ‚¬μš©μžκ°€ λ³΄κΈ°μ—λŠ” unlink의 λ™μž‘μ΄ 곧 μ‚¬μš©μž 곡간에 μ‘΄μž¬ν•˜λŠ” 파일의 μ‚­μ œμ™€ λ™μΌν•˜λ‹€κ³  λ³Ό 수 μžˆλ‹€. unlink의 λ°˜ν™˜ 값이 0이라면 μ •μƒμ μœΌλ‘œ ν•˜λ“œ 링크λ₯Ό λŠμ€ 것이고, μ •μƒμ μœΌλ‘œ λ™μž‘ν•˜μ§€ λͺ»ν–ˆμ„ λ•ŒλŠ” -1이 λ°˜ν™˜λœλ‹€.

4. μ˜ˆμ‹œ

#include <stdio.h> #include <unistd.h> int main(int argc, char **argv) { int i; i = 0; while (++i < argc) { if (!access(argv[i], F_OK)) { if (!unlink(argv[i])) printf("File is unlinked\n"); else printf("File is not unlinked\n"); } else printf("File is not existing\n"); } return (0); }
C

3) fork

1. μ˜μ‘΄μ„±

#include <unistd.h>
C

2. ν•¨μˆ˜ μ›ν˜•

pid_t fork(void);
C

3. ν•¨μˆ˜ μ„€λͺ…

ν˜„μž¬ μ‹€ν–‰ 쀑인 ν”„λ‘œμ„ΈμŠ€μ—μ„œ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•œλ‹€. 이에 따라 ν˜„μž¬ μ‹€ν–‰ 쀑인 ν”„λ‘œμ„ΈμŠ€λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό κ°–κ³  μžˆλŠ” λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ λœλ‹€. μƒμ„±λœ μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ™€ μ™„μ „νžˆ λ˜‘κ°™μ€ ν˜•νƒœλ‘œ 생성이 λ˜λŠ”λ°, μ΄λŠ” 곧 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ λ©”λͺ¨λ¦¬μ˜ μƒνƒœλ₯Ό κ·ΈλŒ€λ‘œ κ°–λŠ”λ‹€λŠ” 것을 μ˜λ―Έν•œλ‹€. 즉, λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ λ©”λͺ¨λ¦¬ μ£Όμ†Œ 곡간을 μΌκ΄„μ μœΌλ‘œ λ³΅μ‚¬ν•˜μ—¬ 이λ₯Ό μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—κ²Œ ν• λ‹Ήν•˜κ²Œ 되고, PC (Program Counter) μ—­μ‹œ λ³΅μ‚¬λ˜μ–΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” fork ν•¨μˆ˜ 호좜 이후뢀터 Contextλ₯Ό κ°–κ²Œ λœλ‹€.
PC (Program Counter)? PC λΌλŠ” 것은 CPU와 같은 쀑앙 처리 μž₯치 λ‚΄λΆ€μ˜ λ ˆμ§€μŠ€ν„° 쀑에 ν•˜λ‚˜λ‘œμ¨ ν˜„μž¬ 처리 쀑인 Instruction의 λ°”λ‘œ λ‹€μŒ Instruction의 μ£Όμ†Œλ₯Ό κ°–κ³  μžˆλ‹€. 즉, 싀행될 Instruction의 μœ„μΉ˜λ₯Ό μ•Œκ³  있기 λ•Œλ¬Έμ— Instruction Pointer 라고 λΆˆλ¦¬κΈ°λ„ ν•œλ‹€. μ—¬κΈ°μ„œ λ§ν•˜λŠ” Instructionμ΄λž€ C μ–Έμ–΄μ˜ μ½”λ“œ ν•œ 쀄을 λ§ν•˜λŠ” 것이 μ•„λ‹ˆλΌ, κΈ°κ³„μ μœΌλ‘œ μ²˜λ¦¬λ˜λŠ” 기계어 ν•œ ꡬ문을 λ§ν•œλ‹€. μœ„μ˜ forkλ₯Ό 예둜 λ“€λ©΄, forkλ₯Ό μ²˜λ¦¬ν•˜λŠ”λ° μš”κ΅¬λ˜λŠ” 기계어 묢음이 μžˆμ„ν…λ° 이λ₯Ό 마치게 되면 PCλŠ” fork λ‹€μŒμ— 싀행될 ꡬ문의 첫 κΈ°κ³„μ–΄μ˜ μœ„μΉ˜λ₯Ό κ°–κ³  있게 λœλ‹€. μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” PC μ—­μ‹œ λ³΅μ‚¬ν•˜μ—¬ μƒμ„±λ˜κΈ° λ•Œλ¬Έμ— PCκ°€ κ°–κ³  μžˆλŠ” μ£Όμ†Œμ— ν•΄λ‹Ήν•˜λŠ” InstructionλΆ€ν„° Fetchν•˜μ—¬ μ‹€ν–‰ν•œλ‹€.
이처럼 μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό κ°–κ²Œ λ˜μ—ˆμ„ λ•Œ fork의 λ°˜ν™˜ κ°’μœΌλ‘œ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—κ²Œ ν• λ‹Ήλ˜λŠ” κ°’κ³Ό μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—κ²Œ ν• λ‹Ήλ˜λŠ” 값이 μ„œλ‘œ λ‹€λ₯΄λ‹€. λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ pid 값이 fork의 λ°˜ν™˜ κ°’μœΌλ‘œ μ„€μ •λ˜κ³ , μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—λŠ” 0μ΄λΌλŠ” 값이 fork의 λ°˜ν™˜ κ°’μœΌλ‘œ μ„€μ •λœλ‹€. 만일 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œ forkλ₯Ό μˆ˜ν–‰ν–ˆμ„ λ•Œ μ •μƒμ μœΌλ‘œ forkκ°€ λ˜μ§€ μ•ŠλŠ”λ‹€λ©΄ -1이 λ°˜ν™˜λœλ‹€. λ”°λΌμ„œ 이에 λŒ€ν•œ μ—λŸ¬ 처리λ₯Ό λ³„λ„λ‘œ ν•΄μ£Όμ–΄μ•Ό ν•œλ‹€.

4. μ˜ˆμ‹œ

#include <stdio.h> #include <stdlib.h> #include <unistd.h> int global; int main(void) { int automatic; int *heap; pid_t pid; global = 10; automatic = 10; heap = (int *)malloc(sizeof(int)); if (!heap) return (1); *heap = 10; pid = fork(); if (pid == -1) { free(heap); return (1); } else if (!pid) { printf("Child: Before operations -> %d (Global), %d (Automatic), %d (Heap)\n", global, automatic, *heap); global += 10; automatic += 10; *heap += 10; printf("Child: After operations -> %d (Global), %d (Automatic), %d (Heap)\n", global, automatic, *heap); } else if (pid) { printf("Parent: Before operations -> %d (Global), %d (Automatic), %d (Heap)\n", global, automatic, *heap); global += 20; automatic += 20; *heap += 20; printf("Parent: After operations -> %d (Global), %d (Automatic), %d (Heap)\n", global, automatic, *heap); } free(heap); return (0); }
C
μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ λ©”λͺ¨λ¦¬ 곡간이 λ³„λ„λ‘œ κ΅¬μ„±λœλ‹€λŠ” 것은 μœ„μ™€ 같은 μ½”λ“œλ₯Ό μ‹€ν–‰ν•¨μœΌλ‘œμ¨ μ‰½κ²Œ μ•Œ 수 μžˆλ‹€. λ©”λͺ¨λ¦¬ 곡간이 λ³„λ„μ΄λ―€λ‘œ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—μ„œμ˜ 증감 μ—°μ‚° 결과와 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œμ˜ 증감 μ—°μ‚°μ˜ κ²°κ³Όκ°€ λ‹€λ₯Έ 것을 주어진 그림처럼 확인할 수 μžˆλ‹€.
μ• μ΄ˆμ— ν”„λ‘œμ„ΈμŠ€κ°€ μš΄μ˜μ²΄μ œλ‘œλΆ€ν„° 할당받은 λ©”λͺ¨λ¦¬λŠ” Shared Memory 기법을 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 이상 λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€μ™€ 곡유될 수 μ—†λŠ” 독립성을 보μž₯λ°›κΈ° λ•Œλ¬Έμ— λ³„λ„μ˜ κ³΅κ°„μ΄λΌλŠ” 것을 증λͺ…ν•˜κΈ° μœ„ν•΄ ꡳ이 μœ„μ™€ 같은 μ‹€ν—˜μ„ ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€.
#include <stdio.h> #include <unistd.h> int main(void) { pid_t pid; pid = fork(); if (pid == -1) return (1); else if (!pid) { printf("Child: I got a pid %d internally\n", pid); usleep(100000); printf("Child: Exiting with Code 0\n"); } else if (pid) { printf("Parent: I have a Child which pid is %d\n", pid); printf("Parent: Exiting with Code 0\n"); } return (0); }
C
주어진 μ˜ˆμ‹œλ₯Ό 싀행해보면, usleep으둜 0.1μ΄ˆκ°„ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό Sleep μƒνƒœλ‘œ λ§Œλ“€κΈ° λ•Œλ¬Έμ— λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ λ¨Όμ € μ’…λ£Œν•˜λŠ” 것을 λ³Ό 수 μžˆλ‹€. μ‰˜ μžμ²΄μ—μ„œ μ‹€ν–‰λœ ν”„λ‘œμ„ΈμŠ€λŠ” λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ΄κΈ° λ•Œλ¬Έμ— λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œλ§Œ κΈ°λ‹€λ¦¬κ²Œ 되고, λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œμ™€ λ™μ‹œμ— μ‰˜μ€ μƒˆλ‘œμš΄ ν”„λ‘¬ν”„νŠΈλ₯Ό 좜λ ₯μ‹œν‚€λŠ” 것을 λ³Ό 수 μžˆλ‹€. λ”°λΌμ„œ ν”„λ‘œκ·Έλž¨μ΄ 마친 뒀에 λ’€λŠ¦κ²Œ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ 좜λ ₯ν•œ ꡬ문이 μƒˆλ‘œμš΄ ν”„λ‘¬ν”„νŠΈ 이후에 λ‚˜νƒ€λ‚˜κ²Œ λœλ‹€. μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μž‘μ—…μ„ 마칠 λ•ŒκΉŒμ§€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ 이λ₯Ό κΈ°λ‹€λ¦¬κ²Œ ν•˜κΈ° μœ„ν•΄μ„  wait ν˜Ήμ€ waitpidλ₯Ό μ΄μš©ν•΄μ•Ό ν•œλ‹€. 이와 같은 ν•¨μˆ˜λ“€μ„ 톡해 λ©€ν‹° ν”„λ‘œμ„Έμ‹± ν”„λ‘œκ·Έλž¨μ— λŒ€ν•΄ 보닀 심도 있게 이해할 수 μžˆλ‹€. μ΄μ–΄μ§€λŠ” ν•­λͺ©μ—μ„œ wait ν•¨μˆ˜λΆ€ν„° μ΄ν•΄ν•΄λ³΄μž.

4) wait

1. μ˜μ‘΄μ„±

#include <sys/wait.h>
C

2. ν•¨μˆ˜ μ›ν˜•

pid_t wait(int *status);
C

3. ν•¨μˆ˜ μ„€λͺ…

wait ν•¨μˆ˜λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œλ₯Ό λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œ κΈ°λ‹€λ¦°λ‹€λŠ” κ°œλ…μœΌλ‘œ κ°„λ‹¨νžˆ 이해할 수 μžˆλ‹€. 이전 fork ν•¨μˆ˜μ˜ 예제λ₯Ό 보면 μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” 0.1μ΄ˆλ™μ•ˆ Sleep μƒνƒœκ°€ λ˜μ–΄ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ λ¨Όμ € μ’…λ£Œλ˜μ—ˆλŠ”λ°, 이 λ•Œ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ ppidλŠ” 1이 λ˜λ©΄μ„œ κ³ μ•„ ν”„λ‘œμ„ΈμŠ€κ°€ λœλ‹€. 이와 같은 ν˜„μƒμ„ 방지할 λ•Œ μ‚¬μš©λ˜λŠ” 것이 wait ν•¨μˆ˜μ΄λ‹€. wait ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜κ²Œ 되면 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œλ  λ•ŒκΉŒμ§€ Sleep μƒνƒœλ‘œ κΈ°λ‹€λ¦¬κ²Œ 되며, μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œλ˜μ—ˆμ„ λ•Œ λΉ„λ‘œμ†Œ wait ν•¨μˆ˜ μ΄ν›„μ˜ ꡬ문을 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ μ²˜λ¦¬ν•  수 있게 λœλ‹€. κ·Έλ ‡λ‹€λ©΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό 기닀리지 μ•Šμ•„λ„ λ˜λŠ” μƒν™©μ—μ„œλŠ” wait ν•¨μˆ˜λ₯Ό 쓰지 μ•Šμ•„λ„ λ˜λŠ” κ²ƒμΌκΉŒ? 이에 λŒ€ν•œ 닡을 μ•„λž˜μ˜ μ˜ˆμ‹œμ—μ„œ μ°Ύμ•„λ³Ό 것이닀. κ·Έ 전에 wait ν•¨μˆ˜μ˜ μ‹œκ·Έλ‹ˆμ²˜μ— λŒ€ν•΄μ„œ λ¨Όμ € μ•Œμ•„λ³΄μž.
μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ main문의 return ν˜Ήμ€ exit을 톡해 λͺ…μ‹œλœ μ’…λ£Œ μ½”λ“œμ— μ˜ν•΄μ„œ (정상 μ’…λ£Œλ“  비정상 μ’…λ£Œλ“ ) μ’…λ£Œλ˜λ©΄ wait ν•¨μˆ˜μ˜ λ°˜ν™˜ 값은 μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ pidκ°€ 되고, 그렇지 μ•Šκ³  μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ‹œκ·Έλ„μ— μ˜ν•΄ μ’…λ£Œλ˜λ©΄ errnoκ°€ EINTR둜 μ„€μ •λ˜λ©΄μ„œ -1을 λ°˜ν™˜ν•œλ‹€. 이 λ•Œ wait ν•¨μˆ˜μ˜ 인자둜 받은 statusλŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œλ˜λ©΄μ„œ λ°˜ν™˜ν•œ λ‹€μ–‘ν•œ 정보듀을 κΈ°λ‘ν•˜κ²Œ λœλ‹€. μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ λ©”λͺ¨λ¦¬ 곡간이 λ³„λ„λ‘œ μœ μ§€λ˜κΈ° λ•Œλ¬Έμ— statusλΌλŠ” μΈμžλŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—κ²Œ λ„˜μ–΄κ°€μ„œ κΈ°λ‘λ˜λŠ” 것이 μ•„λ‹ˆλΌ 말 κ·ΈλŒ€λ‘œ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œλ˜λ©΄μ„œ λ„˜κΈ΄ 정보듀을 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ μ·¨ν•˜λ©΄μ„œ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œ μ‹œμ μ— κΈ°λ‘λ˜λŠ” 것이닀. wait ν•¨μˆ˜μ—μ„œ μ‚¬μš©λ˜λŠ” statusλŠ” waitpidμ—μ„œ μ‚¬μš©λ˜λŠ” status와 λ™μΌν•˜λ―€λ‘œ 쑰금 κ΅¬κ΅¬μ ˆμ ˆν•˜λ”λΌλ„ 짚고 λ„˜μ–΄κ°€λ³΄μž.
pid_tλŠ” Mac OS X와 같은 Darwin μš΄μ˜μ²΄μ œμ—μ„œ __darwin_id_t둜 Aliasλ˜μ–΄ μžˆλ‹€. pid_t뿐만 μ•„λ‹ˆλΌ uid_t, gid_t와 같은 νƒ€μž…λ“€λ„ 이에 ν•΄λ‹Ήλ˜λ©°, __darwin_id_tλŠ” __uint32_t이닀.
status에 κΈ°λ‘λ˜λŠ” 정보듀은 μ’…λ£Œ μ½”λ“œμ™€ μ‹œκ·Έλ„μ΄λ‹€. μ—¬λŸ¬ 정보가 ν•˜λ‚˜μ˜ λ³€μˆ˜μ— κΈ°λ‘λ˜μ—ˆλ‹€λŠ” 것은 λΉ„νŠΈλ₯Ό μ΄μš©ν•˜μ—¬ κΈ°λ‘λ˜μ—ˆλ‹€λŠ” κ²ƒμ΄λ―€λ‘œ, 이와 같은 정보λ₯Ό 각각 νšŒμˆ˜ν•˜κΈ° μœ„ν•΄μ„  λ³„λ„μ˜ λ§ˆμŠ€ν‚Ή μž‘μ—…μ΄ ν•„μš”ν•˜λ‹€. λ”°λΌμ„œ 각 정보듀이 μ–Όλ§ŒνΌμ˜ λΉ„νŠΈλ₯Ό μ΄μš©ν–ˆλŠ”μ§€ μ •ν™•νžˆ ν•˜κΈ° μœ„ν•΄μ„œ <sys/wait.h>λ₯Ό 확인할 ν•„μš”κ°€ μžˆλ‹€. μœ„ 그림을 보면 status에 기둝된 정보듀을 확인할 수 μžˆλ„λ‘ 맀크둜λ₯Ό 톡해 μ •μ˜λœ 것을 λ³Ό 수 μžˆλŠ”λ°, λ‚΄μš©μ„ λ†“μΉ˜μ§€ μ•Šλ„λ‘ 찬찬히 μ§šμ–΄λ³΄μž.
μœ„ μ½”λ“œλ₯Ό 얼핏 λ³΄μ•˜μ„ λ•Œ 주둜 μ΄μš©λ˜λŠ” λΉ„νŠΈ 연산은 8개의 λΉ„νŠΈλ₯Ό μ‰¬ν”„νŒ… ν•˜λŠ” 연산이며, 이 λ•Œ λΉ„κ΅λŠ” 단 1λ°”μ΄νŠΈλ§Œμ„ μˆ˜ν–‰ν•˜λŠ” 것을 μ•Œ 수 μžˆλ‹€. ν•΄λ‹Ή 연산이 무엇을 μœ„ν•œ κ²ƒμΈμ§€λŠ” μ•„μ§κΉŒμ§€ μ•Œ 수 μ—†μ§€λ§Œ, int κ°’μ˜ statusλ₯Ό μ΄μš©ν–ˆμ„ λ•Œ 기둝 μžμ²΄λŠ” 2λ°”μ΄νŠΈ λ‚΄μ—μ„œ μ΄λ€„μ§„λ‹€λŠ” 것을 μœ μΆ”ν•  수 μžˆλ‹€. (μ‰¬ν”„νŒ… ν–ˆμ„ λ•Œ 1λ°”μ΄νŠΈμ΄λ―€λ‘œ κΈ°μ‘΄ 1λ°”μ΄νŠΈκΉŒμ§€ 총 2λ°”μ΄νŠΈκ°€ λœλ‹€.) μ΄μš©λ˜λŠ” 곡간이 2λ°”μ΄νŠΈμž„μ—λ„ statusκ°€ int둜 μ΄μš©λ˜λŠ” μ΄μœ λŠ” 곧 μ•Œκ²Œ λœλ‹€.
λ°”μ΄νŠΈ 값이 κ°–κ³  μžˆλŠ” 정보에 λŒ€ν•΄ μœ„ 그림을 μ΄μš©ν•˜μ—¬ 풀어보면, status의 4λ°”μ΄νŠΈ μ€‘μ—μ„œ 2번 index의 λ°”μ΄νŠΈλŠ” μ’…λ£Œ μ½”λ“œλ₯Ό μ˜λ―Έν•˜κ³  3번 index의 λ°”μ΄νŠΈλŠ” μ‹œκ·Έλ„μ„ μ˜λ―Έν•œλ‹€. 즉, μ’…λ£Œ μ½”λ“œμ™€ μ‹œκ·Έλ„μ„ μ‘°ν•©ν•œ 값이 곧 statusκ°€ λ˜λŠ”λ° 이 λ•Œ μ΄μš©ν•˜λŠ” 연산이 W_EXITCODEλΌλŠ” 맀크둜 ν•¨μˆ˜μ΄λ‹€. μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œλ˜λ©΄ W_EXITCODEλ₯Ό μ΄μš©ν•˜μ—¬ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ statusλ₯Ό κΈ°λ‘ν•˜κ²Œ 되고, W_EXITCODEλŠ” μœ λ‹‰μŠ€ 섀계 상 int νƒ€μž…μœΌλ‘œ μ΄μš©ν•˜λ„λ‘ λ˜μ–΄ μžˆλ‹€. λ”°λΌμ„œ 2λ°”μ΄νŠΈλ§Œμ„ μ΄μš©ν•¨μ—λ„ statusκ°€ int둜 μ΄μš©λ˜λŠ” 것이닀.
μ’…λ£Œ μ½”λ“œ 및 μ‹œκ·Έλ„μ— λŒ€ν•œ 기둝의 λΆ„κΈ°λŠ” μœ„ κ·Έλ¦Όκ³Ό 같이 λ‚˜νƒ€λ‚œλ‹€. λ°˜ν™˜ 값에 λŒ€ν•΄ μ„€λͺ…ν•  λ•Œ 살짝 μ–ΈκΈ‰ν•œλŒ€λ‘œ μ’…λ£Œ μ½”λ“œμ— μ˜ν•œ μ’…λ£ŒμΈμ§€, μ‹œκ·Έλ„μ— μ˜ν•œ μ’…λ£ŒμΈμ§€κ°€ status 기둝에 영ν–₯을 끼치게 λœλ‹€. μ’…λ£Œ μ½”λ“œμ— μ˜ν•œ μ’…λ£Œκ°€ λ°œμƒν–ˆμ„ λ•Œμ˜ statusλ₯Ό μ•Œμ•„λ³Έ λ’€ μ‹œκ·Έλ„μ— μ˜ν•œ μ’…λ£Œκ°€ λ°œμƒν–ˆμ„ λ•Œμ˜ statusλ₯Ό μ•Œμ•„λ³΄λ„λ‘ ν•˜μž.
일반적으둜 ν”„λ‘œμ„ΈμŠ€κ°€ 정상적이든 비정상적이든 μ‹œκ·Έλ„ 없이 μ’…λ£Œλ₯Ό ν•˜κ²Œ 되면, μ’…λ£Œ μ½”λ“œκ°€ 2번 index의 λ°”μ΄νŠΈκ°€ 기둝되고 3번 index의 λ°”μ΄νŠΈλŠ” μ‹œκ·Έλ„μ΄ μ—†μœΌλ―€λ‘œ 0으둜 μ±„μ›Œμ§€κ²Œ λœλ‹€. 정상 μ’…λ£Œλ₯Ό μ˜λ―Έν•˜λŠ” 0을 μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ λ°˜ν™˜ν•˜κ²Œ 되면, λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œλŠ” μ’…λ£Œ μ½”λ“œλ„ 0이고 μ‹œκ·Έλ„λ„ 0μ΄λ―€λ‘œ status 값은 0이 λœλ‹€. λ°˜λŒ€λ‘œ 비정상 μ’…λ£Œλ₯Ό μ˜λ―Έν•˜λŠ” 0 μ΄μ™Έμ˜ 값을 μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ λ°˜ν™˜ν•˜κ²Œ 되면, status 값이 λΉ„μ •μƒμ μœΌλ‘œ 큰 값이 λ‚˜μ˜€λŠ” 것을 확인할 수 μžˆλŠ”λ° μ΄λŠ” 3번 index의 λ°”μ΄νŠΈκ°€ 0으둜 μ±„μ›Œμ Έ μžˆλŠ” 것을 κ³ λ €ν•˜μ§€ μ•Šμ•„μ„œ κ·Έλ ‡λ‹€. 0 μ΄μ™Έμ˜ μ’…λ£Œ μ½”λ“œλ₯Ό λ°›μ•˜μ„ λ•Œ 이λ₯Ό μ •ν™•ν•˜κ²Œ μ·¨λ“ν•˜κΈ° μœ„ν•΄μ„  μ‹œκ·Έλ„μ— λŒ€ν•œ 정보λ₯Ό λ°°μ œν•΄μ•Όν•˜λ―€λ‘œ, 8개의 λΉ„νŠΈλ₯Ό 였λ₯Έμͺ½μœΌλ‘œ μ‰¬ν”„νŒ… ν•œ ν›„ μ •ν™•νžˆ μ΅œν•˜μœ„ 8개의 λΉ„νŠΈλ₯Ό μ·¨λ“ν•˜λ©΄ λœλ‹€.
λͺ…μ‹œλœ μ’…λ£Œ μ½”λ“œμ— μ˜ν•œ μ’…λ£Œ
만일 ν”„λ‘œμ„ΈμŠ€κ°€ μ‹œκ·Έλ„μ— μ˜ν•΄μ„œ μ’…λ£Œλ₯Ό ν•˜κ²Œ 되면, μ΄λŠ” 크게 STOP μ‹œκ·Έλ„μ— μ˜ν•œ μ’…λ£ŒμΈμ§€ 이λ₯Ό μ œμ™Έν•œ μ‹œκ·Έλ„μ— μ˜ν•œ μ’…λ£ŒμΈμ§€μ— 따라 λ‚˜λ‰˜κ²Œ λœλ‹€. STOP μ‹œκ·Έλ„μ— μ˜ν•œ μ’…λ£ŒμΈ κ²½μš°μ—λŠ” CONT μ‹œκ·Έλ„μ„ 톡해 STOP μ‹œμ λΆ€ν„° μ΄μ–΄μ„œ μ‹€ν–‰ν•  수 μžˆμ§€λ§Œ κ·Έ μ™Έμ˜ μ‹œκ·Έλ„μ€ 그렇지 μ•Šλ‹€λŠ” μ μ—μ„œ 차이가 μžˆλ‹€.
μš°μ„  STOP μ‹œκ·Έλ„κ³Ό CONT μ‹œκ·Έλ„μ€ λ‹€λ₯Έ μ‹œκ·Έλ„λ“€κ³Ό 달리 자기 μžμ‹ μ—κ²Œ ν•΄λ‹Ήλ˜λŠ” μ‹œκ·Έλ„ 번호λ₯Ό μ‚¬μš©ν•˜λ”λΌλ„ λ‚΄λΆ€μ μœΌλ‘œ 3번 index의 λ°”μ΄νŠΈ 값이 127둜 κ³ μ •λœλ‹€. 이 λ•Œ μ’…λ£Œ μ½”λ“œκ°€ κΈ°λ‘λ˜λŠ” 2번 index의 λ°”μ΄νŠΈκ°€ 곧 자기 μžμ‹ μ—κ²Œ ν•΄λ‹Ήλ˜λŠ” μ‹œκ·Έλ„ 번호둜 μ±„μ›Œμ§„λ‹€. CONT μ‹œκ·Έλ„μ„ λ³΄λ‚΄λŠ” κ²½μš°μ—λŠ” SIGCONT에 ν•΄λ‹Ήν•˜λŠ” 19κ°€ μ±„μ›Œμ§€κ³ , STOP μ‹œκ·Έλ„μ„ λ³΄λ‚΄λŠ” κ²½μš°μ—λŠ” SIGSTOP에 ν•΄λ‹Ήν•˜λŠ” 17이 μ±„μ›Œμ§€κ²Œ λœλ‹€. STOP μ‹œκ·Έλ„μ— ν•΄λ‹Ήν•˜λŠ” 17κ³Ό CONT μ‹œκ·Έλ„μ— ν•΄λ‹Ήν•˜λŠ” 19을 3번 index의 λ°”μ΄νŠΈμ— μ΄μš©ν•˜λ©΄ νŽΈν• ν…λ°, κ·Έλ ‡κ²Œ ν•˜μ§€ μ•ŠλŠ” μ΄μœ λŠ” 두 μ‹œκ·Έλ„μ΄ 유기적으둜 μ—°κ²°λ˜μ–΄ 있기 λ•Œλ¬Έμ— μŠ€μœ„μΉ˜μ˜ on/off처럼 λ™μž‘ν•˜λ„λ‘ λ§Œλ“€κΈ° μœ„ν•¨μ΄λ‹€. ν•˜λ‚˜μ˜ νŠΉμ •ν•œ 값을 정해두고 μ²˜λ¦¬ν•˜κ²Œ 되면 ν”„λ‘œκ·Έλž¨ μž…μž₯μ—μ„œλŠ” 더 νŽΈν•΄μ§„λ‹€. (Mac OS X의 μ‹œκ·Έλ„μ€ μœ λ‹‰μŠ€μ˜ μ‹œκ·Έλ„μ„ λ”°λ₯Έλ‹€. μ‹œμŠ€ν…œ λ§ˆλ‹€ μ‹œκ·Έλ„μ΄ λ‹€λ₯Ό 수 μžˆμœΌλ―€λ‘œ 이에 μœ μ˜ν•˜μž.)
μ‹œκ·Έλ„μ— ν•΄λ‹Ήν•˜λŠ” 번호λ₯Ό μ΄μš©ν•˜λ©΄ μ–΄λ–€ μ‹œκ·Έλ„μΈμ§€ 각각 비ꡐλ₯Ό ν•΄μ•Όν•˜μ§€λ§Œ, 두 λ™μž‘ μžμ²΄κ°€ 유기적으둜 μ—°κ²°λ˜μ–΄ μžˆμœΌλ―€λ‘œ λ™μΌν•œ 값을 μ΄μš©ν•˜λ©΄ ν•œ 번의 λΉ„κ΅λ§ŒμœΌλ‘œ νŽΈν•˜κ²Œ μ²˜λ¦¬κ°€ κ°€λŠ₯ν•˜λ‹€. ν˜„μž¬ ν”„λ‘œμ„ΈμŠ€μ˜ μƒνƒœλŠ” ν”„λ‘œκ·Έλž¨μ˜ λ‚΄λΆ€μ—μ„œ μ²˜λ¦¬ν•˜μ§€ μ•Šμ•„λ„ κ·Έ μƒνƒœλ₯Ό μ•Œ 수 μžˆλ‹€.
μ‹œκ·Έλ„μ— μ˜ν•œ μ’…λ£Œ (STOP μ‹œκ·Έλ„ 및 CONT μ‹œκ·Έλ„)
STOP μ‹œκ·Έλ„ μ΄μ™Έμ˜ μ‹œκ·Έλ„μ„ ν†΅ν•΄μ„œ ν”„λ‘œκ·Έλž¨μ΄ μ’…λ£Œλ˜λ©΄, 2번 indexλ₯Ό μ˜λ―Έν•˜λŠ” μ’…λ£Œ μ½”λ“œλŠ” 0으둜 μ±„μ›Œμ§€λ©° μ‹œκ·Έλ„μ— ν•΄λ‹Ήν•˜λŠ” 값이 3번 index에 μ±„μ›Œμ§€κ²Œ λœλ‹€.
μ‹œκ·Έλ„μ— μ˜ν•œ μ’…λ£Œ (λ‚˜λ¨Έμ§€ μ‹œκ·Έλ„)
wait의 인자둜 μ‚¬μš©λ˜λŠ” status에 μ–΄λ–€ 값듀이 기둝되고, 이λ₯Ό μ–΄λ–»κ²Œ μ·¨λ“ν•˜λŠ”μ§€ μ•Œμ•„λ³΄μ•˜λ‹€. 이듀을 μ΄μš©ν•˜μ—¬ μ½”λ“œλ₯Ό μž‘μ„±ν•  λ•Œμ—λŠ” ν•˜λ‚˜μ˜ κ²½μš°μ— λŒ€ν•΄μ„œλ§Œ μ²˜λ¦¬ν•΄λ‘λŠ” 것보닀, WIFEXITED, WIFSIGNALED, WIFSTOPPED, WIFCONTINUEDλ₯Ό λͺ¨λ‘ λΆ„κΈ° μ²˜λ¦¬ν•˜κ³  그에 따라 μ‚¬μš©λœ 값을 각각 μ·¨λ“ν•˜μ—¬ ν”„λ‘œκ·Έλž¨μ΄ 상황에 맞게 Contextλ₯Ό μ΄μ–΄κ°ˆ 수 μžˆλ„λ‘ ν•˜λŠ” 것이 λ°”λžŒμž‘ν•œ λ°©ν–₯이라고 λ³Ό 수 μžˆλ‹€. μ•„λž˜μ— κ°„λ‹¨ν•œ μ½”λ“œλ₯Ό λ‘μ—ˆλŠ”λ° 이와 같은 ν˜•μ‹μœΌλ‘œ 상황에 따라 λΆ„κΈ°μ²˜λ¦¬λ₯Ό ν•΄μ£Όλ©΄ λœλ‹€.
λΆ„κΈ° 처리
wait ν•¨μˆ˜μ˜ λ°˜ν™˜ κ°’κ³Ό μ‚¬μš©λ˜λŠ” μΈμžμ— λŒ€ν•΄μ„œ μ•Œμ•„λ³΄μ•˜μœΌλ―€λ‘œ, μ•„λž˜ μ˜ˆμ‹œλ₯Ό 톡해 ν•¨μˆ˜ μ„€λͺ… μ΄ˆκΈ°μ— μ–ΈκΈ‰ν•œ 뢀뢄에 λŒ€ν•΄μ„œ μ•Œμ•„λ³΄λ„λ‘ ν•˜μž.

4. μ˜ˆμ‹œ

#include <stdio.h> #include <unistd.h> int main(void) { pid_t pid; pid = fork(); if (pid == -1) return (1); else if (!pid) printf("Child: I will be exited\n"); else { printf("Parent: I have a Child which pid is %d\n", pid); while (1) ; } return (0); }
C
wait ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” 주된 λͺ©μ μ€ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œλ₯Ό κΈ°λ‹€λ¦¬λŠ” 것 말고도, λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œ μƒμ„±λœ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό μˆ˜κ±°ν•˜λŠ” 데 μžˆλ‹€. 주어진 μ½”λ“œλ₯Ό 싀행해보면 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ λ¬΄ν•œ 루프에 κ±Έλ € 있기 λ•Œλ¬Έμ— μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ 좜λ ₯ ꡬ문을 μˆ˜ν–‰ν•œ 뒀에 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λ³΄λ‹€ λ¨Όμ € μ’…λ£Œλ˜λŠ” 것을 λ³Ό 수 μžˆλ‹€. μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ •μƒμ μœΌλ‘œ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λ³΄λ‹€ λ¨Όμ € μ’…λ£Œλ˜μ—ˆκΈ° λ•Œλ¬Έμ— 아무 λ¬Έμ œκ°€ 없을 것 κ°™μ§€λ§Œ, 주어진 κ²°κ³Όλ₯Ό μ‚΄νŽ΄λ³΄λ©΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ—¬μ „νžˆ μ‚΄μ•„μ„œ μ’€λΉ„ ν”„λ‘œμ„ΈμŠ€λ‘œ μœ μ§€λ˜κ³  μžˆλŠ” 것을 λ³Ό 수 μžˆλ‹€. μ’€λΉ„ ν”„λ‘œμ„ΈμŠ€λŠ” μ΄λ¦„μ²˜λŸΌ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œλ˜κΈ° μ „κΉŒμ§€λŠ” ν”„λ‘œμ„ΈμŠ€ ν…Œμ΄λΈ”μ— 남아 μžˆλŠ” μƒνƒœλ‘œ μœ μ§€λœλ‹€. λ”°λΌμ„œ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” κΌ­ wait ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄μ„œ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό μˆ˜κ±°ν•˜μ—¬ ν”„λ‘œμ„ΈμŠ€ ν…Œμ΄λΈ”μ—μ„œ μ‚­μ œν•  μ˜λ¬΄κ°€ μžˆμœΌλ―€λ‘œ 이에 따라 주어진 μ½”λ“œλ₯Ό μ•„λž˜μ™€ 같이 wait ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ„λ‘ μˆ˜μ •ν•΄μ•Ό ν•œλ‹€.
μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œλ˜λŠ” μ¦‰μ‹œ μš΄μ˜μ²΄μ œμ—μ„œλŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ λͺ¨λ“  μžμ›μ„ 문제 없이 νšŒμˆ˜ν•˜μ§€λ§Œ, 이 μ‹œμ μ— ν”„λ‘œμ„ΈμŠ€ ν…Œμ΄λΈ”μ—μ„œ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό μ‚­μ œκΉŒμ§€ 해버리면 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€μ— λŒ€ν•œ μƒνƒœμ— λŒ€ν•΄ μ•Œ 수 μ—†λŠ” 상황이 λ˜μ–΄λ²„λ¦°λ‹€. μ’€λΉ„ ν”„λ‘œμ„ΈμŠ€λ₯Ό λ‘” μ΄μœ λŠ” 이 λ•Œλ¬Έμ΄λ‹€.
#include <stdio.h> #include <sys/wait.h> #include <unistd.h> int main(void) { pid_t pid; pid_t ret; pid = fork(); if (pid == -1) return (1); else if (!pid) printf("Child: I will be exited\n"); else { printf("Parent: I have a Child which pid is %d\n", pid); ret = wait(NULL); printf("Parent: %d Child has been retrieved\n", ret); while (1) ; } return (0); }
C

5) waitpid

1. μ˜μ‘΄μ„±

#include <sys/wait.h>
C

2. ν•¨μˆ˜ μ›ν˜•

pid_t waitpid(pid_t pid, int *status, int options);
C

3. ν•¨μˆ˜ μ„€λͺ…

λ°˜ν™˜ κ°’ 및 statusλΌλŠ” μΈμžλŠ” wait ν•¨μˆ˜μ™€ λ™μΌν•˜κΈ° λ•Œλ¬Έμ— 이전 ν•­λͺ©μ—μ„œ wait ν•¨μˆ˜λΆ€ν„° 읽어보고 μ˜€λŠ” 것을 κΆŒν•œλ‹€. waitpid ν•¨μˆ˜μ—μ„œλŠ” wait ν•¨μˆ˜μ™€ 달리 pid_t νƒ€μž…μœΌλ‘œ 된 pid와 int νƒ€μž…μ˜ option을 μΆ”κ°€μ μœΌλ‘œ 인자둜 μ‚¬μš©ν•˜λŠ” 것을 λ³Ό 수 μžˆλ‹€. waitpid의 κΈ°λŠ₯ μžμ²΄λŠ” wait ν•¨μˆ˜μ™€ λ™μΌν•˜κ²Œ, μ •μƒμ μœΌλ‘œ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μƒνƒœλ₯Ό νšλ“ν•˜κ³  μžμ›μ„ μˆ˜κ±°ν•˜κ³  λ°˜ν™˜ν•˜λŠ”λ° μžˆλ‹€. κ·Έλ ‡λ‹€λ©΄ μ–΄λ–€ κΈ°λŠ₯이 λ‹€λ₯Έμ§€ μΆ”κ°€μ μœΌλ‘œ 받은 μΈμžλ“€μ„ 톡해 μ•Œμ•„λ³΄κ³ , waitpid ν•¨μˆ˜κ°€ λ§Œλ“€μ–΄μ§„ 의의λ₯Ό μ•Œμ•„λ³΄μž.
wait ν•¨μˆ˜μ—μ„œ λ³΄μ•˜λ˜ 이전 μ˜ˆμ‹œλ“€μ„ 보면 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œ μƒμ„±λœ μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” 단 1κ°œμ˜€λ‹€. λ§Œμ•½ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œ forkλ₯Ό 톡해 μƒμ„±ν•œ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ 1κ°œκ°€ μ•„λ‹ˆλΌ μ—¬λŸ¬ 개라면, wait ν•¨μˆ˜λ₯Ό μ΄μš©ν–ˆμ„ λ•Œ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ ContextλŠ” μž„μ˜μ˜ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œλ₯Ό κΈ°λ‹€λ Έλ‹€κ°€ μˆ˜κ±°ν•˜κ²Œ λœλ‹€. 즉, νŠΉμ • pidλ₯Ό 가진 μžμ‹ ν”„λ‘œμ„ΈμŠ€μ— λŒ€ν•œ wait이 λΆˆκ°€λŠ₯ν•˜λ‹€λŠ” 것이닀. λ”°λΌμ„œ νŠΉμ • ν”„λ‘œμ„ΈμŠ€μ— λŒ€ν•΄μ„œ μˆ˜ν–‰ν•  수 μžˆλ„λ‘ waitpid ν•¨μˆ˜μ—λŠ” pidλΌλŠ” 인자λ₯Ό λ°›κ²Œ λ˜μ–΄ μžˆλ‹€. 이 λ•Œ waitpid의 pid둜 -1μ΄λΌλŠ” 값을 주게 되면, waitκ³Ό λ™μΌν•˜κ²Œ λ™μž‘ν•˜μ—¬ μž„μ˜μ˜ ν”„λ‘œμ„ΈμŠ€λ₯Ό μˆ˜κ±°ν•˜κ²Œ λœλ‹€.
λ˜ν•œ wait ν•¨μˆ˜μ˜ μ˜ˆμ‹œμ—μ„œ λΆˆκ°€ν”Όν•˜κ²Œ waitpidλ₯Ό μ‚¬μš©ν–ˆλ˜ 것을 λ³Ό 수 μžˆμ—ˆλŠ”λ°, waitpid ν•¨μˆ˜μ—λŠ” νŠΉμ • option을 톡해 wait ν•¨μˆ˜μ—μ„œ μˆ˜ν–‰ν•˜μ§€ λͺ»ν•˜λŠ” κΈ°λŠ₯듀을 μˆ˜ν–‰ν•˜λ„λ‘ λ§Œλ“€ 수 μžˆλ‹€. 이전 μ˜ˆμ‹œλ₯Ό λ– μ˜¬λ €λ³΄λ©΄ WUNTRACED, WCONTINUED, WNOHANG듀이 μžˆμ—ˆλŠ”λ°, 이듀이 곧 waitpid의 option으둜 μ‚¬μš©ν•  수 μžˆλŠ” 값듀이닀. ν•΄λ‹Ή 값듀은 λΉ„νŠΈ λ‹¨μœ„λ‘œ 값이 맀겨져 있기 λ•Œλ¬Έμ—, OR λΉ„νŠΈ 연산을 톡해 ν•œλ²ˆμ— option으둜 μ‚¬μš©ν•  μˆ˜λ„ μžˆλ‹€. (μ—¬κΈ°μ„œ μ œμ‹œλœ 3개의 option외에도 WEXITED, WSTOPPED, WNOWAIT이 μžˆμœΌλ―€λ‘œ 이에 λŒ€ν•΄μ„  직접 찾아보도둝 ν•˜μž.)
WUNTRACED β†’ STOP μ‹œκ·Έλ„μ„ 톡해 싀행을 멈좘 μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ status에 λŒ€ν•΄μ„œ λ°˜ν™˜
WCONTINUED β†’ CONT μ‹œκ·Έλ„μ„ 톡해 싀행을 μž¬κ°œν•œ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ status에 λŒ€ν•΄μ„œ λ°˜ν™˜
WNOHANG β†’ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œλ₯Ό 기닀리지 μ•Šκ³  μ¦‰μ‹œ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ status에 λŒ€ν•΄μ„œ λ°˜ν™˜
WNOHANG을 μ‚¬μš©ν•˜λ©΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œλ₯Ό 기닀리지 μ•ŠκΈ° λ•Œλ¬Έμ— WNOHANG을 μ‚¬μš©ν•œ waitpid ν•¨μˆ˜μ˜ 호좜 μ‹œμ μ— μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œλ˜μ—ˆμ„ μˆ˜λ„ 있고 그렇지 μ•Šμ„ μˆ˜λ„ μžˆλ‹€. 두 κ²½μš°μ—λŠ” waitpid의 λ°˜ν™˜ 값이 μ„œλ‘œ λ‹€λ₯΄λ‹€. WNOHANG을 μ‚¬μš©ν•˜κΈ° 이전에 μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œλœ κ²½μš°μ—λŠ” statusκ°€ μ˜¬λ°”λ₯Έ κ°’μ΄λ―€λ‘œ, waitpid의 λ°˜ν™˜ 값은 μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ pidκ°€ λœλ‹€. λ°˜λŒ€λ‘œ μ˜΅μ…˜μ΄ μ‚¬μš©λ˜μ—ˆμ„ λ•Œ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œλ˜μ§€ μ•Šμ€ μƒνƒœλΌλ©΄ statusκ°€ μ˜¬λ°”λ₯΄μ§€ μ•Šμ€ 값이 λ˜λ―€λ‘œ, waitpid의 λ°˜ν™˜ 값은 0이 λœλ‹€.
WUNTRACED 및 WCONTINUEDλŠ” wait ν•¨μˆ˜μ˜ μ˜ˆμ‹œμ—μ„œ λ³΄μ•˜λ˜ κ²ƒμ²˜λŸΌ STOP μ‹œκ·Έλ„, CONT μ‹œκ·Έλ„μ„ 받은 μžμ‹ ν”„λ‘œμ„ΈμŠ€μ— λŒ€ν•΄μ„œλ„ statusλ₯Ό μ–»μ–΄μ˜¬ 수 μžˆλ„λ‘ λ§Œλ“€μ–΄μ€€λ‹€. wait ν•¨μˆ˜λŠ” 이와 같은 κΈ°λŠ₯을 μˆ˜ν–‰ν•  수 μ—†μœΌλ―€λ‘œ ν•΄λ‹Ή μƒν™©μ—μ„œλŠ” waitpid ν•¨μˆ˜κ°€ μœ μš©ν•˜κ²Œ 이용될 수 μžˆλ‹€.
μ€‘λ³΅λœ μ˜ˆμ‹œλŠ” μž‘μ„±ν•˜μ§€ μ•Šμ„ μ˜ˆμ •μ΄λ―€λ‘œ 두 option에 λŒ€ν•œ μ˜ˆμ‹œλŠ” wait ν•¨μˆ˜μ˜ μ˜ˆμ‹œλ₯Ό μ°Έκ³ ν•˜μž.
WNOHANGμ΄λΌλŠ” option은 wait ν•¨μˆ˜μ˜ μ˜ˆμ‹œμ—μ„œ μ–ΈκΈ‰ν•œλŒ€λ‘œ 동기 및 비동기, Block 및 Non-Blockμ΄λΌλŠ” κ°œλ…μ΄ 이용되기 λ•Œλ¬Έμ— 이에 λŒ€ν•œ 이해가 μ„ μˆ˜μ μœΌλ‘œ μš”κ΅¬λœλ‹€. WNOHANG을 μ‚¬μš©ν•˜μ§€ μ•Šμ•˜μ„ λ•Œμ˜ waitpid의 λ™μž‘μ€ wait ν•¨μˆ˜μ™€ 크게 λ‹€λ₯΄μ§€ μ•Šλ‹€. λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œ wait ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜κΈ° μ „κΉŒμ§€λŠ” λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ™€ μžμ‹ ν”„λ‘œμ„ΈμŠ€ λ‘˜ λ‹€ 각자의 Contextλ₯Ό 따라 λΉ„λ™κΈ°μ μœΌλ‘œ μ‹€ν–‰λ˜κ³ , λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œ wait ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν–ˆμ„ λ•Œ 곧 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” Block μƒνƒœκ°€ λ˜μ–΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œ μ „κΉŒμ§€ 더 μ΄μƒμ˜ Contextλ₯Ό 이어가지 μ•ŠλŠ”λ‹€. 즉, wait ν•¨μˆ˜μ™€ WNOHANGμ΄λΌλŠ” option이 μ—†λŠ” waitpid ν•¨μˆ˜λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œλ₯Ό 기닀리기 μœ„ν•΄ Block μƒνƒœλ₯Ό μ•ΌκΈ°ν•˜λ„λ‘ λ™μž‘ν•œλ‹€λŠ” 것이 곧 μš”μ μ΄λ‹€.
ν•΄λ‹Ή ν•¨μˆ˜λ“€μ˜ Blockμ΄λΌλŠ” 기본적인 νŠΉμ„±μ„ 잘만 μ΄μš©ν•˜λ©΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ λ™μž‘μ΄ 일련의 동기적 νλ¦„μœΌλ‘œ μ‹€ν–‰λ˜λ„λ‘ λ§Œλ“€ 수 μžˆλ‹€. λ”°λΌμ„œ Blockμ΄λΌλŠ” νŠΉμ„±μ€ μˆœμ„œλ₯Ό μ§€μΌœμ„œ μˆ˜ν–‰λ˜μ–΄μ•Ό ν•˜λŠ” μ½”λ“œλ₯Ό λ§Œλ“€μ–΄μ•Ό ν•˜λŠ” κ²½μš°μ—λŠ” κ½€λ‚˜ 큰 μž₯점이 λœλ‹€. ν•˜μ§€λ§Œ κ³Όλ„ν•˜κ²Œ Block μƒνƒœλ₯Ό λ§Œλ“€λ©΄ ν”„λ‘œκ·Έλž¨μ˜ μ„±λŠ₯ μ €ν•˜λ‘œ μ΄μ–΄μ§ˆ 수 있기 λ•Œλ¬Έμ— μ£Όμ˜ν•΄μ•Ό ν•œλ‹€.
ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜λ‹€λ³΄λ©΄ μœ„μ—μ„œ μ–ΈκΈ‰ν•œ κ²ƒμ²˜λŸΌ 동기적인 νλ¦„μœΌλ‘œλ§Œ λ™μž‘ν•˜λ„λ‘ λ§Œλ“€μ§€ μ•Šκ³ , Non-Block으둜 두어 각 ν”„λ‘œμ„ΈμŠ€μ˜ νλ¦„λŒ€λ‘œ μ‹€ν–‰ν•˜λ‹€κ°€ ν•„μš”ν•  λ•Œλ§Œ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό μˆ˜κ±°ν•˜μ—¬ λ©€ν‹° ν”„λ‘œμ„Έμ‹±μ˜ μž₯점을 μ·¨ν•˜λ„λ‘ λ§Œλ“€κ³  싢은 κ²½μš°λ„ μžˆμ„ 것이닀. 이 λ•ŒλŠ” λ°˜λ“œμ‹œ waitpid의 WNOHANG을 μ΄μš©ν•΄μ•Ό ν•œλ‹€.
Non-Block을 μ΄μš©ν•˜λŠ” μ˜ˆμ‹œλ₯Ό μ•„λž˜μ—μ„œ 닀뀄볼 것인데, λ‹€μŒκ³Ό 같은 λ‚΄μš©μ΄λ‹€. λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μƒνƒœ λ³€ν™”λ₯Ό SIGCHLDλΌλŠ” μ‹œκ·Έλ„μ„ Kernelλ‘œλΆ€ν„° λ°›κ²Œ 되면, λ³„λ„μ˜ ν•Έλ“€λŸ¬λ₯Ό ν˜ΈμΆœν•˜μ—¬ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ statusλ₯Ό μ·¨λ“ν•œ λ’€ 상황에 λ§žλŠ” μ μ ˆν•œ 행동을 μˆ˜ν–‰ν•˜λ„λ‘ ν•œλ‹€. 이λ₯Ό 톡해 μ›ν•˜λŠ” 타이밍에 적절히 waitpidλ₯Ό ν˜ΈμΆœν•  수 μžˆμ„ 뿐 μ•„λ‹ˆλΌ, μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œλ₯Ό 기닀리지 μ•Šκ³ λ„ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μƒνƒœ 변화에 λŒ€ν•΄μ„œ statusλ₯Ό μ¦‰μ‹œ μ–»μŒμœΌλ‘œμ¨ Non-Block μƒνƒœλ‘œ 흐름을 μ΄μ–΄κ°ˆ 수 있게 λœλ‹€. 만일 이와 같은 μƒν™©μ—μ„œ WNOHANG을 μ‚¬μš©ν•˜μ§€ μ•ŠμœΌλ©΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œλ˜μ–΄μ•Όλ§Œ statusλ₯Ό μ•Œ 수 있기 λ•Œλ¬Έμ—, μžμ‹ ν”„λ‘œμ„ΈμŠ€ μƒνƒœ λ³€ν™”λ₯Ό κ°μ§€ν•˜κ³  이에 따라 μ²˜λ¦¬ν•΄μ•Όν•  행동을 λ°”λ‘œ λ°”λ‘œ μ²˜λ¦¬ν•  수 μ—†κ²Œ λœλ‹€.
wait ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜κΈ° μ΄μ „μ—λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ 각자 μžμ‹ μ˜ Contextλ₯Ό μ΄μ–΄κ°„λ‹€λŠ” 점을 μ΄μš©ν•˜μ—¬ wait ν•¨μˆ˜λ₯Ό μ΅œλŒ€ν•œ λ―Έλ€„μ„œ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€ μ’…λ£Œ 직전 λ“±μ—μ„œ ν˜ΈμΆœν•˜λ„λ‘ λ§Œλ“€λ©΄ WNOHANG을 μ‚¬μš©ν•œ 것과 λ™μΌν•˜κ²Œ Non-Block μƒνƒœλ‘œ μ²˜λ¦¬λ˜λ„λ‘ λ§Œλ“€ μˆ˜λŠ” μžˆμœΌλ‚˜, 이 λ™μž‘μ€ μ—¬μ „νžˆ Non-Block을 ν•„μš”λ‘œ ν•˜λŠ” 상황에 λŒ€ν•΄μ„œ μœ μ—°ν•œ 흐름을 λ§Œλ“€μ–΄λ‚Ό 수 μ—†λ‹€.

4. μ˜ˆμ‹œ

#include <stdio.h> #include <sys/wait.h> #include <unistd.h> int main(void) { pid_t pid; pid_t ret; int status; pid = fork(); if (pid == -1) return (1); else if (!pid) { usleep(50000); printf("Child1: I am the 1st Child\n"); return (2); } else { pid = fork(); if (pid == -1) return (1); else if (!pid) { usleep(49000); printf("Child2: I am the 2nd Child\n"); return (3); } else { printf("Parent: I have 2 Children\n"); ret = wait(&status); printf("Parent: Successfully got status from %d Child\n", ret); printf("Parent: Exit Code is %d, Signal is %d\n", WEXITSTATUS(status), WTERMSIG(status)); ret = wait(&status); printf("Parent: Successfully got status from %d Child\n", ret); printf("Parent: Exit Code is %d, Signal is %d\n", WEXITSTATUS(status), WTERMSIG(status)); } } return (0); }
C
wait ν•¨μˆ˜λŠ” 2개 μ΄μƒμ˜ fork된 ν”„λ‘œμ„ΈμŠ€μ— λŒ€ν•΄μ„œ μˆœμ„œλ₯Ό 보μž₯ν•˜μ§€ μ•ŠλŠ”λ‹€λŠ” 것을 보이기 μœ„ν•΄ usleep ν•¨μˆ˜λ₯Ό 적절히 μ΄μš©ν•΄λ³΄μ•˜λ‹€. 반볡적으둜 μ—¬λŸ¬ μ°¨λ‘€ 싀행해보면, μ–΄λ–¨ λ•ŒλŠ” 첫 번째 μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό λ¨Όμ € μˆ˜κ±°ν•˜κΈ°λ„ ν•˜κ³ , μ–΄λ–¨ λ•ŒλŠ” 두 번째 μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό λ¨Όμ € μˆ˜κ±°ν•˜κΈ°λ„ ν•œλ‹€. wait ν•¨μˆ˜λŠ” fork의 μˆœμ„œμ™€ 관계 없이 λ¨Όμ € 마친 μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό μˆ˜κ±°ν•˜κΈ° λ•Œλ¬Έμ— μ—¬λŸ¬ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ“€μ„ λ‘κ³ μ„œ μˆœμ„œμ— λ―Όκ°ν•œ μž‘μ—…μ„ μˆ˜ν–‰ν•΄μ•Ό ν•˜λŠ” 상황이라면, μ΄λŸ¬ν•œ μž‘μ—…μ€ ν”„λ‘œκ·Έλž¨μ΄ μ‹€ν–‰λ˜κ³  μžˆλŠ” λ¨Έμ‹ μ˜ μ„±λŠ₯에 λ”°λΌμ„œλ„ 차이λ₯Ό 보일 수 있기 λ•Œλ¬Έμ— μœ„μ²˜λŸΌ wait ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜λŠ” 것은 쒋은 방법이 μ•„λ‹ˆλ‹€. wait ν•¨μˆ˜μ˜ ν•œκ³„λ₯Ό κ·Ήλ³΅ν•˜κΈ° μœ„ν•΄μ„  μ•„λž˜ μ½”λ“œμ™€ 같이 waitpid ν•¨μˆ˜μ— μ§μ ‘μ μœΌλ‘œ pidλ₯Ό λͺ…μ‹œν•¨μœΌλ‘œμ¨ μˆœμ„œλ₯Ό 보μž₯ν•˜λ„λ‘ λ§Œλ“€ 수 μžˆλ‹€.
μ‚¬μš© 쀑인 머신에 λ”°λΌμ„œ μœ„ μ½”λ“œλ₯Ό μ΄μš©ν–ˆμ„ λ•Œ κ³ μ •λœ κ²°κ³Όκ°€ λ‚˜μ˜¬ 수 μžˆλ‹€. usleep ꡬ문 μ΄ν›„μ˜ μ½”λ“œλ₯Ό μ²˜λ¦¬ν•˜λŠ” 속도가 λ¨Έμ‹ λ§ˆλ‹€ λ‹€λ₯΄κΈ° λ•Œλ¬Έμ΄λ―€λ‘œ, 이런 κ²½μš°μ—λŠ” usleep의 값을 적절히 μˆ˜μ •ν•˜λ©΄ λœλ‹€.
#include <stdio.h> #include <sys/wait.h> #include <unistd.h> int main(void) { pid_t pid1; pid_t pid2; pid_t ret; int status; pid1 = fork(); if (pid1 == -1) return (1); else if (!pid1) { usleep(50000); printf("Child1: I am the 1st Child\n"); return (2); } else { pid2 = fork(); if (pid2 == -1) return (1); else if (!pid2) { usleep(49000); printf("Child2: I am the 2nd Child\n"); return (3); } else { printf("Parent: I have 2 Children\n"); ret = waitpid(pid1, &status, 0); printf("Parent: Successfully got status from %d Child\n", ret); printf("Parent: Exit Code is %d, Signal is %d\n", WEXITSTATUS(status), WTERMSIG(status)); ret = waitpid(pid2, &status, 0); printf("Parent: Successfully got status from %d Child\n", ret); printf("Parent: Exit Code is %d, Signal is %d\n", WEXITSTATUS(status), WTERMSIG(status)); } } return (0); }
C
#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <sys/wait.h> #include <unistd.h> void handler(int sig) { pid_t ret; int status; if (sig != SIGCHLD) exit(1); ret = waitpid(-1, &status, WNOHANG); printf("Parent: Successfully got status from %d Child\n", ret); printf("Parent: Exit Code is %d, Signal is %d\n", WEXITSTATUS(status), WTERMSIG(status)); exit(0); } int main(void) { pid_t pid; pid = fork(); if (pid == -1) return (1); else if (!pid) { printf("Child: I am going to take a sleep for 5 seconds\n"); usleep(5000000); return (0); } else { printf("Parent: I have a Child which pid is %d\n", pid); signal(SIGCHLD, handler); while(1) ; } return (0); }
C
SIGCHLDλΌλŠ” μ‹œκ·Έλ„μ€ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μƒνƒœμ— λ³€ν™”κ°€ μžˆμ„ λ•Œ Kenelλ‘œλΆ€ν„° λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—κ²Œ μ „λ‹¬λœλ‹€. 일반적으둜 Kernelλ‘œλΆ€ν„° SIGCHLDλ₯Ό 받은 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ κΈ°λ³Έ 처리 λ™μž‘μ€ SIG_IGN이닀. 이에 λŒ€ν•΄μ„œ κΈ°λ³Έ 처리 λ™μž‘μ„ SIG_IGN이 μ•„λ‹ˆλΌ μ‚¬μš©μžκ°€ μ •μ˜ν•œ ν•Έλ“€λŸ¬λ‘œ λ™μž‘ν•˜λ„λ‘ signal ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜μ˜€λ‹€. ν•Έλ“€λŸ¬ λ‚΄λΆ€μ—λŠ” waitpidλ₯Ό ν˜ΈμΆœν•˜μ—¬ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ statusλ₯Ό 얻을 수 μžˆλ„λ‘ ν–ˆκ³ , WNOHANG을 μ΄μš©ν•˜μ—¬ Block μƒνƒœλ₯Ό λ°©μ§€ν•¨μœΌλ‘œμ¨ 즉각적인 λ°˜ν™˜μ„ μœ λ„ν•˜λ„λ‘ ν–ˆλ‹€. μœ„μ™€ 같이 처리λ₯Ό ν•˜κ²Œ 되면, μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μƒνƒœ λ³€ν™”κ°€ λ°œμƒν–ˆμ„ λ•Œ νŠΉμ • 행동을 μˆ˜ν–‰ν•  수 μžˆλ„λ‘ λ§Œλ“€ 수 μžˆλ‹€. 만일 WNOHANG을 μ‚¬μš©ν•˜μ§€ μ•ŠμœΌλ©΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œν•˜κΈ° μ „κΉŒμ§€ Block μƒνƒœμ— λ†“μ΄κ²Œ 될 뿐만 μ•„λ‹ˆλΌ, μ·¨λ“ν•œ status μ—­μ‹œ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μƒνƒœ λ³€ν™”λ₯Ό λ‹΄κ³  μžˆμ§€ μ•Šκ³  μ’…λ£Œ μƒνƒœμ— λŒ€ν•΄μ„œλ§Œ λ‹΄κ³  μžˆλŠ” 상황이 λ²Œμ–΄μ§„λ‹€. λ”°λΌμ„œ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μƒνƒœ 변화에 λ”°λ₯Έ νŠΉμ • 행동을 μˆ˜ν–‰ν•˜λ„λ‘ λ§Œλ“œλŠ”λ° 어렀움이 생긴닀. λ¬Όλ‘  μœ„μ˜ μ˜ˆμ‹œμ²˜λŸΌ Non-Block으둜 흐름을 μ œμ–΄ν•˜λ”λΌλ„ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ κ³ μ•„ ν”„λ‘œμ„ΈμŠ€λ‘œ 남지 μ•Šλ„λ‘ μ£Όμ˜ν•΄μ•Ό ν•œλ‹€.
μ‹œκ·Έλ„μ„ λ°›μ•˜μ„ λ•Œ κΈ°λ³Έ 처리 λ™μž‘μ€ SIG_IGN, SIG_DFL, ν•Έλ“€λŸ¬λ‘œ λ‚˜λ‰˜λ©°, SIG_DFL은 κΈ°λ³Έ μ •μ˜λœ 행동을 ν•˜λΌλŠ” κ²ƒμœΌλ‘œ μ’…λ£Œ, λ¬΄μ‹œ, 덀프, 쀑단, 재개 등이 μžˆλ‹€. μ‹œκ·Έλ„μ— λŒ€ν•œ κΈ°λ³Έ 처리 λ™μž‘μ€ signal, sigset, sigaction을 톡해 μž¬μ •μ˜ ν•  수 있으며, sigaction을 μ΄μš©ν–ˆμ„ λ•ŒλŠ” ν•˜λ‚˜μ˜ μ‹œκ·Έλ„μ„ μ²˜λ¦¬ν•˜λŠ” λ™μ•ˆ λ‹€λ₯Έ μ‹œκ·Έλ„μ΄ μ˜€μ§€ μ•Šλ„λ‘ νŠΉμ • μ‹œκ·Έλ„λ“€μ„ 막을 μˆ˜λ„ μžˆλ‹€. 이λ₯Ό 톡해 쑰금 더 μ •κ΅ν•œ ν”„λ‘œκ·Έλž¨μ„ λ§Œλ“€ 수 μžˆλ‹€

6) dup

1. μ˜μ‘΄μ„±

#include <unistd.h>
C

2. ν•¨μˆ˜ μ›ν˜•

int dup(int fd);
C

3. ν•¨μˆ˜ μ„€λͺ…

dup κ³„μ—΄μ˜ ν•¨μˆ˜λŠ” 주둜 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό ν™œμš©ν•˜λŠ” ν•¨μˆ˜μ΄λ‹€. λ”°λΌμ„œ 파일 λ””μŠ€ν¬λ¦½ν„°μ— λŒ€ν•œ 이해가 λ¨Όμ € ν•„μš”ν•˜λ‹€. 이에 λŒ€ν•΄μ„  get_next_lineμ—μ„œ λ¦¬λ·°ν•œ λ°”κ°€ 있기 λ•Œλ¬Έμ— μ—¬κΈ°μ„œ μ€‘λ³΅μœΌλ‘œ 닀루진 μ•Šμ„ 것이닀. dup ν˜Ήμ€ dup2에 λŒ€ν•œ μ„€λͺ…을 읽기 전에 λ°˜λ“œμ‹œ μ•„λž˜ 링크의 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό ν™•μΈν•˜λŠ” 것을 κΆŒν•œλ‹€.
dup ν•¨μˆ˜λŠ” fdλΌλŠ” 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό 인자둜 λ°›λŠ”λ‹€. dup ν•¨μˆ˜μ˜ λͺ©μ μ΄ 파일 λ””μŠ€ν¬λ¦½ν„°μ˜ λ³΅μ œμ΄λ―€λ‘œ λ°˜ν™˜ 값은 볡제된 파일 λ””μŠ€ν¬λ¦½ν„°μ˜ κ°’μ΄λœλ‹€. 만일 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό λ³΅μ œν•˜λŠ” κ³Όμ •μ—μ„œ λ¬Έμ œκ°€ λ°œμƒν•˜λ©΄, dup ν•¨μˆ˜λŠ” -1μ΄λΌλŠ” 값을 λ°˜ν™˜ν•œλ‹€.
get_next_lineμ—μ„œ 파일 λ””μŠ€ν¬λ¦½ν„°μ— λŒ€ν•œ λ‚΄μš©μ„ μ½μ—ˆλ‹€λ©΄, νŒŒμΌμ„ μ—΄λ©΄μ„œ 파일 λ””μŠ€ν¬λ¦½ν„°κ°€ μ–΄λ–»κ²Œ ν• λ‹Ήν•˜λŠ”μ§€ μ΄ν•΄ν–ˆμ„ 것이닀. dup ν•¨μˆ˜μ˜ λ°˜ν™˜ 값은 νŒŒμΌμ„ μ—΄ λ•Œμ˜ 상황과 λ™μΌν•œ 기법을 μ΄μš©ν•˜μ—¬ 얻어진닀. λ”°λΌμ„œ dup ν•¨μˆ˜μ˜ κ²½μš°μ—λ„ inode에 λŒ€ν•œ 정보λ₯Ό File Table의 entry에 κΈ°λ‘ν•˜λ©΄μ„œ 이에 λŒ€ν•œ μ£Όμ†Œλ₯Ό FD Tableμ—μ„œ μ°Έμ‘°ν•  수 μžˆλ„λ‘, 순차적으둜 FD Table을 νƒμƒ‰ν•˜λŠ” 과정을 κ±°μΉœλ‹€. FD Table의 곡간을 0번 indexλΆ€ν„° ν™•μΈν•˜μ—¬ File Table의 entry μ£Όμ†Œκ°€ 담겨 μžˆμ§€ μ•Šμ€ indexλ₯Ό λ°˜ν™˜ν•˜λ―€λ‘œ, μ‚¬μš©ν•  수 μžˆλŠ” 파일 λ””μŠ€ν¬λ¦½ν„° μ€‘μ—μ„œ κ°€μž₯ μž‘μ€ 값을 λ°˜ν™˜ν•˜κ²Œ λœλ‹€. 이 λ•Œ File Tableκ³Ό VFS inode CacheλŠ” μ–΄λ–»κ²Œ λ™μž‘ν•˜λŠ”μ§€ μ•Œμ•„λ³΄μž.
일반적으둜 λ™μΌν•œ νŒŒμΌμ„ μ—¬λŸ¬ μ°¨λ‘€ μ—¬λŠ” ν–‰μœ„λŠ” 파일이 열릴 λ•Œλ§ˆλ‹€ λ³„λ„μ˜ File Table의 entry둜 μœ μ§€λœλ‹€κ³  ν–ˆλ‹€. (이 λ•Œ 각 File Table의 entryκ°€ μ°Έμ‘°ν•˜λŠ” inodeλŠ” λ™μΌν•˜λ©°, 이λ₯Ό μ°Έμ‘°ν•˜λŠ” File Table의 entry μˆ˜μ— 따라 inode의 i_count 값이 κ²°μ •λœλ‹€.) ν•˜μ§€λ§Œ dup ν•¨μˆ˜μ˜ 경우 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό μ–»λŠ”λ‹€λŠ” 점은 νŒŒμΌμ„ μ—¬λŠ” ν–‰μœ„μ™€ λ™μΌν•˜μ§€λ§Œ, λ‚΄λΆ€μ μœΌλ‘œλŠ” λ³„λ„μ˜ File Table의 entryλ₯Ό λ‘λŠ” 것이 μ•„λ‹ˆλΌ λ™μΌν•œ File Table의 entryλ₯Ό μ°Έμ‘°ν•˜λ„λ‘ λ˜μ–΄ μžˆλ‹€. λ”°λΌμ„œ dup ν•¨μˆ˜λ₯Ό μˆ˜ν–‰ν•˜κ²Œ 되면 ν•΄λ‹Ή File Table의 entryμ—μ„œ f_count 값이 μ¦κ°€ν•˜λŠ” λ°©μ‹μœΌλ‘œ λ™μž‘ν•˜κ²Œ λœλ‹€.
dup ν•¨μˆ˜λ₯Ό μˆ˜ν–‰ν•˜κ²Œ 되면 인자둜 넣은 파일 λ””μŠ€ν¬λ¦½ν„°μ™€ λ°˜ν™˜ κ°’μœΌλ‘œ 받은 파일 λ””μŠ€ν¬λ¦½ν„°κ°€ λ™μΌν•œ νŒŒμΌμ„ μ°Έμ‘°ν•˜κ³  μžˆμ§€λ§Œ, close ν•¨μˆ˜λŠ” 각각 ν˜ΈμΆœν•΄μ€˜μ•Ό ν•œλ‹€λŠ” 점에 μœ μ˜ν•΄μ•Ό ν•œλ‹€. f_count의 값이 0이 λ˜μ–΄μ•Ό File Table의 entryκ°€ μ‚­μ œλ  수 있고, 이에 따라 i_count 값도 κ°μ†Œν•˜μ—¬ μ΅œμ’…μ μœΌλ‘œλŠ” μ˜¬λ°”λ₯΄κ²Œ VFS inode Cacheμ—μ„œλ„ μ‚­μ œλ  수 μžˆλ‹€. 각 파일 λ””μŠ€ν¬λ¦½ν„°μ— λŒ€ν•΄μ„œ closeλ₯Ό ν˜ΈμΆœν•  λ•Œλ§ˆλ‹€ File Table의 entryκ°€ κ°–κ³  μžˆλŠ” f_count 값이 κ°μ†Œν•˜κ²Œ λœλ‹€.
λ¬Όλ‘  close ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ§€ μ•Šλ”λΌλ„ ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œλ˜λ©΄ λͺ¨λ“  파일 λ””μŠ€ν¬λ¦½ν„°λŠ” μžλ™μœΌλ‘œ λ‹«νžˆκ²Œ λœλ‹€. λ”°λΌμ„œ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œ μ‹œμ—λŠ” μžλ™μœΌλ‘œ f_countκ°€ κ°μ†Œν•œλ‹€κ³  λ³Ό 수 μžˆλ‹€. 이에 따라 f_countκ°€ 0이 λœλ‹€λ©΄ μ„±κ³΅μ μœΌλ‘œ File Table의 entryλŠ” ν•΄μ œλ  것이닀. ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œ μ‹œμ— 파일 λ””μŠ€ν¬λ¦½ν„°κ°€ μžλ™μœΌλ‘œ λ‹«νžˆλŠ” ν–‰μœ„μ— λŒ€ν•΄μ„œλŠ” exit ν•¨μˆ˜μ˜ λ™μž‘μœΌλ‘œ μ •μ˜λ˜μ–΄ 있으며, μ΄λŠ” POSIX에 따라 ν‘œμ€€μœΌλ‘œ μ •μ˜λœ 사항이닀. ν•˜μ§€λ§Œ μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 파일 λ””μŠ€ν¬λ¦½ν„°μ— λŒ€ν•œ μ μ ˆν•œ close ν•¨μˆ˜μ˜ 호좜이 ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•  λ•Œ 더 쒋은 μŠ΅κ΄€μ„ λ§Œλ“€κ³ , 예기치 λͺ»ν•œ λ™μž‘μ— λŒ€ν•΄μ„œ 방지할 수 μžˆλ‹€.

4. μ˜ˆμ‹œ

#include <fcntl.h> #include <stdio.h> #include <string.h> #include <unistd.h> int main(void) { int fd; int tmp; int ret; char buffer[4096]; tmp = open("test.txt", O_RDONLY); fd = dup(tmp); close(tmp); if (fd == -1) return (1); ret = read(fd, buffer, 4096); close(fd); if (ret == -1) return (1); buffer[ret] = '\0'; write(STDOUT_FILENO, buffer, strlen(buffer)); return (0); }
C

7) dup2

1. μ˜μ‘΄μ„±

#include <unistd.h>
C

2. ν•¨μˆ˜ μ›ν˜•

int dup2(int fd, int fd2);
C

3. ν•¨μˆ˜ μ„€λͺ…

dup2의 역할은 dup ν•¨μˆ˜μ™€ λ™μž‘ 방식이 λ™μΌν•˜λ‹€. λ”°λΌμ„œ 파일 λ””μŠ€ν¬λ¦½ν„°μ— λŒ€ν•œ λ‚΄μš©, 파일 λ””μŠ€ν¬λ¦½ν„°μ˜ 처리 흐름, 파일 λ””μŠ€ν¬λ¦½ν„°μ˜ 볡제 과정에 λŒ€ν•΄μ„œλŠ” dup ν•¨μˆ˜λ₯Ό ν™•μΈν•˜λŠ” 것을 κΆŒν•œλ‹€.
dup2 ν•¨μˆ˜λŠ” dup ν•¨μˆ˜μ™€ λΉ„κ΅ν–ˆμ„ λ•Œ, μ‚¬μš© 방법에 차이가 μžˆλ‹€. 인자둜 넣은 fdλΌλŠ” 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό λ³΅μ œν•˜κ³  ν˜„μž¬ μ‚¬μš©ν•˜κ³  μžˆμ§€ μ•Šμ€ 파일 λ””μŠ€ν¬λ¦½ν„° 쀑 κ°€μž₯ μž‘μ€ 값을 λ°˜ν™˜ν•˜λŠ” 것이 dupμ΄μ—ˆλ‹€λ©΄, dup2의 κ²½μš°μ—λŠ” λ°˜ν™˜ 값이 μ‚¬μš©μžκ°€ μ›ν•˜λŠ” fd2λΌλŠ” 값이 λ‚˜μ˜¬ 수 μžˆλ„λ‘ fdλΌλŠ” 인자λ₯Ό μ‚¬μš©ν•˜μ—¬ 볡제λ₯Ό μˆ˜ν–‰ν•œλ‹€. 즉, 볡제 κ³Όμ •μ—μ„œ λ¬Έμ œκ°€ 생기지 μ•ŠλŠ”λ‹€λ©΄ dup2의 λ°˜ν™˜ 값은 fd2κ°€ λœλ‹€.
볡제 κ³Όμ •μ—μ„œ λ¬Έμ œκ°€ 생긴닀면 dup ν•¨μˆ˜μ™€ λ§ˆμ°¬κ°€μ§€λ‘œ, dup2 ν•¨μˆ˜λ„ -1을 λ°˜ν™˜ν•œλ‹€.
만일 볡제 κ³Όμ •μ—μ„œ fd2κ°€ 기쑴에 이미 μ—΄λ €μ„œ μ‚¬μš©λ˜κ³  μžˆλŠ” 값이라면 μ–΄λ–»κ²Œ 될까? μ΄λŠ” 볡제 κ³Όμ •μ—μ„œμ˜ 였λ₯˜λ‘œ μ²˜λ¦¬ν•˜μ§€ μ•Šκ³  기쑴의 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό closeν•˜μ—¬ File Table의 entry와 inodeλ₯Ό μ²˜λ¦¬ν•˜μ—¬, File Table의 entryλ₯Ό μ°Έμ‘°ν•˜κ³  μžˆμ§€ μ•Šμ€ μƒνƒœμ˜ 파일 λ””μŠ€ν¬λ¦½ν„°λ‘œ λ§Œλ“€μ–΄μ„œ 볡제λ₯Ό μˆ˜ν–‰ν•  수 μžˆλ„λ‘ λ§Œλ“ λ‹€.
dup ν•¨μˆ˜κ°€ 이미 μ‘΄μž¬ν•˜λŠ”λ°λ„ λΆˆκ΅¬ν•˜κ³  dup2 ν•¨μˆ˜λ₯Ό λ§Œλ“€μ–΄λ‘” μ΄μœ λŠ” μœ μ—°ν•œ 파일 λ””μŠ€ν¬λ¦½ν„°μ˜ μ΄μš©μ„ μœ„ν•΄μ„œμ΄λ‹€. dup2 ν•¨μˆ˜λŠ” 주둜 pipe ν•¨μˆ˜μ™€ ν•¨κ»˜ 많이 μ“°μ΄λŠ”λ°, pipe ν•¨μˆ˜μ—μ„œ μ‚¬μš©λ˜λŠ” 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό ν‘œμ€€ μž…λ ₯κ³Ό ν‘œμ€€ 좜λ ₯을 μ°Έμ‘°ν•˜λŠ” indexκ°€ λ³΅μ œν•  수 μžˆλ„λ‘ 주둜 μ‚¬μš©λœλ‹€. 이λ₯Ό 톡해 pipe둜 μ—°κ²°λœ ν”„λ‘œμ„ΈμŠ€ 간에 λͺ…λ Ήμ–΄λ₯Ό μ²˜λ¦¬ν•  λ•Œ ν‘œμ€€ μž…λ ₯κ³Ό ν‘œμ€€ 좜λ ₯을 μ΄μš©ν•˜κΈ° μœ„ν•΄ 0번 index와 1번 indexλ₯Ό μ΄μš©ν•œλ‹€λ©΄, μ‹€μ œλ‘œλŠ” ν‘œμ€€ μž…λ ₯κ³Ό ν‘œμ€€ 좜λ ₯을 μ΄μš©ν•˜λŠ” 것이 μ•„λ‹ˆλΌ λ³΅μ œν•œ 파일 λ””μŠ€ν¬λ¦½ν„°μ˜ νŒŒμΌμ„ μ΄μš©ν•˜κ²Œ λœλ‹€. pipe에 λŒ€ν•΄μ„  μ°¨ν›„μ˜ ν•­λͺ©μ—μ„œ λ‹€λ£¨λ―€λ‘œ 이와 λΉ„μŠ·ν•œ μ˜ˆμ‹œλ₯Ό μ•„λž˜μ—μ„œ 닀뀄볼 것이닀.
만일 dup2κ°€ μ‘΄μž¬ν•˜μ§€ μ•Šμ•„μ„œ dup으둜만 이λ₯Ό μ²˜λ¦¬ν•΄μ•Ό ν•œλ‹€λ©΄ ꡉμž₯히 κΉŒλ‹€λ‘œμš΄ 상황이 λ°œμƒν•  수 μžˆλ‹€. μ‚¬μš©μžκ°€ μ›ν•˜λŠ” κ°’ μ΄μ „κΉŒμ§€λŠ” 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό 열어둬야 ν•˜κ³ , μ‚¬μš©μžκ°€ μ›ν•˜λŠ” 값이 이미 μ μœ λ˜μ—ˆλ‹€λ©΄ closeλ₯Ό ν˜ΈμΆœν•΄μ€˜μ•Ό ν•œλ‹€. λ§ˆμΉ¨λ‚΄ dup을 ν˜ΈμΆœν•˜κ²Œ λ˜μ–΄ μ›ν•˜λŠ” 값을 ν• λ‹Ή λ°›μ•˜λ‹€λ©΄, 이λ₯Ό μœ„ν•΄ 이전에 μ—΄μ–΄λ‘” μ‚¬μš©λ˜μ§€ μ•ŠλŠ” 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό close ν•˜λŠ” 과정을 거쳐야 ν•œλ‹€. λ¬Όλ‘  이와 같은 λ³΅μž‘ν•œ 과정이 μ‹«μ–΄μ„œ dup2와 λ™μΌν•œ λ™μž‘μ„ λ§Œλ“€μ–΄ 내지 μ•ŠλŠ”λ‹€κ³  ν•œλ‹€λ©΄, λ‹¨μˆœνžˆ dup ν•¨μˆ˜λ§Œμ„ μ΄μš©ν•˜κ³  λ°˜ν™˜ 받은 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό 문제 없이 μ‚¬μš©ν•  수 μžˆλ„λ‘ dup ν•¨μˆ˜μ˜ ν˜ΈμΆœμžμ—μ„œ 이λ₯Ό 적절히 μ²˜λ¦¬ν•΄μ€˜μ•Ό ν•˜λŠ” 상황이 λ°œμƒν•œλ‹€.
μ˜ˆμ‹œμ—μ„œ μ‚¬μš©λœ μ½”λ“œμ˜ 상황은 μœ„μ˜ κ·Έλ¦Όκ³Ό 같은 상황이닀. 이 λ•Œ dup2λ₯Ό ν˜ΈμΆœν•˜κ²Œ 되면 κΈ°μ‘΄ 0번 index의 파일 λ””μŠ€ν¬λ¦½ν„°κ°€ λ‹«νžˆκ³ , 3번 index에 λŒ€ν•œ File Table의 entryλ₯Ό μ°Έμ‘°ν•˜λ„λ‘ λ³΅μ œκ°€ 이뀄진닀. 볡제 후에 κΈ°μ‘΄ 0번 indexκ°€ μ°Έμ‘°ν•˜κ³  μžˆλŠ” File Table의 entryκ°€ ν˜„μž¬ ν”„λ‘œμ„ΈμŠ€μ— μ˜ν•΄μ„œ μ „ν˜€ 참쑰되고 μžˆμ§€ μ•ŠμŒμ—λ„ File Tableμ—μ„œ ν•΄μ œλ˜μ§€ μ•Šμ€ μ΄μœ λŠ” λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€λ“€λ„ ν‘œμ€€ μž…λ ₯을 μœ„ν•΄μ„œ ν•΄λ‹Ή entryλ₯Ό μ°Έμ‘°ν•˜κ³  있기 λ•Œλ¬Έμ΄λ‹€. (즉, ν‘œμ€€ μž…λ ₯을 μœ„ν•œ entry의 f_countλŠ” 비둝 ν˜„μž¬ ν”„λ‘œμ„ΈμŠ€μ˜ 0번 indexκ°€ μ°Έμ‘°λ₯Ό λŠλ”λΌλ„ 0이 λ˜λŠ” κ²½μš°λŠ” μ—†λ‹€κ³  보면 λœλ‹€.)

4. μ˜ˆμ‹œ

#include <stdio.h> #include <string.h> #include <fcntl.h> #include <unistd.h> int main(void) { int fd; int tmp; int ret; char buffer[4096]; tmp = open("test.txt", O_RDONLY); fd = dup2(tmp, STDIN_FILENO); close(tmp); if (fd == -1) return (1); ret = read(STDIN_FILENO, buffer, 4096); if (ret == -1) return (1); buffer[ret] = '\0'; write(STDOUT_FILENO, buffer, strlen(buffer)); return (0); }
C

8) pipe

1. μ˜μ‘΄μ„±

#include <unistd.h>
C

2. ν•¨μˆ˜ μ›ν˜•

int pipe(int fd[2]);
C

3. ν•¨μˆ˜ μ„€λͺ…

ν”νžˆ ν”„λ‘œμ„ΈμŠ€ κ°„μ˜ 톡신을 IPC (Inter Process Communication)이라 λΆ€λ₯Έλ‹€. IPCλ₯Ό μˆ˜ν–‰ν•˜κΈ° μœ„ν•΄μ„  데이터λ₯Ό μ£Όκ³  λ°›κΈ° μœ„ν•œ νŠΉμ • 곡간이 μš”κ΅¬λœλ‹€. ν•˜μ§€λ§Œ ν”„λ‘œμ„ΈμŠ€λ“€μ€ λ©”λͺ¨λ¦¬ 상에 각각 λ…λ¦½λœ 곡간을 ν• λ‹Ήλ°›μ•„ μœ„μΉ˜ν•˜κ³ , 이듀은 μ„œλ‘œ 곡유될 수 μ—†κΈ° λ•Œλ¬Έμ— νŠΉλ³„ν•œ 방식 μ—†μ΄λŠ” IPC μˆ˜ν–‰μ— 어렀움이 μžˆλ‹€.
IPCλ₯Ό μˆ˜ν–‰ν•˜κΈ° μœ„ν•œ λ°©μ‹μœΌλ‘œλŠ” 파일, 메세지 큐, 곡유 λ©”λͺ¨λ¦¬ μ†ŒμΌ“ 등이 있으며, fork, wait, waitpidμ—μ„œ μ†Œκ°œλœ μ‹œκ·Έλ„λ„ IPC 방식 쀑 ν•˜λ‚˜μ΄λ‹€. 이와 같은 IPC 방식은 크게 곡유 λ©”λͺ¨λ¦¬ 기법과 메세지 κ΅ν™˜ κΈ°λ²•μœΌλ‘œ λ‚˜λ‰˜λŠ”λ°, 메세지 κ΅ν™˜ 기법 μ€‘μ—μ„œλ„ forkλ₯Ό μ΄μš©ν–ˆμ„ λ•Œ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ μ„œλ‘œ ν†΅μ‹ ν•˜λŠ”λ° μ΄μš©λ˜λŠ” IPC 방식이 νŒŒμ΄ν”„μ΄λ‹€.
μ œμ‹œλœ IPC 방식듀이 λͺ¨λ‘ μ–‘λ°©ν–₯ 톡신을 μ§€μ›ν•˜λŠ” 것은 μ•„λ‹ˆλ‹€. λ”°λΌμ„œ μ‚¬μš©ν•˜λ €λŠ” IPC 방식이 μ–‘λ°©ν–₯ 톡신을 μ§€μ›ν•˜λŠ”μ§€ λ¨Όμ € ν™•μΈν•˜κ³ , 그렇지 μ•Šλ‹€λ©΄ μ–‘λ°©ν–₯ 톡신을 μœ„ν•΄ λ³„λ„μ˜ μž‘μ—…μ„ 거쳐야 ν•œλ‹€.
이전 ν•­λͺ©μ˜ μ˜ˆμ‹œμ—μ„œ μž‘μ„±λœ μ½”λ“œλ₯Ό 보면 μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€ 간에 μ‹œκ·Έλ„μ„ μ£Όκ³  λ°›λŠ” 것을 λ³Ό 수 μžˆλŠ”λ°, μ΄λŠ” 보내진 μ‹œκ·Έλ„μ— 따라 각 ν”„λ‘œμ„ΈμŠ€κ°€ μˆ˜ν–‰ν•  λ™μž‘μ„ μ •μ˜ν•˜λŠ” λ“±μœΌλ‘œ μ‚¬μš©λ˜κΈ° λ•Œλ¬Έμ— μƒν˜Έ 간에 데이터λ₯Ό μ£Όκ³  λ°›λŠ”λ°λŠ” 어렀움이 μžˆλ‹€. λ”°λΌμ„œ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ μ„œλ‘œ 데이터λ₯Ό μ£Όκ³  λ°›κΈ° μœ„ν•΄μ„  μ‹œκ·Έλ„λ³΄λ‹€λŠ” νŒŒμ΄ν”„λ₯Ό μ΄μš©ν•΄μ•Ό ν•œλ‹€. 이 λ•Œ, μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€ 사이에 νŒŒμ΄ν”„λ₯Ό 두기 μœ„ν•΄ μ΄μš©λ˜λŠ” ν•¨μˆ˜κ°€ pipe이닀.
νŒŒμ΄ν”„λΌλŠ” IPC 방식은 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό μ΄μš©ν•˜μ—¬ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€ 간에 데이터λ₯Ό μ£Όκ³  받을 수 μžˆλ„λ‘ ν•΄μ€€λ‹€. νŒŒμ΄ν”„λŠ” 단방ν–₯ 톡신이기 λ•Œλ¬Έμ—, μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€ κ°„ νŒŒμ΄ν”„λ₯Ό κ°œμ„€ν•˜κ²Œ 되면 ν•œ μͺ½μ—μ„œλŠ” Read μž‘μ—…λ§Œ κ°€λŠ₯ν•˜κ³  λ‹€λ₯Έ μͺ½μ—μ„œλŠ” Write μž‘μ—…λ§Œ κ°€λŠ₯ν•˜λ‹€. 그리고 비둝 νŒŒμ΄ν”„κ°€ 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό μ΄μš©ν•˜κΈ΄ ν•˜λ‚˜, μ΄λŠ” νŒŒμΌμ— λŒ€ν•œ 파일 λ””μŠ€ν¬λ¦½ν„°κ°€ μ•„λ‹Œ μš΄μ˜μ²΄μ œλ‘œλΆ€ν„° ν• λ‹Ή 받은 νŠΉμ • 버퍼에 λŒ€ν•œ 파일 λ””μŠ€ν¬λ¦½ν„°μ΄λ‹€. λ”°λΌμ„œ νŒŒμ΄ν”„μ— Writeν•  수 μžˆλŠ” λ°μ΄ν„°λŠ” ν• λ‹Ή 받은 λ²„νΌμ˜ ν¬κΈ°λ§ŒνΌμ΄λΌλŠ” μ œν•œμ΄ μžˆλ‹€.
λ”°λΌμ„œ 이전에 μ–ΈκΈ‰ν–ˆλ˜ κ²ƒμ²˜λŸΌ νŒŒμ΄ν”„λ₯Ό μ΄μš©ν•˜μ—¬ 두 ν”„λ‘œμ„ΈμŠ€κ°€ μ–‘λ°©ν–₯ 톡신을 μœ„ν•΄μ„ , 각 ν”„λ‘œμ„ΈμŠ€κ°€ λͺ¨λ‘ 읽고 μ“°λŠ” μž‘μ—…μ΄ κ°€λŠ₯ν•΄μ•Ό ν•˜λ―€λ‘œ 2개의 νŒŒμ΄ν”„λ₯Ό 두어야 ν•œλ‹€.
파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό μ΄μš©ν•˜μ—¬ ν”„λ‘œμ„ΈμŠ€ 간에 톡신이 κ°€λŠ₯ν•œ μ΄μœ λŠ” 파일 λ””μŠ€ν¬λ¦½ν„°κ°€ μ°Έμ‘°ν•˜λŠ” 파일 μžμ²΄λŠ” λ””μŠ€ν¬ μƒμ˜ λ³„λ„μ˜ κ³΅κ°„μœΌλ‘œ μœ μ§€λ˜λ©΄μ„œ ν”„λ‘œμ„ΈμŠ€μ˜ λ©”λͺ¨λ¦¬ 곡간을 μΉ¨ν•΄ν•˜μ§€ μ•Šκ³ , 이듀은 μ–΄λ–€ ν”„λ‘œμ„ΈμŠ€μ—μ„œλ„ 접근이 κ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€. 즉, 이둠적으둜 각 ν”„λ‘œμ„ΈμŠ€μ—μ„œ μ‚¬μš©ν•˜κ³  μžˆλŠ” Read μš©λ„μ˜ 파일 λ””μŠ€ν¬λ¦½ν„°μ™€ Write μš©λ„μ˜ 파일 λ””μŠ€ν¬λ¦½ν„°κ°€ λ™μΌν•œ νŒŒμΌμ„ μ°Έμ‘°ν•˜λ„λ‘ λ˜μ–΄ μžˆλ‹€λ©΄, ν•΄λ‹Ή 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό 읽고 μ“°λ©΄μ„œ 톡신이 κ°€λŠ₯ν•˜κ²Œ λ˜λŠ” 것이닀.
이와 같은 μž‘μ—…μ΄ 특히 μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€ 간에 많이 μ΄μš©λ˜λŠ” μ΄μœ λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ 생성이 forkλ₯Ό ν†΅ν•΄μ„œ 이뀄지고, fork ν•¨μˆ˜λŠ” λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ λͺ¨λ“  λ©”λͺ¨λ¦¬ 곡간과 PCκΉŒμ§€ κ·ΈλŒ€λ‘œ λ³΅μ œν•˜μ—¬ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—κ²Œ ν• λ‹Ήν•˜λŠ” νŠΉμ„±μ„ κ°–κ³  있기 λ•Œλ¬Έμ΄λ‹€. λ”°λΌμ„œ fork μˆ˜ν–‰ 이전에 pipe ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ—¬ Read, Write μš©λ„μ˜ 두 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό μ—°κ²°ν•΄λ‘μ—ˆλ‹€λ©΄, fork ν•¨μˆ˜ μˆ˜ν–‰ 이후에 μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—μ„œλ„ 이 μƒνƒœκ°€ κ·ΈλŒ€λ‘œ μœ μ§€λ˜κ³  있게 λœλ‹€. 비둝 파일 λ””μŠ€ν¬λ¦½ν„°κ°€ ν”„λ‘œμ„ΈμŠ€ λ‹¨μœ„λ‘œ κ΄€λ¦¬λ˜κΈ°λŠ” ν•˜μ§€λ§Œ 이미 μ„œλ‘œ λ™μΌν•œ νŒŒμΌμ„ μ°Έμ‘°ν•˜λ„λ‘ μ„€μ •λ˜μ–΄ 있기 λ•Œλ¬Έμ— μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” μ›ν™œν•˜κ²Œ 톡신할 수 μžˆλ‹€.
ν•¨μˆ˜μ˜ ν˜•νƒœλ₯Ό μ‚΄νŽ΄λ³΄λ©΄, pipe ν•¨μˆ˜λŠ” μœ„μ—μ„œ μ„€λͺ…λœ κ²ƒμ²˜λŸΌ 2개의 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό 인자둜 λ°›μ•„ μ΄μš©ν•˜λŠ” 것을 λ³Ό 수 μžˆλ‹€. pipe의 fd에 파일 λ””μŠ€ν¬λ¦½ν„°λ“€μ΄ μ„±κ³΅μ μœΌλ‘œ ν• λ‹Ήλœλ‹€λ©΄ 이 값을 μ΄μš©ν•  수 있게 되고 0을 λ°˜ν™˜ν•œν•œλ‹€. fd에 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό ν• λ‹Ήν•˜λŠ” κ³Όμ •μ—μ„œ λ¬Έμ œκ°€ 생긴닀면 pipeλŠ” μ¦‰μ‹œ -1을 λ°˜ν™˜ν•œλ‹€.
이 λ•Œ 인자둜 μ‚¬μš©λ˜λŠ” fdλŠ” 크기가 2인 int νƒ€μž…μ˜ 배열인데, fd[0]은 Read에 이용되고 fd[1]은 Write에 μ΄μš©λœλ‹€. μœ„μ˜ 그림처럼 aλΌλŠ” ν”„λ‘œμ„ΈμŠ€μ—μ„œ fd[1]을 μ΄μš©ν•˜μ—¬ hiλ₯Ό 썼닀면, bλΌλŠ” ν”„λ‘œμ„ΈμŠ€μ—μ„œλŠ” fd[0]을 μ΄μš©ν•˜μ—¬ hiλ₯Ό 읽을 수 μžˆλ‹€λŠ” 것이닀.
μ•„λž˜ μ˜ˆμ‹œμ—μ„œ pipeμ—μ„œ μ‚¬μš©ν•  파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό ν• λ‹Ή λ°›κ³ , 이λ₯Ό 각각 dup2λ₯Ό μ΄μš©ν•˜μ—¬ ν‘œμ€€ μž…λ ₯을 μœ„ν•œ index와 ν‘œμ€€ 좜λ ₯을 μœ„ν•œ index둜 λ³΅μ œν•¨μœΌλ‘œμ¨ μ£Όκ³  받은 데이터λ₯Ό νŒŒμΌμ— 기둝해볼 것이닀. μ˜ˆμ‹œμ— λŒ€ν•œ 각 ν”„λ‘œμ„ΈμŠ€μ˜ 상황은 μ•„λž˜ κ·Έλ¦Όκ³Ό κ°™λ‹€.
μžμ‹ ν”„λ‘œμ„ΈμŠ€
λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€

4. μ˜ˆμ‹œ

#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/wait.h> #include <unistd.h> #define P_READ 0 #define P_WRITE 1 #define BUFFER_SIZE 4096 void childcommand(void) { int ret; char buffer[BUFFER_SIZE]; ret = read(STDIN_FILENO, buffer, BUFFER_SIZE); buffer[ret] = '\0'; write(STDOUT_FILENO, buffer, strlen(buffer)); } void childproc(int pipe[2]) { int fd; int r_fd; int w_fd; printf("Child: I'm going to close fd for Read\n"); printf("Child: I'm going to connect STDOUT to fd for Write\n"); printf("Child: I'm going to connect STDIN to fd from a file\n"); printf("Child: Eventually I'll read from STDIN (file) and write to STDOUT (pipe)\n"); close(pipe[P_READ]); w_fd = dup2(pipe[P_WRITE], STDOUT_FILENO); close(pipe[P_WRITE]); if (w_fd == -1) exit(1); fd = open("read.txt", O_RDONLY); if (fd == -1) exit(1); r_fd = dup2(fd, STDIN_FILENO); close(fd); if (r_fd == -1) exit(1); childcommand(); } void parentcommand(void) { int ret; char buffer[BUFFER_SIZE]; ret = read(STDIN_FILENO, buffer, BUFFER_SIZE); buffer[ret] = '\0'; write(STDOUT_FILENO, buffer, strlen(buffer)); } void parentproc(int pipe[2], pid_t pid) { int fd; int r_fd; int w_fd; printf("Parent: I'm going to close fd for Write\n"); printf("Parent: I'm going to connect STDIN to fd for Read\n"); printf("Parent: I'm going to connect STDOUT to fd from a file\n"); printf("Parent: Eventually I'll read from STDIN (pipe) and write to STDOUT (file)\n"); close(pipe[P_WRITE]); r_fd = dup2(pipe[P_READ], STDIN_FILENO); close(pipe[P_READ]); if (r_fd == -1) exit(1); fd = open("write.txt", O_WRONLY); if (fd == -1) exit(1); w_fd = dup2(fd, STDOUT_FILENO); close(fd); if (w_fd == -1) exit(1); if (waitpid(pid, NULL, 0) == -1) exit(1); parentcommand(); } int main(void) { int fd[2]; pid_t pid; if (pipe(fd) == -1) return (1); printf("Parent: fd for Read is %d, fd for Write is %d\n", fd[P_READ], fd[P_WRITE]); pid = fork(); if (pid == -1) { close(fd[P_READ]); close(fd[P_WRITE]); return (1); } else if (!pid) childproc(fd); else parentproc(fd, pid); return (0); }
C

9) execve

1. μ˜μ‘΄μ„±

#include <unistd.h>
C

2. ν•¨μˆ˜ μ›ν˜•

int execve(const char *file, char * const *argv, char * const *envp);
C

3. ν•¨μˆ˜ μ„€λͺ…

μœ„ 그림을 보면 μ•Œ 수 μžˆλ“―μ΄ exec κ³„μ—΄μ˜ ν•¨μˆ˜λŠ” λ‹€μ–‘ν•˜μ§€λ§Œ, 첫 번째 인자둜 μ‹€ν–‰ν•  파일의 경둜λ₯Ό λ°›λŠ”λ‹€λŠ” κ²ƒμ—λŠ” 차이가 μ—†λ‹€. exec κ³„μ—΄μ˜ ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜λ©΄ 첫 번째 인자λ₯Ό μ΄μš©ν•˜μ—¬ ν•΄λ‹Ή 경둜의 νŒŒμΌμ„ μ‹€ν–‰ν•˜λ©΄μ„œ μƒˆλ‘œμš΄ ν”„λ‘œμ„ΈμŠ€λ₯Ό λ§Œλ“€μ–΄λ‚΄κ³ , ν˜„μž¬ ν”„λ‘œμ„ΈμŠ€μ—μ„œ μƒˆλ‘­κ²Œ λ§Œλ“€μ–΄μ§„ ν”„λ‘œμ„ΈμŠ€λ‘œ 흐름을 κ΅μ²΄ν•œλ‹€. 이 λ•Œ μƒˆλ‘œμš΄ ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—λŠ” μƒˆλ‘­κ²Œ μ΄ˆκΈ°ν™” 된 μŠ€νƒ, νž™, 데이터 μ˜μ—­μ„ κ°–λŠ”λ‹€. μ΄λŠ” fork와 같이 λ³„λ„μ˜ ν”„λ‘œμ„ΈμŠ€κ°€ κ΅¬λ™λ˜λŠ” 것이 μ•„λ‹Œ, μƒˆλ‘œμš΄ ν”„λ‘œμ„ΈμŠ€κ°€ ν˜„μž¬ ν”„λ‘œμ„ΈμŠ€λ₯Ό κ΅μ²΄ν•˜λŠ” ν–‰μœ„λ‘œ 이뀄지기 λ•Œλ¬Έμ— μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ 관계λ₯Ό κ°–λŠ” ν˜•νƒœκ°€ μ•„λ‹ˆλ‹€. λ”°λΌμ„œ exec κ³„μ—΄μ˜ ν•¨μˆ˜λ‘œ μƒμ„±λœ ν”„λ‘œμ„ΈμŠ€λŠ” 동기적인 νŠΉμ„±μ„ κ°–λŠ”λ‹€.
예λ₯Ό λ“€μ–΄ ν˜„μž¬ ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œ exec 계열 ν•¨μˆ˜κ°€ 첫 번째 인자둜 /bin/lsλ₯Ό μ΄μš©ν–ˆλ‹€λ©΄ exec ν•¨μˆ˜μ— μ˜ν•΄μ„œ /bin/lsκ°€ μ‹€ν–‰λ˜λ©΄μ„œ μƒˆλ‘œμš΄ ν”„λ‘œμ„ΈμŠ€κ°€ 생기고, μ‹€ν–‰ 흐름은 /bin/ls둜 λ„˜μ–΄κ°€κ²Œ λœλ‹€. μ—¬κΈ°μ„œ μƒˆλ‘œμš΄ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±λ˜λŠ” 것이 인자λ₯Ό μ‹€ν–‰μ‹œν‚€λ©΄μ„œ μ΄λ€„μ§€λŠ” κ²ƒμ΄λ―€λ‘œ, exec κ³„μ—΄μ˜ 첫 번째 μΈμžμ— λŒ€ν•΄μ„  μ‹€ν–‰ κΆŒν•œμ΄ μžˆλŠ”μ§€ 확인이 κΌ­ ν•„μš”ν•˜λ‹€. μ΄λŠ” μœ„μ—μ„œ 배운 access ν•¨μˆ˜λ₯Ό ν†΅ν•΄μ„œ μ„ ν–‰ 검사가 κ°€λŠ₯ν•˜λ‹€.
만일 exec κ³„μ—΄μ˜ ν•¨μˆ˜κ°€ 인자둜 받은 νŒŒμΌμ— λŒ€ν•΄μ„œ μ‹€ν–‰ν•˜κ³  이λ₯Ό μ²˜λ¦¬ν•˜λŠ”λ° μ•„λ¬΄λŸ° λ¬Έμ œκ°€ μ—†λ‹€λ©΄, 0을 λ°˜ν™˜ν•œλ‹€. λ°˜λŒ€λ‘œ λ¬Έμ œκ°€ μƒκΈ°κ²Œ 되면, -1을 λ°˜ν™˜ν•œλ‹€. 이λ₯Ό μœ λ…ν•΄λ‘κ³  각 ν•¨μˆ˜λ“€μ— λŒ€ν•΄μ„œ μ•Œμ•„λ³΄μž.
exec κ³„μ—΄μ˜ ν•¨μˆ˜λŠ” κ·Έ μ΄λ¦„λ“€μ—μ„œ μ–΄λ–€ κ·œμΉ™μ„ 찾을 수 μžˆλŠ”λ°, ν•¨μˆ˜ 이름 뒀에 l, v, e, pκ°€ λΆ™λŠ” 것을 λ³Ό 수 μžˆλ‹€. l은 list, vλŠ” vector, eλŠ” environment, pλŠ” pathλ₯Ό μ˜λ―Έν•œλ‹€.
μœ μ‹¬νžˆ μ‚΄νŽ΄λ³΄λ©΄ λŒ€μ²΄μ μœΌλ‘œ execl 계열과 execv κ³„μ—΄λ‘œ λ‚˜λ‰˜λŠ” 것을볼 수 μžˆλŠ”λ°, lκ³Ό vκ°€ 곧 exec ν•¨μˆ˜λ‘œ μ‹€ν–‰ν•  νŒŒμΌμ— μ‚¬μš©λ˜λŠ” 값을 list둜 일일이 주어쀄지 vector둜 ν•œ λ²ˆμ— 주어쀄지λ₯Ό μ˜λ―Έν•˜λ―€λ‘œ, 두 번째 인자 이후 λΆ€ν„° 인자의 ν˜•νƒœκ°€ λ‹¬λΌμ§€λŠ” 것을 λ³Ό 수 μžˆλ‹€. l 계열 ν•¨μˆ˜λ“€μ€ κ°€λ³€ 인자λ₯Ό μ΄μš©ν•˜λŠ” 것을 λ³Ό 수 있고, v 계열 ν•¨μˆ˜μ—μ„œλŠ” κ°€λ³€ 인자λ₯Ό μ΄μš©ν•˜μ§€ μ•ŠλŠ” 것을 λ³Ό 수 μžˆλ‹€.
이 λ•Œ l 계열이든 v 계열이든 두 번째 인자λ₯Ό μ΄μš©ν•  λ•Œ μ£Όμ˜ν•  점이 μžˆλŠ”λ°, νŒŒμΌμ„ μ‹€ν–‰ν•˜λ©΄μ„œ μƒκΈ°λŠ” μƒˆλ‘œμš΄ ν”„λ‘œμ„ΈμŠ€μ—λŠ” argc에 λŒ€ν•œ 정보가 μ—†κΈ° λ•Œλ¬Έμ— argv의 κ°€μž₯ λ§ˆμ§€λ§‰ μš”μ†Œμ—λŠ” NULL이 μžˆμ–΄μ•Ό ν•œλ‹€. 그리고 argvκ°€ 인자라고 ν•˜λ”λΌλ„ argv의 κ°€μž₯ 첫 μš”μ†Œμ—λŠ” μ‚¬μš©ν•  λͺ…λ Ήμ–΄κ°€ λ°˜λ“œμ‹œ 기재 λ˜μ–΄μ•Ό ν•œλ‹€. execlκ³Ό execvλ₯Ό μ΄μš©ν•˜μ—¬ ls -al test.txtλ₯Ό μ΄μš©ν•˜κ³ μžν•  λ•Œ μ–΄λ–€ μ‹μœΌλ‘œ 각 ν•¨μˆ˜μ˜ 인자λ₯Ό 두어야 ν•˜λŠ”μ§€ μƒκ°ν•΄λ³΄μž.
execl (calling ls -al test.txt)
execv (calling ls -al test.txt)
l 계열 ν•¨μˆ˜λ₯Ό μ΄μš©ν• μ§€ v 계열 ν•¨μˆ˜λ‘œ μ΄μš©ν• μ§€ μ •ν•œ λ’€μ—λŠ” μ‹€ν–‰ν•  νŒŒμΌμ„ μƒλŒ€ 경둜둜 쀄지, μ ˆλŒ€ 경둜둜 쀄 지에 따라 p의 μœ λ¬΄κ°€ κ°ˆλ¦°λ‹€. pλ₯Ό μ΄μš©ν•œ execlp, execvp와 같은 ν•¨μˆ˜λ“€μ€ $PATHλΌλŠ” ν™˜κ²½ λ³€μˆ˜λ₯Ό μ΄μš©ν•˜μ—¬ 첫 번째 인자λ₯Ό μ²˜λ¦¬ν•œλ‹€. 이와 같은 ν•¨μˆ˜λ“€μ€ $PATH에 λ“±λ‘λœ 경둜 내에 λ™μΌν•œ 파일이 μžˆλŠ” κ²½μš°μ— λ¬Έμ œκ°€ λœλ‹€. 특히 이와 같은 λ¬Έμ œλŠ” $PATH λ‚΄μ˜ 경둜λ₯Ό μ‚½μž…ν•˜μ—¬ μ‹€ν–‰ν•  ν”„λ‘œκ·Έλž¨μ— λŒ€ν•΄ κ°•μ œλ‘œ λ°”κΎΈλŠ” 것이 κ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ— λ³΄μ•ˆ μ·¨μ•½ 문제둜 μ΄μ–΄μ§ˆ 수 μžˆλ‹€. λ”°λΌμ„œ μ ˆλŒ€ 경둜λ₯Ό μ΄μš©ν•˜λŠ” λ‚˜λ¨Έμ§€ ν•¨μˆ˜λ“€μ„ μ΄μš©ν•˜λŠ” 것이 μ’‹λ‹€.
exec의 e 계열 ν•¨μˆ˜λ“€μΈ execle, execve와 같은 ν•¨μˆ˜λ“€μ€ e의 μ˜λ―Έμ—μ„œ μ•Œ 수 μžˆλ“―μ΄, ν™˜κ²½ λ³€μˆ˜λ₯Ό ν•¨μˆ˜μ˜ κ°€μž₯ λ§ˆμ§€λ§‰ 인자둜 λ„˜κ²¨μ„œ λ‚΄λΆ€μ μœΌλ‘œ 이λ₯Ό μ΄μš©ν•œλ‹€. ν™˜κ²½ λ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šμ„ 것이라면 execl ν˜Ήμ€ execvλ₯Ό 써도 μ’‹μ§€λ§Œ, execle ν˜Ήμ€ execveλ₯Ό μ‚¬μš©ν•˜λ©΄μ„œ ν™˜κ²½ λ³€μˆ˜μ— ν•΄λ‹Ήν•˜λŠ” μΈμžμ— NULL을 주어도 λœλ‹€. e 계열 ν•¨μˆ˜λ“€μ„ μ΄μš©ν•˜λ©΄μ„œ μ£Όμ˜ν•  점은 κ°€μž₯ λ§ˆμ§€λ§‰ 인자둜 ν™˜κ²½ λ³€μˆ˜λ₯Ό λ„˜κΈΈ λ•Œ, 인자의 κ°€μž₯ λ§ˆμ§€λ§‰ μš”μ†ŒλŠ” NULL이어야 ν•œλ‹€λŠ” 것이닀.
execle ν•¨μˆ˜κ°€ μ‹€ν–‰ν•  νŒŒμΌμ— λ„˜κΈΈ μΈμžλ“€μ„ κ°€λ³€ 인자둜 처리 ν–ˆμŒμ—λ„ κ°€μž₯ λ§ˆμ§€λ§‰ 인자λ₯Ό ν™˜κ²½ λ³€μˆ˜λ‘œ 인식할 수 μžˆλŠ” μ΄μœ λŠ” κ°€μž₯ λ§ˆμ§€λ§‰ 인자 이전에 NULL둜 ꡬ뢄이 λ˜μ–΄ 있기 λ•Œλ¬Έμ΄λ‹€.
execve ν•¨μˆ˜λ₯Ό 톡해 gccλ₯Ό μ‹€ν–‰ν•¨μœΌλ‘œμ¨, μƒˆλ‘œμš΄ μ‹€ν–‰ νŒŒμΌμ„ λ§Œλ“€μ–΄ λ³΄λŠ” 과정을 μ•Œμ•„λ³΄μž.

4. μ˜ˆμ‹œ

#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char **argv) { int i; char **args; if (argc == 1) return (1); i = -1; args = (char **)malloc(argc * sizeof(char *)); if (!args) return (1); args[argc - 1] = NULL; while (++i < argc - 1) args[i] = argv[i + 1]; execve("/usr/bin/gcc", args, NULL); free(args); return (0); }
C

2. Approach

1) 닀쀑 λͺ…λ Ήμ–΄

λͺ…λ Ήμ–΄ μˆ˜λ³΄λ‹€ ν•˜λ‚˜ μž‘μ€ 만큼 νŒŒμ΄ν”„κ°€ μ‘΄μž¬ν•˜λ―€λ‘œ κΈ°μ‘΄μ—λŠ” μ•„λž˜ μ˜μ‚¬ μ½”λ“œμ™€ 같이 νŒŒμ΄ν”„μ˜ 수만큼 동적할당을 λ°›κ³ , λ°˜λ³΅λ¬Έμ„ 돌 λ•Œ indexλ₯Ό κ³„μ‚°ν•˜μ—¬ pipe ν•¨μˆ˜μ— 넣도둝 λ§Œλ“€μ—ˆλ‹€.
int i; int *fd; fd = (int *)malloc(num_pipe * 2 * sizeof(int)); if (!fd) exit (1); i = -1; while (++i < num_pipe) if (pipe(num_pipe * 2) < 0) exit(1); /* ** cmd0 cmd1 cmd2 cmd3 cmd4 ... ** pipe0 pipe1 pipe2 pipe3 ... ** [0,1] [2,3] [4,5] [6,7] ... */
C
μš°μ„  μœ„μ™€ 같은 방법에 λŒ€ν•΄μ„  νŒŒμ΄ν”„λ‘œ μ‚¬μš©ν•  파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό μ–»λŠ”λ° 동적할당을 μ‚¬μš©ν•œλ‹€λŠ” 점이 λ§ˆμŒμ— 듀지 μ•Šμ•˜κ³ , μ²˜λ¦¬ν•΄μ•Όν•  λͺ…령어듀이 λ§Žμ€ νŒŒμ΄ν”„λ₯Ό μš”κ΅¬ν•œλ‹€λ©΄ 그에 λΉ„λ‘€ν•˜λŠ” λ©”λͺ¨λ¦¬λ₯Ό μ΄μš©ν•΄μ•Ό ν•œλ‹€λŠ” 점도 λ§ˆμŒμ— 듀지 μ•Šμ•˜λ‹€.
λ”°λΌμ„œ νŒŒμ΄ν”„λ₯Ό 적게 μ“Έ 수 μžˆλŠ” 방법에 λŒ€ν•΄μ„œ 고민을 ν•˜λ‹€κ°€, νŒŒμ΄ν”„κ°€ 단방ν–₯ ν†΅μ‹ μœΌλ‘œ μ΄μš©λœλ‹€λŠ” 점과 fork둜 μƒμ„±λœ λΆ€λͺ¨ 및 μžμ‹ κ΄€κ³„μ˜ ν”„λ‘œμ„ΈμŠ€λŠ” μ„œλ‘œ λ™μΌν•œ λ©”λͺ¨λ¦¬ ꡬ쑰λ₯Ό κ°–λŠ” 점을 μ΄μš©ν•˜μ—¬ 2개의 νŒŒμ΄ν”„λ§ŒμœΌλ‘œ 닀쀑 λͺ…λ Ήμ–΄λ₯Ό μ²˜λ¦¬ν•  수 μžˆλ„λ‘ κ΅¬μƒν•΄λ³΄μ•˜λ‹€.
이전 λ°©λ²•μ—μ„œ 주어진 νŒŒμ΄ν”„κ°€ μ΄μš©ν•˜λŠ” Read와 Write의 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό 2개둜 μ€„μ˜€μ„ λ•Œ λ™μž‘μ€ μ•„λž˜μ˜ μ˜μ‚¬ μ½”λ“œλ‘œ λ‚˜νƒ€λ‚Έ κ²ƒμ²˜λŸΌ λͺ…λ Ήμ–΄μ˜ indexκ°€ 짝수일 λ•ŒλŠ” B νŒŒμ΄ν”„μ—μ„œ 읽고 A νŒŒμ΄ν”„μ— μ“°λ©°, ν™€μˆ˜μΌ λ•ŒλŠ” A νŒŒμ΄ν”„μ—μ„œ 읽고 B νŒŒμ΄ν”„μ— μ“°λŠ” 것을 μ•Œ 수 μžˆλ‹€.
/* ** cmd0 -> Read from file, Write on A pipe ** cmd1 -> Read from A pipe, Write on B pipe ** cmd2 -> Read from B pipe, Write on A pipe ** cmd3 -> Read from A pipe, Write on B pipe ** ... */
C
λ”°λΌμ„œ λͺ…λ Ήμ–΄λ§ŒνΌμ˜ λ°˜λ³΅λ¬Έμ„ 돌리고 λ‚΄λΆ€μ—μ„œ forkλ₯Ό 톡해 λͺ…λ Ήμ–΄λ₯Ό μˆ˜ν–‰ν•  μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό λ§Œλ“ λ‹€κ³  ν–ˆμ„ λ•Œ, μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ 반볡문 indexκ°€ μ§μˆ˜μΈμ§€ ν™€μˆ˜μΈμ§€μ— 따라 μ–΄λ–€ νŒŒμ΄ν”„μ˜ Read ν˜Ήμ€ Writeλ₯Ό μ΄μš©ν• μ§€ λ§Œλ“€μ–΄μ£Όλ©΄ λœλ‹€. 만일 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” Write에 λŒ€ν•œ 파일 λ””μŠ€ν¬λ¦½ν„°κ°€ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—μ„œ 남아 있게 되면 λͺ…λ Ήμ–΄ 처리 μ‹œ λ¬΄ν•œνžˆ λŒ€κΈ°ν•˜λŠ” ν˜„μƒμ„ λ³Ό 수 있기 λ•Œλ¬Έμ— Write에 λŒ€ν•œ 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό 적절히 λ‹«λŠ” 과정이 ν•„μš”ν•˜λ‹€. μ΄λŠ” λ‹¨μˆœνžˆ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—μ„œ ν•΄λ‹Ή 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό λ‹«μœΌλ©΄ 될 것 κ°™μ§€λ§Œ, μ‹€μ œλ‘œλŠ” κ·Έλ ‡κ²Œ λ‹¨μˆœν•˜μ§€ μ•Šλ‹€.
예λ₯Ό λ“€μ–΄, cmd1은 λͺ…λ Ήμ–΄ indexκ°€ ν™€μˆ˜μ΄λ―€λ‘œ 반볡문 λ‚΄μ˜ fork μ‹œμ  이전에 B νŒŒμ΄ν”„λ₯Ό μƒμ„±ν•˜κ²Œ 될 것이닀. 그리고 fork μ΄ν›„μ˜ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—μ„œλŠ” B νŒŒμ΄ν”„μ— μ›ν•˜λŠ” λ‚΄μš©μ„ κΈ°λ‘ν•˜κ²Œ 될 것인데, 이에 λŒ€ν•΄ ν•„μš”ν•œ μΈμžλ“€μ€ A νŒŒμ΄ν”„μ—μ„œ 읽도둝 μœ λ„ν•΄μ•Ό ν•œλ‹€. 이전 반볡문의 μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—μ„œλŠ” A νŒŒμ΄ν”„μ— 이미 λ‚΄μš©μ„ κΈ°λ‘ν–ˆμ„ κ²ƒμ΄λ―€λ‘œ A νŒŒμ΄ν”„μ—μ„œ λ‚΄μš©μ„ μ½λŠ”λ°λŠ” λ¬Έμ œκ°€ μ—†μ§€λ§Œ, λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œλŠ” A νŒŒμ΄ν”„μ— λ‚΄μš©μ„ κΈ°λ‘ν•˜μ§€ μ•Šμ„ 것이기 λ•Œλ¬Έμ— Write에 λŒ€ν•œ 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό λ‹«μ•„ 두어야 ν•œλ‹€. κ·Έλž˜μ•Ό ν˜„ fork μ‹œμ μ— μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” A νŒŒμ΄ν”„μ— λŒ€ν•΄μ„œ WriteλŠ” λ‹«ν˜€ μžˆλŠ” μƒνƒœλ‘œ Readλ₯Ό μˆ˜ν–‰ν•˜κ³ , μ—΄λ € μžˆλŠ” Write에 λŒ€ν•œ 파일 λ””μŠ€ν¬λ¦½ν„°κ°€ μ—†μœΌλ―€λ‘œ λŒ€κΈ° 없이 정상 μ’…λ£Œλœλ‹€.
cmd0λŠ” 읽을 λ‚΄μš©μ΄ νŒŒμ΄ν”„μ— μžˆλŠ” 것이 μ•„λ‹ˆλΌ νŒŒμΌμ— 있고, κ°€μž₯ λ§ˆμ§€λ§‰ cmdλŠ” μ“Έ λ‚΄μš©μ΄ νŒŒμ΄ν”„κ°€ μ•„λ‹ˆλΌ νŒŒμΌμ— μžˆμœΌλ―€λ‘œ 두 κ²½μš°μ— λŒ€ν•΄μ„œλŠ” λ³„λ„μ˜ μ²˜λ¦¬κ°€ ν•„μš”ν•˜λ‹€.
ν•„μš”ν•œ μ‹œμ λ§ˆλ‹€ Write에 λŒ€ν•œ 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—μ„œ λ‹«μœΌλ©΄ μ•ˆ λ˜λŠ”μ§€ 의문이 λ“€ 수 μžˆλŠ”λ°, νŒŒμ΄ν”„μ˜ μ‚¬μš©ν•˜μ§€ μ•Šμ„ Write에 λŒ€ν•œ 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό λ‹«λŠ” 과정은 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œλ„ ν•„μš”ν•˜κΈ° λ•Œλ¬Έμ— μ€‘λ³΅μœΌλ‘œ λ‹«λŠ” ꡬ문을 λ„£λ‹€κ°€λŠ” 동기화λ₯Ό 쑰금만 잘λͺ»ν•˜λ©΄ Bad File Descriptorλ₯Ό λ³Ό 수 있게 λœλ‹€. λ”°λΌμ„œ μ΅œλŒ€ν•œ μ•ˆμ „ν•˜κ²Œ, fork μ‹œμ  이전에 κ³΅ν†΅μ μœΌλ‘œ μ²˜λ¦¬ν•  수 μžˆλŠ” 뢀뢄에 λŒ€ν•΄μ„œ λ¨Όμ € 처리λ₯Ό ν•΄μ£ΌλŠ” 것이 λ°”λžŒμ§ν•˜λ‹€.
μœ„ λ‚΄μš©μ— λŒ€ν•œ μš”μ§€λŠ” 짝수의 index와 ν™€μˆ˜μ˜ index의 λͺ…λ Ήμ–΄μ—μ„œ μ‚¬μš©ν•  νŒŒμ΄ν”„λ₯Ό 적절히 μƒμ„±ν•˜κ³ , μ‚¬μš©ν•˜μ§€ μ•Šμ„ 파일 λ””μŠ€ν¬λ¦½ν„°μ— λŒ€ν•΄μ„œλŠ” 이전 λ°˜λ³΅λ¬Έμ—μ„œ 사전에 처리λ₯Ό ν•΄μ€˜μ•Ό ν˜„ fork μ‹œμ μ— λ¬Έμ œκ°€ μ—†λ‹€λŠ” 것이닀. μ•„λž˜ μ˜μ‚¬ μ½”λ“œλ₯Ό ν™•μΈν•΄λ³΄μž.
int pipeA[2]; int pipeB[2]; int i; pid_t pid; i = -1; while (++i < num_pipe + 1) { if (!(i % 2)) if (pipe(pipeA) < 0) exit(1); if (i % 2) if (pipe(pipeB) < 0) exit(1); pid = fork(); if (pid == -1) exit(1); else if (!pid) child_proc(); else parent_proc(); } /* ** child_proc ** (각 과정에 λŒ€ν•œ μ²˜λ¦¬μ—μ„œ ν•„μš” μ—†λŠ” 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό 적절히 λ‹«λŠ” 과정이 ν•„μš”ν•˜λ‹€.) ** ** 졜초: νŒŒμΌμ—μ„œ μ½λŠ” μž‘μ—…μ„ μˆ˜ν–‰ ** ** μ΅œμ’…: νŒŒμΌμ— μ“°λŠ” μž‘μ—…μ„ μˆ˜ν–‰ ** ** 쀑간: 짝수 index인지, ν™€μˆ˜ index인지에 따라 μ–΄λŠ νŒŒμ΄ν”„μ˜ Read, Writeλ₯Ό Redirectionν•  지 달라진닀. ** ν™€μˆ˜ index -> A νŒŒμ΄ν”„μ—μ„œ 읽어야 ν•˜λ―€λ‘œ A νŒŒμ΄ν”„μ˜ Readλ₯Ό STDIN으둜 dup2λ₯Ό μˆ˜ν–‰ν•œλ‹€. ** B νŒŒμ΄ν”„μ— 써야 ν•˜λ―€λ‘œ, B νŒŒμ΄ν”„μ˜ Writeλ₯Ό STDOUT으둜 dup2λ₯Ό μˆ˜ν–‰ν•œλ‹€. ** 짝수 index -> B νŒŒμ΄ν”„μ—μ„œ 읽어야 ν•˜λ―€λ‘œ B νŒŒμ΄ν”„μ˜ Readλ₯Ό STDIN으둜 dup2λ₯Ό μˆ˜ν–‰ν•œλ‹€. ** A νŒŒμ΄ν”„μ— 써야 ν•˜λ―€λ‘œ, A νŒŒμ΄ν”„μ˜ Writeλ₯Ό STDOUT으둜 dup2λ₯Ό μˆ˜ν–‰ν•œλ‹€. */ /* ** parent_proc의 λͺ…λ Ήμ–΄ index에 λ”°λ₯Έ 처리 ** (ν˜„ index의 μ²˜λ¦¬λŠ” fork μ‹œμ  이후 μž„μ„ λͺ…μ‹¬ν•œλ‹€.) ** ** 졜초: 짝수 index이고 읽을 λ‚΄μš©μ€ νŒŒμΌμ— μžˆμœΌλ―€λ‘œ, A νŒŒμ΄ν”„μ˜ Write만 λ‹«λŠ”λ‹€. ** ** μ΅œμ’…: 짝수 index인지, ν™€μˆ˜ index인지에 따라 μ–΄λŠ νŒŒμ΄ν”„μ˜ Writeλ₯Ό λ‹«λŠ”μ§€ 달라진닀. ** ν™€μˆ˜ index -> κΈ°μ‘΄μ—λŠ” B νŒŒμ΄ν”„μ— Writeλ₯Ό ν•˜κ² μ§€λ§Œ, νŒŒμΌμ— Writeλ₯Ό μˆ˜ν–‰ν•  κ²ƒμ΄λ―€λ‘œ B νŒŒμ΄ν”„μ˜ WriteλŠ” ν•„μš”κ°€ μ—†λ‹€. ** 짝수 index -> κΈ°μ‘΄μ—λŠ” A νŒŒμ΄ν”„μ— Writeλ₯Ό ν•˜κ² μ§€λ§Œ, νŒŒμΌμ— Writeλ₯Ό μˆ˜ν–‰ν•  κ²ƒμ΄λ―€λ‘œ A νŒŒμ΄ν”„μ˜ WriteλŠ” ν•„μš”κ°€ μ—†λ‹€. ** ** 쀑간: 짝수 index인지, ν™€μˆ˜ index인지에 따라 μ–΄λŠ νŒŒμ΄ν”„μ˜ Read, Writeλ₯Ό λ‹«λŠ”μ§€ 달라진닀. ** ν™€μˆ˜ index -> λ‹€μŒ λ°˜λ³΅λ¬Έμ€ 짝수 indexμ΄λ―€λ‘œ B νŒŒμ΄ν”„μ—μ„œ 읽고, A νŒŒμ΄ν”„μ— μ“Έ 것이닀. ** λ”°λΌμ„œ B νŒŒμ΄ν”„μ˜ Writeλ₯Ό λ‹«κ³ , A νŒŒμ΄ν”„μ˜ Readλ₯Ό λ‹«λŠ”λ‹€. ** 짝수 index -> λ‹€μŒ λ°˜λ³΅λ¬Έμ€ ν™€μˆ˜ indexμ΄λ―€λ‘œ A νŒŒμ΄ν”„μ—μ„œ 읽고, B νŒŒμ΄ν”„μ— μ“Έ 것이닀. ** λ”°λΌμ„œ A νŒŒμ΄ν”„μ˜ Writeλ₯Ό λ‹«κ³ , B νŒŒμ΄ν”„μ˜ Readλ₯Ό λ‹«λŠ”λ‹€. ** ** λͺ…λ Ήμ–΄ index에 λ”°λ₯Έ μ²˜λ¦¬κ°€ 끝났닀면, μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ ν˜„ λͺ…λ Ήμ–΄ μˆ˜ν–‰μ„ 기닀리도둝 적절히 wait / waitpidλ₯Ό μ΄μš©ν•œλ‹€. ** 만일 μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—μ„œ Exception이 λ°œμƒν–ˆλ‹€λ©΄, 적절히 statusλ₯Ό λΆ„μ„ν•œλ‹€. ** exec ν•¨μˆ˜λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€ 자체λ₯Ό κ΅μ²΄ν•˜μ—¬ μˆ˜ν–‰λœλ‹€λŠ” 점을 μœ μ˜ν•΄μ•Ό ν•œλ‹€. */
C
μœ„ μ½”λ“œλ₯Ό 보면 λ§ˆμ§€λ§‰ λͺ…λ Ήμ–΄μ˜ Read에 λŒ€ν•œ 파일 λ””μŠ€ν¬λ¦½ν„°κ°€ λ‹«νžˆμ§€ μ•Šμ€ 것을 λ³Ό 수 μžˆλŠ”λ°, μ½”λ“œ ꡬ동에 μžˆμ–΄μ„œ λ¬Έμ œκ°€ λ˜λŠ” 것은 Write에 λŒ€ν•œ 파일 λ””μŠ€ν¬λ¦½ν„°κ°€ λ‹«νžˆμ§€ μ•Šμ€ κ²½μš°μ΄λ‹€. ν•˜μ§€λ§Œ κ·Έ μ™Έ 쀑간 λͺ…λ Ήμ–΄μ˜ 파일 λ””μŠ€ν¬λ¦½ν„°λ“€μ€ Read, Write에 λŒ€ν•΄ λ‹«λŠ” 것을 λ³Ό 수 μžˆλŠ”λ°, μ΄λŠ” λ™μΌν•œ 번호의 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό μœ μ§€ν•˜κΈ° μœ„ν•¨μ΄λ‹€. 이미 μ—΄λ € μžˆλŠ” 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό κ°–κ³  μžˆλŠ” νŒŒμ΄ν”„μ— λ‹€μ‹œ pipeλ₯Ό μˆ˜ν–‰ν•΄λ„ 였λ₯˜λŠ” λ‚˜μ§€ μ•ŠμœΌλ‚˜, 기쑴에 μ—΄λ € 있던 파일 λ””μŠ€ν¬λ¦½ν„°μ˜ 번호λ₯Ό 버리고 μƒˆλ‘œμš΄ 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό μ–»μ–΄λ‚΄λŠ” 것을 λ³Ό 수 μžˆλ‹€. 즉, 쀑간 λͺ…령어에 λŒ€ν•΄μ„  ν˜„μž¬ μ‚¬μš© 쀑인 νŒŒμ΄ν”„μ˜ 파일 λ””μŠ€ν¬λ¦½ν„°λ“€μ„ 적절히 닫아주지 μ•ŠμœΌλ©΄ λ™μΌν•œ 번호의 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό μœ μ§€ν•  수 μ—†κ²Œ λœλ‹€. 이와 같이 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό μœ μ§€ν•˜λŠ” 것은 λ¬Έμ œκ°€ 될 κ°€λŠ₯성이 ꡉμž₯히 λ†’μœΌλ©°, ν˜Ήμ—¬λ‚˜ λ™μž‘ μžμ²΄μ—λŠ” 문제 없더라도 ν• λ‹Ή 받을 파일 λ””μŠ€ν¬λ¦½ν„°κ°€ 없을 κ²½μš°κ°€ μžˆμ„ μˆ˜λ„ μžˆλ‹€λŠ” 점을 μœ μ˜ν•΄μ•Ό ν•œλ‹€.

2) here_doc에 λ”°λ₯Έ μ‚¬μš©μž μž…λ ₯ 처리

here_doc을 λͺ…μ‹œν•˜λ©΄ μ‚¬μš©μžκ°€ 직접 μž…λ ₯ν•œ λ‚΄μš©μ„ ν‘œμ€€ μž…λ ₯으둜 μ²˜λ¦¬ν•˜μ—¬ λͺ…λ Ήμ–΄κ°€ 이λ₯Ό 받을 수 μžˆλ„λ‘ λ§Œλ“€μ–΄μ•Ό ν•œλ‹€. 단, ctrl + Dλ₯Ό μ΄μš©ν•˜μ§€ μ•Šκ³  limiter에 ν•΄λ‹Ήν•˜λŠ” λ¬Έμžμ—΄μ΄ λ‚˜μ˜€λ©΄ ν‘œμ€€ μž…λ ₯을 λ§ˆμΉ˜λ„λ‘ ν•΄μ•Όν•œλ‹€. λ”°λΌμ„œ μ•„λ¬΄λŸ° μž‘μ—… 없이 exec 계열 ν•¨μˆ˜κ°€ ν‘œμ€€ μž…λ ₯을 μ΄μš©ν•˜κ²Œ λ‘” κ²½μš°μ—λŠ” limiter에 λŒ€ν•œ ꡬ뢄이 λΆˆκ°€λŠ₯ν•˜λ―€λ‘œ λ‹€λ₯Έ 방법이 μš”κ΅¬λœλ‹€.
μš°μ„  get_next_line을 μ΄μš©ν•˜μ—¬ ν‘œμ€€ μž…λ ₯으둜 limiter μ „κΉŒμ§€ 받도둝 λ§Œλ“€μ–΄ λ‚΄κ³  이λ₯Ό exec 계열 ν•¨μˆ˜κ°€ μ΄μš©ν•  수 μžˆλ„λ‘ λ§Œλ“€μ–΄μ•Ό ν•œλ‹€. 이 λ•Œ μ΄μš©ν•  수 μžˆλŠ” 방법은 2가지가 μžˆλ‹€. 첫 μ§ΈλŠ” νŒŒμ΄ν”„λ₯Ό μ΄μš©ν•œ 방법이고, λ‘˜ μ§ΈλŠ” μž„μ‹œ νŒŒμΌμ„ μ΄μš©ν•œ 방법이닀.
νŒŒμ΄ν”„λ₯Ό μ΄μš©ν•˜κ²Œ 되면 λ³„λ„μ˜ νŒŒμΌμ„ μœ μ§€ν•˜μ§€ μ•Šμ•„λ„ 되고, 이에 λŒ€ν•΄μ„œ ν”„λ‘œκ·Έλž¨ μ’…λ£Œ μ‹œμ μ— νŒŒμΌμ„ μ‚­μ œν•˜λŠ” ν–‰μœ„λ₯Ό κ±°μΉ˜μ§€ μ•Šμ•„λ„ λœλ‹€. ν•˜μ§€λ§Œ νŒŒμ΄ν”„ μžμ²΄κ°€ μœ μ§€ν•  수 μžˆλŠ” 데이터 μžμ²΄λŠ” 섀정에 따라 정해진 버퍼 μ‚¬μ΄μ¦ˆ 만큼이기 λ•Œλ¬Έμ—, νŒŒμ΄ν”„λ₯Ό μ΄μš©ν•˜κΈ° 전에 ν‘œμ€€ μž…λ ₯을 사전에 λŒλ¦¬λŠ” μž‘μ—…μ΄ μš”κ΅¬λœλ‹€. 그리고 ν‘œμ€€ μž…λ ₯을 사전에 λŒλ¦¬λŠ” μž‘μ—… μžμ²΄λŠ” 동일 ν”„λ‘œμ„ΈμŠ€μ—μ„œ 진행 μ‹œμ— get_next_line으둜 limiter μ „κΉŒμ§€ λ°›μ•„λ‚΄λŠ” μž‘μ—…μ΄ λΆˆκ°€λŠ₯ν•˜λ―€λ‘œ, forkλ₯Ό 톡해 λ³„λ„μ˜ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—μ„œ 진행해야 ν•œλ‹€.
μž„μ‹œ νŒŒμΌμ„ μ΄μš©ν•˜κ²Œ 되면 비둝 νŒŒμΌμ— λŒ€ν•œ 관리가 μš”κ΅¬λ˜κΈ΄ ν•˜λ‚˜, νŒŒμ΄ν”„μ™€ 같이 μ‘°κΈˆμ€ λ³΅μž‘ν•œ 과정을 κ±°μΉ˜μ§€ μ•Šμ•„λ„ 되며 버퍼 μ‚¬μ΄μ¦ˆ μ œν•œμœΌλ‘œλΆ€ν„° μžμœ λ‘œμš°λ―€λ‘œ 데이터 크기에 λŒ€ν•΄μ„œ μ‹ κ²½ μ“Έ ν•„μš”κ°€ 없어진닀. λ”°λΌμ„œ 사전에 ν‘œμ€€ μž…λ ₯을 돌릴 ν•„μš”κ°€ μ—†μ–΄μ§€λ―€λ‘œ, fork μž‘μ—…μ΄ μš”κ΅¬λ˜μ§€ μ•ŠλŠ”λ‹€.
pipexμ—μ„œ unlink ν•¨μˆ˜λ₯Ό ν—ˆμš©ν•˜μ§€λ§Œ μ•„μ§κΉŒμ§€ μ‚¬μš©μ΄ λ˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ— unlink ν•¨μˆ˜λ₯Ό μ—¬κΈ°μ„œ μ‚¬μš©ν•˜λ©΄ λ˜κ² λ‹€λŠ” 생각이 λ“€μ—ˆκ³ , νŒŒμ΄ν”„λ₯Ό μ΄μš©ν•˜μ—¬ ν‘œμ€€ μž…λ ₯을 돌렀 λ†“λŠ” μž‘μ—…μ΄ λͺ…λ Ήμ–΄ μ‹€ν–‰ 전에 이뀄져 비둝 λͺ…λ Ήμ–΄ μ‹€ν–‰ 전이라 μ½νžˆμ§€λŠ” μ•ŠμœΌλ‚˜ 접근이 κ°€λŠ₯ν•˜λ‹€λŠ” 점 λ•Œλ¬Έμ— limiter의 μ˜λ―Έμ™€λŠ” 쑰금 거리가 μžˆλ‹€λŠ” 생각이 λ“€μ—ˆλ‹€. 고둜 두 방법 쀑 μ–΄λŠ 방법을 μ‚¬μš©ν•˜μ—¬λ„ λ¬΄λ°©ν•˜λ‹€κ³  생각이 λ˜λ‚˜, μ—¬λŸ¬ λ²ˆλ³΅μ„ 톡해 μž„μ‹œ νŒŒμΌμ„ λ§Œλ“œλŠ” λ°©μ‹μœΌλ‘œ μ§„ν–‰ν•˜κΈ°λ‘œ ν–ˆλ‹€.
μ—¬κΈ°κΉŒμ§€ 생각할 수 μžˆλ„λ‘ 도와주신 hyechoiλ‹˜, hyeonskiλ‹˜, hyeonsokλ‹˜ κ°μ‚¬ν•©λ‹ˆλ‹€.

1. νŒŒμ΄ν”„λ₯Ό μ΄μš©ν•œ here_doc 처리

1.
νŒŒμ΄ν”„ 생성 ν›„ fork μ‹œλ„
2.
λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€ : νŒŒμ΄ν”„μ˜ Write λ‹«κΈ°
3.
λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€ : dup2λ₯Ό 톡해 νŒŒμ΄ν”„μ˜ Readλ₯Ό ν‘œμ€€ μž…λ ₯으둜 돌린 ν›„, νŒŒμ΄ν”„μ˜ Read λ‹«κΈ°
4.
λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€ : λŒ€κΈ°
5.
μžμ‹ ν”„λ‘œμ„ΈμŠ€ : νŒŒμ΄ν”„μ˜ Read λ‹«κΈ°
6.
μžμ‹ ν”„λ‘œμ„ΈμŠ€ : get_next_line을 톡해 ν‘œμ€€ μž…λ ₯으둜 읽은 λ¬Έμžμ—΄μ„ νŒŒμ΄ν”„μ˜ Write에 기둝
7.
μžμ‹ ν”„λ‘œμ„ΈμŠ€ : limterλ₯Ό λ§Œλ‚˜λ©΄ νŒŒμ΄ν”„μ˜ Write λ‹«κΈ°
8.
μžμ‹ ν”„λ‘œμ„ΈμŠ€ : μ’…λ£Œ

2. μž„μ‹œ νŒŒμΌμ„ μ΄μš©ν•œ here_doc 처리

1.
O_WRONLY, O_CREAT, O_TRUNC λͺ¨λ“œ 및 0644 κΆŒν•œμœΌλ‘œ μž„μ‹œ 파일 생성
2.
limiterκ°€ λ‚˜μ˜€κΈ° μ „κΉŒμ§€ μž„μ‹œ νŒŒμΌμ— 기둝
3.
limiterλ₯Ό λ§Œλ‚˜λ©΄ 기둝을 μ€‘μ§€ν•˜κ³  μž„μ‹œ νŒŒμΌμ„ λ‹«κΈ°
4.
O_RDONLY λͺ¨λ“œλ‘œ μž„μ‹œ 파일 λ‹€μ‹œ μ—΄κΈ°
5.
dup2λ₯Ό 톡해 ν‘œμ€€ μž…λ ₯을 μž„μ‹œ 파일둜 돌리기
6.
μž„μ‹œ 파일 λ‹«κΈ°

3) 기타

μœ„μ—μ„œ μ²˜λ¦¬ν•΄μ•Ό ν•˜λŠ” λ‚΄μš©λ“€ 외에도 μ•„λž˜μ™€ 같이 ν•œ 번 쯀은 생각해봐야 ν•˜λŠ” 것듀이 μžˆλ‹€.
1.
닀쀑 λ”°μ˜΄ν‘œ 처리
2.
λͺ…λ Ήμ–΄ 경둜 μ„€μ •
3.
λͺ…λ Ήμ–΄ 처리 λ‹¨μœ„
4.
였λ₯˜ 문ꡬ 처리
1λ²ˆμ— λŒ€ν•΄μ„  λ¨Όμ € λ‚˜μ˜¨ λ”°μ˜΄ν‘œ μŒμ— λ§žμΆ°μ„œ νŒŒμ‹±μ„ 진행해야 ν•˜λ©°, λ”°μ˜΄ν‘œ 내에 μžˆμ§€ μ•Šμ€ λ‚΄μš©λ“€μ€ 곡백 문자λ₯Ό κΈ°μ€€μœΌλ‘œ νŒŒμ‹±μ„ 진행해야 ν•œλ‹€. 이 λ•Œ λ¨Όμ € λ°œκ²¬ν•œ λ”°μ˜΄ν‘œ 쌍 μžμ²΄λŠ” exec ν•¨μˆ˜μ˜ 인자둜 λ„˜κΈΈ λ•Œ 포함 λ˜μ–΄μ„œλŠ” μ•ˆ λœλ‹€. 예λ₯Ό λ“€μ–΄ awk '\"{count++} END {print count}\"'의 경우, exec 계열 ν•¨μˆ˜μ˜ μΈμžλ‘œλŠ” awk, \"{count++} END {print count}\"와 같이 λ”°μ˜΄ν‘œλ₯Ό μ œμ™Έν•˜κ³  λ“€μ–΄κ°€κ²Œ λœλ‹€.
μˆ˜ν–‰ν•  λͺ…λ Ήμ–΄λŠ” 항상 /binμ—λ§Œ μžˆλŠ” 것도 μ•„λ‹ˆκ³ , /usr/binμ—λ§Œ μžˆλŠ” 것도 μ•„λ‹ˆλ‹€. 정해진 λͺ…λ Ήμ–΄λ₯Ό μ΄μš©ν•  수 μžˆλŠ” 상황도 μ•„λ‹ˆκΈ° λ•Œλ¬Έμ— λͺ…령어에 λŒ€ν•œ 경둜λ₯Ό 미리 μ„€μ •ν•΄λ‘λŠ” 것에도 무리가 μžˆλ‹€. λ”°λΌμ„œ μ΅œλŒ€ν•œ μ‰˜μ˜ λ™μž‘κ³Ό μœ μ‚¬ν•˜κ²Œ μž‘μ—…μ„ ν•΄μ•Όν•˜λ―€λ‘œ, 상황에 따라 μ μ ˆν•œ 경둜의 λͺ…λ Ήμ–΄λ₯Ό μ΄μš©ν•  수 μžˆλ„λ‘ $PATHλ₯Ό μ΄μš©ν•΄μ•Ό ν•œλ‹€. 이에 따라 main ν•¨μˆ˜μ—μ„œ μ„Έ 번째 인자둜 char **envpλ₯Ό 받도둝 λ§Œλ“ λ‹€. envpλ₯Ό 톡해 pipex ꡬ동 μ‹œμ μ˜ λͺ¨λ“  ν™˜κ²½ λ³€μˆ˜λ₯Ό μ–»μ–΄μ™”λ‹€λ©΄, $PATHλΌλŠ” ν™˜κ²½ λ³€μˆ˜λ₯Ό : λ‹¨μœ„λ‘œ νŒŒμ‹±μ„ ν•˜μ—¬ μ ‘κ·Όν•˜λ €λŠ” 파일 이름을 뢙이고 파일의 쑴재 유무λ₯Ό ν™•μΈν•˜λ©΄ λœλ‹€. 만일 파일이 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ νŒŒμ‹±λœ κ·Έ λ‹€μŒ 경둜λ₯Ό μ΄μš©ν•˜μ—¬ 파일의 쑴재 유무λ₯Ό ν™•μΈν•˜λ©΄ 되고, λκΉŒμ§€ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ 파일 이름 κ·ΈλŒ€λ‘œλ₯Ό μ΄μš©ν•œλ‹€. 이와 같이 μ„€μ •λœ λͺ…λ Ήμ–΄ 경둜λ₯Ό μ΄μš©ν•˜μ—¬ exec 계열 ν•¨μˆ˜λ‘œ 싀행을 ν–ˆμ„ λ•Œ 였λ₯˜κ°€ λ°œμƒν•œλ‹€λ©΄, μ‰˜μ—μ„œμ˜ λ‹€μ–‘ν•œ 였λ₯˜ ꡬ문과 μœ μ‚¬ν•˜κ²Œ μ μ ˆν•œ μž‘μ—…μ΄ μš”κ΅¬λ˜λŠ” 것을 μžŠμ–΄μ„  μ•ˆ λœλ‹€.
결ꡭ에 $PATH ν™˜κ²½ λ³€μˆ˜λ₯Ό μ΄μš©ν•˜λ©΄μ„œ execvpλ₯Ό μ΄μš©ν•˜μ§€ μ•ŠλŠ” μ΄μœ λŠ”, execvpλŠ” pipex ꡬ동 도쀑 λ³€κ²½λœ $PATH에 λŒ€ν•΄μ„œλ„ 영ν–₯을 받을 수 있기 λ•Œλ¬Έμ΄λ‹€. μ΄λŠ” $PATH Injection Attack으둜 μ΄μ–΄μ§ˆ 수 μžˆμ–΄ μƒλŒ€μ μœΌλ‘œ 더 λ³΄μ•ˆμ— μ·¨μ•½ν•˜λ‹€.
3λ²ˆμ— λŒ€ν•΄μ„œ κ°„κ³Όν•˜κΈ° μ‰¬μš΄ 것 κ°™λ‹€λŠ” 생각이 λ“€μ—ˆλ‹€. μ²˜μŒμ— pipexλ₯Ό κ΅¬ν˜„ν•  λ•Œ νŒŒμ΄ν”„λ‘œ λ„˜μ–΄κ°€κΈ° 전에 였λ₯˜κ°€ λ‚˜λ©΄ 전체 ν”„λ‘œκ·Έλž¨μ„ μ’…λ£Œν•˜λŠ” 방식을 κ³ μ§‘ν–ˆλŠ”λ°, μ‹€μ œ μ‰˜μ—μ„œλŠ” νŒŒμ΄ν”„λ‘œ κ΅¬λΆ„λœ λͺ…λ Ήμ–΄λ“€ 사이에 였λ₯˜κ°€ 생기면 μ¦‰μ‹œ μ’…λ£Œλ˜μ§€ μ•Šκ³  νŒŒμ΄ν”„ λ‹¨μœ„λ‘œ λ‚˜λ‰œ λͺ…령어듀을 λͺ¨λ‘ μ²˜λ¦¬ν•˜λŠ” 것을 λ³Ό 수 μžˆμ—ˆλ‹€. 예λ₯Ό λ“€μ–΄μ„œ grep hello | wc -l κ³Ό 같은 2개의 λͺ…λ Ήμ–΄κ°€ μžˆλ‹€κ³  해보면, grepμ—μ„œ 였λ₯˜κ°€ λ‚œλ‹€κ³  ν•΄μ„œ μ’…λ£Œλ˜λŠ” 것이 μ•„λ‹ˆλΌ grepμ—μ„œ 였λ₯˜κ°€ λ‚˜λ”λΌλ„ wcλŠ” λ“€μ–΄μ˜€λŠ” μΈμžκ°€ μ—†λŠ” κ²ƒμœΌλ‘œ μƒκ°ν•˜κ³  μ •μƒμ μœΌλ‘œ λ™μž‘ν•œλ‹€λŠ” 것이닀. 즉, νŒŒμ΄ν”„λ₯Ό μ΄μš©ν•˜κ²Œ 되면 λͺ…λ Ήμ–΄ 처리 λ‹¨μœ„λŠ” 전체가 μ•„λ‹Œ νŒŒμ΄ν”„ λ‹¨μœ„μž„μ„ λͺ…심해야 ν•œλ‹€.
μ‰˜μ— λŒ€ν•΄μ„  bash ν˜Ήμ€ zshλ₯Ό 많이 μ΄μš©ν•œλ‹€. λŒ€μ²΄μ μœΌλ‘œ 두 μ‰˜μ—μ„œ λ‚΄λŠ” 였λ₯˜ 문ꡬ듀이 λΉ„μŠ·ν•˜κ±°λ‚˜ λ™μΌν•œ κ²½μš°κ°€ λ§Žμ•„μ„œ, 였λ₯˜ 문ꡬ에 λŒ€ν•΄μ„œλ„ μ •ν™•νžˆ λ§žμΆ°μ•Ό ν•˜λŠ”κ°€μ— λŒ€ν•΄ 고민이 λ“€ μˆ˜λ„ μžˆκ² λ‹€λŠ” 생각이 λ“€μ—ˆλ‹€. ν•˜μ§€λ§Œ μ‰˜μ€ bash, zsh만 μžˆλŠ” 것은 μ•„λ‹ˆλ‹€. 두 μ‰˜ 외에도 sh, csh, ksh, tcsh λ“± λ‹€μ–‘ν•œ μ‰˜μ΄ μ‘΄μž¬ν•œλ‹€. 이 μ‰˜λ“€ λ‚΄μ—μ„œλ„ λͺ¨λ“  였λ₯˜ 문ꡬ가 λ™μΌν•˜μ§€λŠ” μ•Šλ‹€. 잘 생각해보면 이듀도 μ„œλ‘œ λ‹€λ₯Έ κ°œλ°œμžλ“€μ— μ˜ν•΄ λ§Œλ“€μ–΄μ§„ μ„œλ‘œ λ‹€λ₯Έ ν”„λ‘œκ·Έλž¨μ— λΆˆκ³Όν•˜λ‹€. 였λ₯˜μ— λŒ€ν•œ μ²˜λ¦¬κ°€ λ˜μ—ˆλ‹€λŠ” 점은 λ™μΌν•˜μ§€λ§Œ λͺ¨λ“  문ꡬ가 μΌμΉ˜ν•˜μ§€λŠ” μ•ŠλŠ”λ‹€. λ”°λΌμ„œ pipexλ₯Ό κ΅¬ν˜„ν•  λ•Œλ„ λ§₯락 상 μ–΄λ–€ 였λ₯˜κ°€ λ°œμƒν–ˆλŠ”μ§€ νŒŒμ•…λ§Œ κ°€λŠ₯ν•˜λ‹€λ©΄ 였λ₯˜ 문ꡬ가 달라도 크게 λ¬Έμ œκ°€ μ—†λ‹€λŠ” 생각이 λ“ λ‹€. 특히 pipexμ—μ„œλŠ” λͺ¨λ“  문ꡬλ₯Ό λ§žμΆ”κ³ μž ν•œλ‹€λ©΄ μΈμžκ°€ 디렉토리인지 μ•„λ‹Œμ§€μ— λŒ€ν•œ ꡬ뢄이 ν•„μš”ν•  λ•Œκ°€ μžˆλŠ”λ°, pipexμ—μ„œλŠ” <sys/stat.h>의 stat ꡬ쑰체와 κ΄€λ ¨ ν•¨μˆ˜λ“€μ΄ ν—ˆμš©λ˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ— μ •ν™•ν•˜κ²Œ 문ꡬλ₯Ό λ§žμΆ”λŠ”λ°λŠ” 무리가 μžˆλ‹€. μ²˜λ¦¬κ°€ λΆˆκ°€λŠ₯ν•œ 문ꡬ μ™Έμ—λŠ” μ΅œλŒ€ν•œ 였λ₯˜μ— λŒ€ν•œ 의미 전달이 κ°€λŠ₯ν•˜λ„λ‘ λ§Œλ“€μ–΄μ•Ό ν•œλ‹€.

3. Reference

κ³ λ €λŒ€ν•™κ΅ COSE341 운영체제 by 유혁 κ΅μˆ˜λ‹˜
[C-λ„€νŠΈμ›Œν¬] λ©€ν‹°ν”„λ‘œμ„ΈμŠ€ fork() - 2 (μ‹œκ·Έλ„ 핸듀링)
μ•ˆλ…•ν•˜μ„Έμš”, μ­μž…λ‹ˆλ‹€. μ΄λ²ˆμ—” cμ–Έμ–΄λ‘œ λ©€ν‹°ν”„λ‘œμ„ΈμŠ€λ₯Ό κ΅¬μ„±ν•˜λŠ”λ°, μ‹œκ·Έλ„μ„ μ΄μš©ν•œ κΉ”λ”ν•œ 처리λ₯Ό ν•΄λ΄…μ‹œλ‹€. μ‹œκ·Έλ„(Signal)이 뭐죠? μ‹œκ·Έλ„μ€ νŠΉμ • 상황이 λ˜μ—ˆμ„λ•Œ, 운영체제(OS)κ°€ ν”„λ‘œμ„ΈμŠ€μ—κ²Œ ν•΄λ‹Ή 상황이 λ°œμƒν–ˆμŒμ„ μ•Œλ¦¬λŠ” μΌμ’…μ˜ 메세지λ₯Ό λ§ν•©λ‹ˆλ‹€. 사싀은 우리의 ν”„λ‘œμ„ΈμŠ€λŠ” μ‹€ν–‰λ˜λŠ” 도쀑, OS둜 λΆ€ν„° 각쒅 μ‹œκ·Έλ„μ„ λ°›μŠ΅λ‹ˆλ‹€. κ·Έ μ‹œκ·Έλ„λ“€ μ€‘μ—μ„œλŠ” 도착해도 λ¬΄μ‹œκ°€λ˜λŠ”(ν”„λ‘œμ„ΈμŠ€λŠ” μ•„λ¬΄λŸ° 방해없이 ν•˜λ˜μž‘μ—…μ„ 계속) μ‹œκ·Έλ„λ„ 있고, ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œλ₯Ό λ™μž‘μ‹œν‚€λŠ” μ‹œκ·Έλ„λ“€(λŒ€ν‘œμ μœΌλ‘œ ctrl+c 둜 κ°•μ œμ’…λ£Œ) 도 μžˆμŠ΅λ‹ˆλ‹€.

4. Code of Jseo