pipe - hochan222/Everything-in-JavaScript GitHub Wiki

νŒŒμ΄ν”„λŠ” 두 ν”„λ‘œμ„ΈμŠ€ μ‚¬μ΄μ—μ„œ ν•œ λ°©ν–₯으둜 톡신할 수 μžˆλ„λ‘ μ§€μ›ν•©λ‹ˆλ‹€. μ‰˜μ—μ„œ | κΈ°ν˜ΈλŠ” νŒŒμ΄ν”„λ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€. μ‰˜μ—μ„œ νŒŒμ΄ν”„ κΈ°λŠ₯은 ν•œ λͺ…λ Ήμ˜ ν‘œμ€€ 좜λ ₯을 λ‹€μŒ λͺ…λ Ήμ—μ„œ ν‘œμ€€ μž…λ ₯을 λ°›μ•„ μˆ˜ν–‰ν•˜λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€.

예λ₯Όλ“€μ–΄,

# grep pipe test.c | more

μ•žμ— μžˆλŠ” λͺ…령인 grep pipe test.c의 ν‘œμ€€ 좜λ ₯을 λ‹€μŒ λͺ…령인 more의 ν‘œμ€€ μž…λ ₯으둜 μ‚¬μš©ν•©λ‹ˆλ‹€. μœ„ 예λ₯Ό μ‹€ν–‰ν•˜λ©΄ test.cμ—μ„œ "pipe"λΌλŠ” λ¬Έμžμ—΄μ΄ μœ„μΉ˜ν•œ 행을 μ°Ύμ•„ ν™”λ©΄ λ‹¨μœ„λ‘œ 좜λ ₯(more)ν•©λ‹ˆλ‹€. νŒŒμ΄ν”„λŠ” μ΄λ¦„μ—†λŠ” νŒŒμ΄ν”„(읡λͺ… νŒŒμ΄ν”„:anonymouse pipe)와 (이름 μžˆλŠ” νŒŒμ΄ν”„:named pipe)둜 κ΅¬λΆ„λ©λ‹ˆλ‹€.


이름 μ—†λŠ” νŒŒμ΄ν”„ : pipe

νŠΉλ³„ν•œ μˆ˜μ‹μ–΄ 없이 κ·Έλƒ₯ νŒŒμ΄ν”„λΌκ³  ν•˜λ©΄ 일반적으둜 이름 μ—†λŠ” νŒŒμ΄ν”„(읡λͺ… νŒŒμ΄ν”„)λ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€. 이름 μ—†λŠ” νŒŒμ΄ν”„λŠ” λΆ€λͺ¨-μžμ‹ ν”„λ‘œμ„ΈμŠ€ 간에 톡신할 수 있게 ν•΄μ€λ‹ˆλ‹€. λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œ fork ν•¨μˆ˜λ₯Ό 톡해 μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•˜κ³ , λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ™€ μžμ‹ ν”„λ‘œμ„ΈμŠ€ 간에 ν†΅μ‹ ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. λ”°λΌμ„œ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€ β†’ μžμ‹ ν”„λ‘œμ„ΈμŠ€ λ˜λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€ β†’ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€ 쀑 ν•œ λ°©ν–₯을 선택해야 ν•©λ‹ˆλ‹€. νŒŒμ΄ν”„λ₯Ό μ΄μš©ν•΄ μ–‘λ°©ν–₯ 톡신을 원할 경우 νŒŒμ΄ν”„λ₯Ό 두 개 생성해야 ν•©λ‹ˆλ‹€.

κ°„λ‹¨ν•œ νŒŒμ΄ν”„ 생성: FILE *popen(const char *command, const char *mode); int pclose(FILE *stream);
λ³΅μž‘ν•œ νŒŒμ΄ν”„ 생성: int pipe(int fildes[2]);


이름 μžˆλŠ” νŒŒμ΄ν”„ : FIFO

λΆ€λͺ¨-μžμ‹ ν”„λ‘œμ„ΈμŠ€ 관계가 μ•„λ‹Œ 독립적인 ν”„λ‘œμ„ΈμŠ€λ“€μ΄ νŒŒμ΄ν”„λ₯Ό μ΄μš©ν•˜λ €λ©΄ 파일처럼 이름이 μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€. μ΄λ ‡κ²Œ μ΄λ¦„μžˆλŠ” νŒŒμ΄ν”„λŠ” 특수 파일의 ν•œ μ’…λ₯˜λ‘œ, FIFO라고도 ν•©λ‹ˆλ‹€. λͺ¨λ“  ν”„λ‘œμ„ΈμŠ€κ°€ 이름 μžˆλŠ” νŒŒμ΄ν”„λ₯Ό μ΄μš©ν•΄ 톡신할 수 μžˆμŠ΅λ‹ˆλ‹€. 이름 μžˆλŠ” νŒŒμ΄ν”„ κ΄€λ ¨ λͺ…λ Ήκ³Ό ν•¨μˆ˜λŠ” μ•„λž˜ ν‘œμ™€ κ°™μŠ΅λ‹ˆλ‹€.

FIFO 생성 λͺ…λ Ή: mknod name p mkfifo [-m mode] path...
FIFO 생성 ν•¨μˆ˜: int mknod(const char *path, mode_t mode, dev_t dev); int mkfifo(const char *path, mode_t mode);


01. 이름 μ—†λŠ” νŒŒμ΄ν”„

νŒŒμ΄ν”„λŠ” 두 ν”„λ‘œμ„ΈμŠ€ 간에 톡신을 ν•  수 μžˆλ„λ‘ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€. 아무 μˆ˜μ‹μ–΄ 없이 κ·Έλƒ₯ νŒŒμ΄ν”„λΌκ³  ν•˜λ©΄ 일반적으둜 이름 μ—†λŠ” νŒŒμ΄ν”„(읡λͺ… νŒŒμ΄ν”„:anonymous pipe)λ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€. 이름 μ—†λŠ” νŒŒμ΄ν”„λŠ” λΆ€λͺ¨-μžμ‹ ν”„λ‘œμ„ΈμŠ€ 간에 톡신을 ν•  수 있게 ν•΄μ€λ‹ˆλ‹€. λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œ fork ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•˜κ³ , λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ™€ μžμ‹ ν”„λ‘œμ„ΈμŠ€ 간에 ν†΅μ‹ ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

νŒŒμ΄ν”„λŠ” 기본적으둜 단방ν–₯μž…λ‹ˆλ‹€. λ”°λΌμ„œ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ 좜λ ₯ν•œ λ‚΄μš©μ„ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—μ„œ 읽을 것인지, μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ 좜λ ₯ν•œ λ‚΄μš©μ„ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œ 읽을 것인지 λ‘˜ 쀑 ν•œ λ°©ν–₯을 선택해야 ν•©λ‹ˆλ‹€. μ΄λŠ” μˆ˜λ„κ΄€μ— 물을 보낼 λ•Œ μ–‘μͺ½μ—μ„œ μ„œλ‘œ 보낼 수 μ—†λŠ” 것과 같은 μ΄μΉ˜μž…λ‹ˆλ‹€. 이 μ ˆμ—μ„œλŠ” νŒŒμ΄ν”„ κ΄€λ ¨ ν•¨μˆ˜μΈ popen, pclose, pipe ν•¨μˆ˜λ₯Ό μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

κ°„λ‹¨ν•œ νŒŒμ΄ν”„ 생성

νŒŒμ΄ν”„λ₯Ό λ§Œλ“œλŠ” κ°€μž₯ κ°„λ‹¨ν•œ 방법은 popen ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. μ‚¬μš©μ„ 마친 νŒŒμ΄ν”„λŠ” pclose ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄ λ‹«μŠ΅λ‹ˆλ‹€.

νŒŒμ΄ν”„ 생성: pipen(3)

#include <stdio.h>

FILE *popen(const char *command, const char *mode);

popen ν•¨μˆ˜λŠ” λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€μ™€ ν†΅μ‹ ν•˜κΈ° μœ„ν•΄ νŒŒμ΄ν”„λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. 첫번째 인자인 commandμ—λŠ” μ‰˜ λͺ…령을, λ‘λ²ˆμ§Έ 인자인 modeμ—λŠ” "r"μ΄λ‚˜ "w"λ₯Ό μ§€μ •ν•©λ‹ˆλ‹€. "r"은 νŒŒμ΄ν”„λ₯Ό 읽기 μ „μš©μœΌλ‘œ, "w"λŠ” μ“°κΈ° μ „μš©μœΌλ‘œ μ—½λ‹ˆλ‹€. popen ν•¨μˆ˜λŠ” λ‚΄λΆ€μ μœΌλ‘œ fork ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό λ§Œλ“€κ³  commandμ—μ„œ μ§€μ •ν•œ λͺ…령을 exec ν•¨μˆ˜λ‘œ μ‹€ν–‰ν•΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μˆ˜ν–‰ν•˜λ„λ‘ ν•©λ‹ˆλ‹€. μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ μ‹€ν–‰ν•˜λŠ” exec ν•¨μˆ˜λŠ” λ‹€μŒκ³Ό 같은 ν˜•νƒœκ°€ λ©λ‹ˆλ‹€.

execl("/usr/bin/sh", "sh", "-c", command, (char *)0);

popen ν•¨μˆ˜λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ νŒŒμ΄ν”„λ₯Ό λ§Œλ“€κ³  mode의 값에 따라 ν‘œμ€€ μž…μΆœλ ₯을 μ—°κ²°ν•©λ‹ˆλ‹€. 리턴값은 파일 ν¬μΈν„°μž…λ‹ˆλ‹€. 파일 μž…μΆœλ ₯ ν•¨μˆ˜μ—μ„œ 이 파일 포인터λ₯Ό μ‚¬μš©ν•˜λ©΄ νŒŒμ΄ν”„λ₯Ό μ½κ±°λ‚˜ μ“Έ 수 μžˆμŠ΅λ‹ˆλ‹€. popen ν•¨μˆ˜λŠ” νŒŒμ΄ν”„ 생성에 μ‹€νŒ¨ν•˜λ©΄ 널 포인터λ₯Ό λ¦¬ν„΄ν•©λ‹ˆλ‹€.

νŒŒμ΄ν”„ λ‹«κΈ°: pclose(3)

#include <stdio.h>

int pclose(FILE *stream);

pclose ν•¨μˆ˜λŠ” 파일 μž…μΆœλ ₯ ν•¨μˆ˜μ²˜λŸΌ 인자둜 μ§€μ •ν•œ νŒŒμ΄ν”„λ₯Ό λ‹«μŠ΅λ‹ˆλ‹€. pclose ν•¨μˆ˜λŠ” κ΄€λ ¨λœ waitpid ν•¨μˆ˜λ₯Ό μˆ˜ν–‰ν•˜λ©° μžμ‹ ν”„λ‘œμ„ΈμŠ€λ“€μ΄ μ’…λ£Œν•˜κΈ°λ₯Ό κΈ°λ‹€λ Έλ‹€κ°€ λ¦¬ν„΄ν•©λ‹ˆλ‹€. pclose ν•¨μˆ˜μ˜ 리턴값은 μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œ μƒνƒœμž…λ‹ˆλ‹€. 이 ν•¨μˆ˜λŠ” νŒŒμ΄ν”„λ₯Ό λ‹«λŠ”λ° μ‹€νŒ¨ν•˜λ©΄ -1을 λ¦¬ν„΄ν•©λ‹ˆλ‹€.

popen ν•¨μˆ˜(μ“°κΈ° μ „μš© λͺ¨λ“œ)λ₯Ό μ‚¬μš©ν•΄ νŒŒμ΄ν”„λ₯Ό μƒμ„±ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

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

int main(void) {
    FILE *fp;
    int a;

    fp = popen("wc -l", "w");
    if(fp == NULL) {
        fprintf(stderr, "popen failed\n");
        exit(1);
    }

    for(a=0; a<100; a++)
        fprintf(fp, "test line\n");

    pclose(fp);

    return 0;
}

μ΄λ²ˆμ—λŠ” popen ν•¨μˆ˜(읽기 μ „μš© λͺ¨λ“œ)λ₯Ό μ‚¬μš©ν•΄ νŒŒμ΄ν”„λ₯Ό μƒμ„±ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€. μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ νŒŒμ΄ν”„μ— κΈ°λ‘ν•œ 데이터λ₯Ό λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ μ½μ–΄μ„œ μ²˜λ¦¬ν•˜κ² μŠ΅λ‹ˆλ‹€.

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

int main(void) {
    FILE *fp;
    char buf[256];

    fp = popen("date", "r"); // μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—μ„œλŠ” date λͺ…령을 μˆ˜ν–‰.
    if(fp == NULL) {
        fprintf(stderr, "popen failed\n");
        exit(1);
    }
    // λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œλŠ” 14ν–‰μ—μ„œ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ κΈ°λ‘ν•œ 데이터λ₯Ό 읽고
    // μ €μž₯ν•΄  20ν–‰μ—μ„œ 좜λ ₯ν•œλ‹€.
    if(fgets(buf, sizeof(buf), fp) == NULL) {
        fprintf(stderr, "No data from pipe!\n");
        exit(1);
    }

    printf("line : %s\n", buf);
    pclose(fp);

    return 0;
}

λ³΅μž‘ν•œ νŒŒμ΄ν”„ 생성

SYSTEM CALL: pipe();

PROTOTYPE: int pipe(int fd[2]);
  RETURNS: μ„±κ³΅μ‹œ 0
           -1 on error: errno = EMFILE (자유둜운 μ‹λ³„μžκ°€ μ—†λ‹€)
                                EMFILE (μ‹œμŠ€ν…œ 파일 ν…Œμ΄λΈ”μ΄ λ‹€ μ°Όλ‹€)
                                EFAULT (fd 배열이 μœ νš¨ν•˜μ§€ μ•Šλ‹€)
NOTES: fd[0]λŠ” 읽기λ₯Ό μœ„ν•΄ μ€€λΉ„λ˜κ³ , fd[1]은 μ“°κΈ°λ₯Ό μœ„ν•΄ μ€€λΉ„λœλ‹€.

popen ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄ νŒŒμ΄ν”„λ₯Ό μƒμ„±ν•˜λŠ” 일은 κ°„λ‹¨ν•˜μ§€λ§Œ, μ‰˜μ„ μ‹€ν–‰ν•΄μ•Ό ν•˜λ―€λ‘œ λΉ„νš¨μœ¨μ μ΄κ³  주고받을 수 μžˆλŠ” 데이터도 μ œν•œμ μž…λ‹ˆλ‹€. popen ν•¨μˆ˜ λŒ€μ‹ μ— pipe ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λ©΄ 과정이 μ•½κ°„ λ³΅μž‘ν•΄μ§€μ§€λ§Œ νŒŒμ΄ν”„λ₯Ό μ’€ 더 효율적으둜 생성할 수 μžˆμŠ΅λ‹ˆλ‹€.

νŒŒμ΄ν”„ λ§Œλ“€κΈ°: pipe(2)

#include <unistd.h>

int pipe(int fildes[2]);

pipe ν•¨μˆ˜λŠ” 인자둜 크기가 2인 μ •μˆ˜ν˜• 배열을 λ°›μŠ΅λ‹ˆλ‹€. pipe ν•¨μˆ˜λŠ” 이 배열에 파일 기술자 2개λ₯Ό μ €μž₯ν•©λ‹ˆλ‹€. fildes[0]은 읽기 μ „μš©μœΌλ‘œ μ—΄κ³ , fildes[1]은 μ“°κΈ° μ „μš©μœΌλ‘œ μ—½λ‹ˆλ‹€. pipe ν•¨μˆ˜λŠ” νŒŒμ΄ν”„λ₯Ό μƒμ„±ν•˜λŠ” 데 μ„±κ³΅ν•˜λ©΄ 0을, μ‹€νŒ¨ν•˜λ©΄ -1을 λ¦¬ν„΄ν•©λ‹ˆλ‹€.

pipe ν•¨μˆ˜λ‘œ ν†΅μ‹ ν•˜λŠ” κ³Όμ •

μ—¬κΈ°μ„œλŠ” pipe ν•¨μˆ˜λ‘œ μƒμ„±ν•œ νŒŒμ΄ν”„λ‘œ ν†΅μ‹ ν•˜λŠ” 과정을 μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€. νŒŒμ΄ν”„λ₯Ό μƒμ„±ν•˜κ³ λ‚˜λ©΄ 일반적으둜 fork ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ pipe ν•¨μˆ˜λ‘œ μƒμ„±ν•œ 파일 κΈ°μˆ μžλ“€λ„ λ³΅μ‚¬ν•©λ‹ˆλ‹€. 이 νŒŒμ΄ν”„λ₯Ό μ΄μš©ν•΄ ν•œ ν”„λ‘œμ„ΈμŠ€μ—μ„œλŠ” μ“°κΈ°λ₯Ό μˆ˜ν–‰ν•˜κ³ , λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€μ—μ„œλŠ” 읽기λ₯Ό μˆ˜ν–‰ν•˜λ©΄ 톡신이 λ˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 이 과정을 λ‹¨κ³„μ μœΌλ‘œ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

β“› pipe ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•΄ νŒŒμ΄ν”„μ— μ‚¬μš©ν•  파일 기술자λ₯Ό μ–»λŠ”λ‹€. νŒŒμ΄ν”„λ„ 파일의 μΌμ’…μ΄λ―€λ‘œ 파일(νŒŒμ΄ν”„)을 읽고 μ“Έ 수 μžˆλŠ” 파일 κΈ°μˆ μžκ°€ ν•„μš”ν•œλ°, 이λ₯Ό pipe ν•¨μˆ˜κ°€ μƒμ„±ν•΄μ£ΌλŠ” 것이닀. μ•„λž˜ κ·Έλ¦Όκ³Ό 같이 ν”„λ‘œμ„ΈμŠ€μ— fd[0]κ³Ό fd[1]이 μƒμ„±λœλ‹€.

β‘‘ fork ν•¨μˆ˜λ₯Ό μˆ˜ν–‰ν•΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•œλ‹€. μ΄λ•Œ pipe ν•¨μˆ˜μ—μ„œ μƒμ„±ν•œ 파일 κΈ°μˆ μžλ„ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ‘œ λ³΅μ‚¬λœλ‹€. μ•„λž˜μ—μ„œ λ³΄λŠ” κ²ƒμ²˜λŸΌ 같은 파일 기술자λ₯Ό λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ™€ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ λͺ¨λ‘ 가지고 있게 λ˜λŠ” 것이닀.

β‘’ νŒŒμ΄ν”„λŠ” 단방ν–₯ ν†΅μ‹ μ΄λ―€λ‘œ 톡신 λ°©ν–₯을 κ²°μ •ν•œλ‹€. 예λ₯Ό λ“€μ–΄, λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” μ“°κΈ°λ₯Ό ν•˜κ³  μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” 읽기λ₯Ό ν•œλ‹€κ³  κ°€μ •ν•˜μž. 그러면 μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” 읽기만 ν•  κ²ƒμ΄λ―€λ‘œ μ“°κΈ°μš© 파일 기술자인 fd[1]을 λ‹«λŠ”λ‹€. λ°˜λŒ€λ‘œ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” μ“°κΈ°λ§Œ ν•  κ²ƒμ΄λ―€λ‘œ 읽기용 파일 기술자인 fd[0]을 λ‹«λŠλ‹€. μ•„λž˜μ™€ 같이 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ‘œ 톡신할 수 μžˆλ„λ‘ 파일 κΈ°μˆ μžλ“€μ΄ μ •λ¦¬λ˜μ—ˆλ‹€. 이제 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ fd[1]에 μ“΄ λ‚΄μš©μ„ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ fd[0]μ—μ„œ 읽으면 λœλ‹€.

λ§Œμ•½ νŒŒμ΄ν”„μ˜ μ“°κΈ° 뢀뢄이 λ‹«ν˜€ μžˆλ‹€λ©΄ νŒŒμ΄ν”„μ—μ„œ 읽으렀고 ν• λ•Œ 0μ΄λ‚˜ EOFκ°€ λ¦¬ν„΄λ©λ‹ˆλ‹€. νŒŒμ΄ν”„μ˜ 읽기 뢀뢄이 λ‹«ν˜€ μžˆλ‹€λ©΄ νŒŒμ΄ν”„μ— μ“°λ €κ³  ν•  λ•Œ SIGPIPE μ‹œκ·Έλ„μ΄ λ°œμƒν•©λ‹ˆλ‹€.

νŒŒμ΄ν”„λ₯Ό μƒμ„±ν•œ ν›„ fork ν•¨μˆ˜λ‘œ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό 생성해 νŒŒμ΄ν”„λ‘œ λΆ€λͺ¨-μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό μ—°κ²°ν•˜κ³ , λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ νŒŒμ΄ν”„μ— 좜λ ₯ν•œ λ¬Έμžμ—΄μ„ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ νŒŒμ΄ν”„μ—μ„œ μ½μ–΄λ“€μ΄λŠ” ν”„λ‘œκ·Έλž¨μ„ λ§Œλ“€μ–΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main(void) {
    int fd[2];
    pid_t pid;
    char buf[257];
    int len, status;

    if(pipe(fd) == -1) { // pipe ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄ νŒŒμ΄ν”„λ₯Ό μƒμ„±ν•œλ‹€. pipe ν•¨μˆ˜μ˜ μΈμžλ‘œλŠ” 파일 기술자λ₯Ό μ €μž₯ν•  배열을 μ§€μ •ν•œλ‹€.
        perror("pipe");
        exit(1);
    }

    switch(pid = fork()) { // fork ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•œλ‹€.
        case -1:
            perror("fork");
            exit(1);
            break;
        // μžμ‹ ν”„λ‘œμ„ΈμŠ€μ˜ λ™μž‘ 뢀뢄이닀. 24ν–‰μ—μ„œ fd[1]을 λ‹«λŠ”λ‹€. μ΄λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—μ„œ
        // νŒŒμ΄ν”„λ₯Ό 읽기용으둜 μ‚¬μš©ν•˜κ² λ‹€λŠ” μ˜λ―Έλ‹€. 27ν–‰μ—μ„œ νŒŒμ΄ν”„μ˜ μž…λ ₯ 뢀뢄인 fd[0]μ—μ„œ
        // λ¬Έμžμ—΄μ„ 읽어듀인닀.
        case 0: /* child */
            close(fd[1]);
            write(1, "Child Process:", 15);
            len = read(fd[0], buf, 256);
            write(1, buf, len);
            close(fd[0]);
            break;
        // λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ λ™μž‘ 뢀뢄이닀. 34ν–‰μ—μ„œ fd[0]을 λ‹«λŠ”λ‹€. μ΄λŠ” νŒŒμ΄ν”„λ₯Ό
        // 좜λ ₯용으둜 μ‚¬μš©ν•˜κ² λ‹€λŠ” μ˜λ―Έλ‹€. 37ν–‰μ—μ„œ fd[1]둜 λ¬Έμžμ—΄μ„ 좜λ ₯ν•œλ‹€.
        default:
            close(fd[0]);
            buf[0] = '\0';
            write(fd[1], "Test Message\n", 14);
            close(fd[1]);
            waitpid(pid, &status, 0);
            break;
    }

    return 0;
}

μ΄λ²ˆμ—λŠ” μ‰˜μ—μ„œ 많이 μ‚¬μš©ν•˜λŠ” λͺ…λ Ή ν˜•νƒœμΈ ps -ef | grep telnet의 λ™μž‘μ„ κ΅¬ν˜„ν•΄λ³΄λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€.

#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main(void) {
    int fd[2];
    pid_t pid;

    if(pipe(fd) == -1) {  // νŒŒμ΄ν”„λ₯Ό μƒμ„±ν•œλ‹€.
        perror("pipe");
        exit(1);
    }

    // fork ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•œλ‹€. pas λͺ…λ Ήμ˜ κ²°κ³ΌλŠ”
    // 기본으둜 ν‘œμ€€ 좜λ ₯으둜 좜λ ₯되고, grep λͺ…령은 ν‘œμ€€ μž…λ ₯을 톡해
    // μž…λ ₯λ°›λŠ”λ‹€. λ”°λΌμ„œ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ™€ μžμ‹ ν”„λ‘œμ„ΈμŠ€ κ°„μ˜ 톡신이
    // ν‘œμ€€ μž…μΆœλ ₯ λŒ€μ‹  νŒŒμ΄ν”„λ₯Ό 톡해 이루어지도둝 λ§Œλ“€μ–΄μ•Ό ν•œλ‹€.
    switch(pid = fork()) {
        case -1:
            perror("fork");
            exit(1);
            break;
        case 0: /* child */
            // μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ ν•΄μ•Ό ν•  일은 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€κ°€ νŒŒμ΄ν”„λ‘œ 좜λ ₯ν•˜λŠ”
            // ps -ef λͺ…λ Ήμ˜ κ²°κ³Όλ₯Ό λ°›μ•„ grep telnet λͺ…령을 μˆ˜ν–‰ν•˜λŠ” 것이닀.
            // λ”°λΌμ„œ νŒŒμ΄ν”„μ˜ 좜λ ₯ 뢀뢄이 ν•„μš”μ—†μœΌλ―€λ‘œ fd[1]을 λ‹«λŠ”λ‹€.
            close(fd[1]); // 읽기용으둜 μ‚¬μš©
            // fd[0]의 값이 0이 μ•„λ‹ˆλ©΄, 즉 ν‘œμ€€ μž…λ ₯이 μ•„λ‹ˆλ©΄ fd[0]의 값을
            // ν‘œμ€€ μž…λ ₯으둜 볡사 ν•œ ν›„ fd[0]을 λ‹«λŠλ‹€. 이제 μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—μ„œλŠ”
            // ν‘œμ€€ μž…λ ₯을 fd[0]이 κ°€λ¦¬ν‚€λŠ” νŒŒμ΄ν”„μ—μ„œ μ½λŠ”λ‹€.
            if(fd[0] != 0) {
                dup2(fd[0], 0);
                close(fd[0]);
            }
            // μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ grep λͺ…령을 exec ν•¨μˆ˜λ‘œ ν˜ΈμΆœν•œλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ grep λͺ…령은
            // ν‘œμ€€ μž…λ ₯을 톡해 데이터λ₯Ό 읽어듀이렀 ν•œλ‹€. 이미 μœ„μͺ½μ— ν‘œμ€€ μž…λ ₯으둜 νŒŒμ΄ν”„μ˜
            // μž…λ ₯ 파일 기술자λ₯Ό λ³΅μ‚¬ν–ˆμœΌλ―€λ‘œ 결과적으둜 νŒŒμ΄ν”„λ₯Ό 톡해 데이터λ₯Ό 읽어듀인닀.
            execlp("grep", "grep", "telnet", (char *)NULL);
            exit(1);
            break;
        default:
            // λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ λ™μž‘μ„ μ‚΄νŽ΄λ³΄λ©΄ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ 크게 λ‹€λ₯Ό 것이 μ—†μŒμ„ μ•Œ 수 μžˆλ‹€.
            // μš°μ„  νŒŒμ΄ν”„μ˜ μž…λ ₯ 뢀뢄이 ν•„μš” μ—†μœΌλ―€λ‘œ λ‹«λŠλ‹€.
            close(fd[0]);
            // νŒŒμ΄ν”„μ˜ 좜λ ₯ 뢀뢄을 ν‘œμ€€ 좜λ ₯으둜 λ³΅μ‚¬ν•œλ‹€. λ”°λΌμ„œ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œ
            // 무언가λ₯Ό 좜λ ₯ν•˜λ©΄, νŒŒμ΄ν”„λ₯Ό 톡해 좜λ ₯λœλ‹€.
            if(fd[1] != 1) {
                dup2(fd[1], 1);
                close(fd[1]);
            }
            // exec ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄ ps -ef λͺ…령을 μ‹€ν–‰ν•œλ‹€. ps -ef의 λͺ…령은 기본으둜 ν‘œμ€€ 좜λ ₯으둜
            // 좜λ ₯ν•˜λ―€λ‘œ κ²°κ³Όκ°€ νŒŒμ΄ν”„λ‘œ 좜λ ₯λœλ‹€. 이 좜λ ₯ κ²°κ³Όλ₯Ό μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ 읽어 듀인닀.
            execlp("ps", "ps", "-ef", (char *)NULL);
            wait(NULL);
            break;
    }

    return 0;
}

μ–‘λ°©ν–₯ νŒŒμ΄ν”„μ˜ ν™œμš©

νŒŒμ΄ν”„λŠ” 기본적으둜 단방ν–₯ 톡신을 μˆ˜ν–‰ν•œλ‹€κ³  ν–ˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ νŒŒμ΄ν”„λ₯Ό μ΄μš©ν•΄ μ–‘λ°©ν–₯ 톡신을 ν•˜λ €λ©΄ νŒŒμ΄ν”„λ₯Ό 두 개 μƒμ„±ν•˜λ©΄ λ©λ‹ˆλ‹€. μƒμˆ˜λ„μ™€ ν•˜μˆ˜λ„κ°€ 각각 λ³„λ„μ˜ νŒŒμ΄ν”„λ‘œ κ΅¬μ„±λ˜μ–΄ μžˆλŠ” 것과 같은 μ΄μΉ˜μž…λ‹ˆλ‹€. 예제λ₯Ό 톡해 μ–‘λ°©ν–₯ νŒŒμ΄ν”„λ₯Ό ν™œμš©ν•˜λŠ” 방법을 μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.

λ‹€μŒμ€ νŒŒμ΄ν”„ λ‘κ°œλ₯Ό 생성해 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ™€ μžμ‹ ν”„λ‘œμ„ΈμŠ€ 간에 μ–‘λ°©ν–₯ 톡신을 μˆ˜ν–‰ν•˜λŠ” μ˜ˆμ œμž…λ‹ˆλ‹€.

#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(void) {
    int fd1[2], fd2[2];
    pid_t pid;
    char buf[257];
    int len, status;

    // νŒŒμ΄ν”„λ₯Ό ν•˜λ‚˜ μƒμ„±ν•œλ‹€. μƒμ„±λœ 파일 기술자 fd1은 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œ
    // μžμ‹ ν”„λ‘œμ„ΈμŠ€λ‘œ 데이터λ₯Ό λ³΄λ‚Όλ•Œ μ‚¬μš©ν•œλ‹€.
    if(pipe(fd1) == -1) {
        perror("pipe");
        exit(1);
    }

    // 또 λ‹€λ₯Έ νŒŒμ΄ν”„λ₯Ό μƒμ„±ν•œλ‹€. 파일 기술자 fd2λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—μ„œ
    // λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λ‘œ 데이터λ₯Ό λ³΄λ‚Όλ•Œ μ‚¬μš©ν•œλ‹€.
    if(pipe(fd2) == -1) {
        perror("pipe");
        exit(1);
    }

    switch(pid = fork()) {
        case -1:
            perror("fork");
            exit(1);
            break;
        // μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ—μ„œ μ˜€λŠ” 데이터λ₯Ό μ½λŠ” 데 μ‚¬μš©ν• 
        // fd1[0]을 남겨두고 fd1[1]을 λ‹«λŠλ‹€. λ˜ν•œ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λ‘œ 데이터λ₯Ό λ³΄λ‚΄λŠ”λ°
        // μ‚¬μš©ν•  fd2[1]을 남겨두고 fd2[0]을 λ‹«λŠλ‹€.
        case 0: /* child */
            close(fd1[1]);
            close(fd2[0]);
            write(1, "Child Process:", 15);
            len = read(fd1[0], buf, 256); // λΆ€λͺ¨ν”„λ‘œμ„ΈμŠ€λ‘œ λΆ€ν„° μ½μ–΄μ˜¨λ‹€.
            write(1, buf, len);
            strcpy(buf, "Good\n");
            write(fd2[1], buf, strlen(buf)); //μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ λΆ€λͺ¨μ—κ²Œ
            break;
        // λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” μžμ‹ ν”„λ‘œμ„ΈμŠ€μ™€ λ°˜λŒ€λ‹€. μžμ‹ ν”„λ‘œμ„ΈμŠ€μ— 데이터λ₯Ό λ³΄λ‚΄λŠ”λ° μ‚¬μš©ν•  fd[1]을
        // 남겨두고, μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—μ„œ μ˜€λŠ” 데이터λ₯Ό μ½λŠ” 데 μ‚¬μš©ν•  fd2[0]을 남겨둔닀.
        default:
            close(fd1[0]);
            close(fd2[1]);
            buf[0] = '\0';
            write(fd1[1], "Hello\n", 6); // λΆ€λͺ¨ν”„λ‘œμ„ΈμŠ€κ°€ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ—κ²Œ
            sleep(2);
            write(1, "Parent Process:", 15);
            len = read(fd2[0], buf, 256); //μžμ‹ν”„λ‘œμ„ΈμŠ€λ‘œλΆ€ν„° μ½μ–΄μ˜¨λ‹€.
            write(1, buf, len);
            waitpid(pid, &status, 0);
            break;
    }

    return 0;
}
⚠️ **GitHub.com Fallback** ⚠️