
23.08.06 최초 작성
23.11.15 예제 추가
popen : 이미 있는 파이프를 사용 (성능 및 보안문제 있음)#include <stdio.h>
FILE *popen(const char * command, const char *mode);
///
command : 쉘 명령
mode : 'r' 또는 'w'
Return : 파일 포인터
(NULL : Fail)
pclose : 이미 있는 파이프를 닫음#include <stdio.h>
int pclose(FILE *stream);// 관련된 waitpid 함수를 수행해 자식 프로세스들이 종료되기 기다렸다가 리턴한다.
///
stream : 닫을 파이프의 주소
Return : 자식 프로세스의 exit status
(-1 : FaiL)
pipe : 파이프를 생성하는 함수#include <unistd.h>
int pipe(int fildes[2]);
///
fildes : 파이프로 사용할 file descriptor 2개
(fildes[0] : 읽기 전용, fildes[1] : 쓰기 전용)
Return
(0 : Success, -1 : Fail)
simple_pipe.c : 부모 프로세스가 데이터를 파이프로 전달하고 자식 프로세스는 파이프에 있는 데이터을 읽어 모니터에 출력하는 코드#include <sys/wait.h>
#include "tlpi_hdr.h"
#define BUF_SIZE 10
int
main(int argc, char *argv[])
{
int pfd[2]; /* Pipe file descriptors */
char buf[BUF_SIZE];
ssize_t numRead;
if (argc != 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s string\n", argv[0]);
if (pipe(pfd) == -1) /* 파이프 생성 */
errExit("pipe");
switch (fork()) {
case -1:
errExit("fork");
case 0: /* 자식 프로세스인 경우 */
if (close(pfd[1]) == -1) /* Write end is unused */
errExit("close - child");
for (;;) { /* 파이프(pfd[0])에서 데이터를 읽음 */
numRead = read(pfd[0], buf, BUF_SIZE);
if (numRead == -1)
errExit("read");
if (numRead == 0)
break; /* EOF를 읽을 경우 종료 */
if (write(STDOUT_FILENO, buf, numRead) != numRead)
fatal("child - partial/failed write");
}
write(STDOUT_FILENO, "\n", 1); /*stdout(모니터)로 출력 */
if (close(pfd[0]) == -1)
errExit("close");
exit(EXIT_SUCCESS);
default: /* 부모 프로세스인 경우 */
if (close(pfd[0]) == -1)
errExit("close - parent");
/*파이프(pfd[1])에 데이터를 씀*/
if (write(pfd[1], argv[1], strlen(argv[1])) != strlen(argv[1]))
fatal("parent - partial/failed write");
if (close(pfd[1]) == -1) /* 자식 프로세스가 EOF 읽은 경우 */
errExit("close");
wait(NULL);
exit(EXIT_SUCCESS);
}
}
popen_glob : 패턴(키워드)을 입력해 이와 일치하는 이름을 가진 파일 찾음#include <ctype.h>
#include <limits.h>
#include "print_wait_status.h" /* For printWaitStatus() */
#include "tlpi_hdr.h"
#define POPEN_FMT "/bin/ls -d %s 2> /dev/null"
#define PAT_SIZE 50
#define PCMD_BUF_SIZE (sizeof(POPEN_FMT) + PAT_SIZE)
int
main(int argc, char *argv[])
{
char pat[PAT_SIZE]; /* 패턴을 저장할 공간 */
char popenCmd[PCMD_BUF_SIZE];
FILE *fp; /* popen()함수의 return 값을 저장할 공간 */
Boolean badPattern; /* 입력받은 패턴을 검사한 결과를 저장 */
int len, status, fileCnt, j;
char pathname[PATH_MAX];
for (;;) { /* Read pattern, display results of globbing */
printf("pattern: ");
fflush(stdout);
if (fgets(pat, PAT_SIZE, stdin) == NULL)
break; /* EOF */
len = strlen(pat);
if (len <= 1) /* 입력 없음 */
continue;
if (pat[len - 1] == '\n') /* Enter 입력 시 문장의 끝으로 치환 */
pat[len - 1] = '\0';
/* 문자열 검사 */
for (j = 0, badPattern = FALSE; j < len && !badPattern; j++)
if (!isalnum((unsigned char) pat[j]) &&
strchr("_*?[^-].", pat[j]) == NULL)
badPattern = TRUE;
if (badPattern) {
printf("Bad pattern character: %c\n", pat[j - 1]);
continue;
}
snprintf(popenCmd, PCMD_BUF_SIZE, POPEN_FMT, pat);
fp = popen(popenCmd, "r");
if (fp == NULL) {
printf("popen() failed\n");
continue;
}
fileCnt = 0;
while (fgets(pathname, PATH_MAX, fp) != NULL) {
printf("%s", pathname);
fileCnt++;
}
/* 파이프 종료 */
status = pclose(fp);
printf(" %d matching file%s\n", fileCnt, (fileCnt != 1) ? "s" : "");
printf(" pclose() status = %#x\n", (unsigned int) status);
if (status != -1)
printWaitStatus("\t", status);
}
exit(EXIT_SUCCESS);
}
이름이 있는 파이프(특수파일의 한 종류). 독립적인 프로세스 사이의 통신을 위해 사용하며 미리 만들워 두어야 사용 가능하다(kernel 내부적으로 데이터 전달).
mkfifo : FIFO 관련된 파일을 생성함#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
///
pathname : FIFO파일을 생성 할 경로
mode : 접근 권한 지정
mkfifo pipeFile
Terminal 1
ls | tee pipeFile | sort -k5n //tee : 파이프에도 쓰고 이후 작업에도 씀
Terminal 2
wc -m < pipeFile
Terminal 1 : write 모드로 파이프를 연다.Terminal 2 : read 모드로 파이프를 연다.