[42SEOUL] pipex : 사전 학습

[42SEOUL] pipex : 사전 학습

이미 잘 알고 있는 UNIX 매커니즘을 더 자세히 알아가는 프로젝트

Redirection : [<] [>]

입출력의 방향을 바꾸는 명령어

유닉스 프로그램은 기본적으로 표준 입력 (stdin), 표준 출력 (stdout) 채널을 갖고 있음. → 프로그램을 사용할 때 사용자가 터미널에 직접 정보를 입력하는 채널이 표준 입력이며, 실행 결과 등이 터미널에 출력되는 채널이 표준 출력임.

(백그라운드에서 실행되는 데몬 같은 경우 제외) 대부분의 유닉스 프로세스는 실행될 때 표준 입출력에 대한 파일 서술자(file descriptor, fd)를 할당함. 각각 0과 1이며, unistd.h 에 STDIN_FILENO , STDOUT_FILENO 매크로로 정의되어 있음.

0 표준입력 (stdin [keyboard]) 1 표준출력 (stdout [screen]) 2 표준에러 (stderr [screen])

표준 입출력과 입력 파일, 출력 파일이 모두 고유의 파일 서술자를 갖고 있다는 점을 생각해보면, 이는 각 fd 사이의 데이터 흐름의 방향을 변경/지정해주는 기능이라고 할 수 있음.

사용법

< : 지정된 파일의 내용을 표준 입력으로 넘겨줌.

> : 위와 반대로 표준 출력에 전달된 내용을 지정된 파일로 넘겨줌. → 기존 파일이 있을 경우 덮어쓰여짐.

>> : 표준 출력에 전달된 내용을 지정된 파일의 내용에 추가함.

예제

입력 리다이렉션

표준 입력에 내용을 모두 입력하고 나면 ctrl + d 를 입력해 프로세스에 EOF 를 전달해야 함.

~/user $ < file.txt A B C ~/user $ 0< file.txt A B C

출력 리다이렉션

~/user $ hello > file.txt ~/user $ cat file.txt hello ~/user $ echo "hihi Linux" >> file.txt ~/user $ cat file.txt hello hihi Linux ~/user $ echo bye > file.txt ~/user $ cat file.txt bye

에러 출력 리다이렉션

보통 출력을 보고 싶지 않을 때 /dev/null 로 많이 보냄. → 주기적으로 비워지는 공간, 휴지통이라 생각하면 쉬움.

~/user $ fifle bash: fifle: command not found ~/user $ fifle 2> file.txt ~/user $ cat file.txt bash: fifle: command not found

Pipe : [ | ]

여러 프로그램을 묶어주는 명령어

여러개의 명령어를 실행할 때 이전 명령어의 결과를 다음 명령어의 입력값으로 사용하고 싶을 때가 있음. 명령어의 입력 - 실행 - 결과 과정을 파이프 안에 흐르는 액체로 비유한다면, 첫 번째 명령어의 파이프 결과를 화면 출력 대신 다른 명령어 파이프로 흘러가도록 연결한다고 생각하면 됨.

한 번에 사용 가능한 파이프의 개수는 제한이 없음.

이전 명령어의 출력값을 필터링하거나 가공할 때 주로 사용하기 때문에 awk cut grep more 등의 명령어들을 조합해서 많이 사용함.

사용법 / 예제

text.txt 파일에서 abc 라는 글자가 포함된 라인만 출력

~/user $ cat test.txt | grep abc abc abcdef abcd

현재 디렉토리에서 c 라는 글자가 들어간 파일 중 java 가 들어간 파일을 제외하고 출력

~/user $ ls | grep c | grep -v java language.c language.cpp

실행 중인 프로세스 목록에서 bash 프로세스 목록을 출력

~/user $ ps -ef | grep bash root 1293 284 0 Apr18 tty1 00:00:00 -bash

Shell

프로세스를 시작시키는 것이 셀의 주요 기능이며, UNIX 에서 프로세스를 시작하는 방법은 Init fork() 2가지 뿐임.

대부분의 프로그램은 Init 이 아니기 때문에 프로세스를 시작하는 실질적인 방법은 fork() syscall 뿐이라 볼 수 있음.

fork

#include int fork();

fork() 를 호출하는 프로세스는 부모 프로세스가 되며, 이 기능을 호출하면 운영 체제가 부모 프로세스로부터 자식 프로세스를 복제하여 두 프로세스를 병렬로 실행함. 기존 프로세스는 두 개의 분리된 프로세스로 분기됨. 그런 다음 자식 프로세스는 exec() 을 사용하여 자신을 새 프로그램으로 바꿈. 부모 프로세스는 다른 작업을 수행할 수 있으며, wait() 을 사용하여 자식 프로세스를 계속 감시할 수 있음.

모든 프로세스는 생성될 때 프로세스 아이디를 부여받음. → fork() 함수는 부모에게는 자식 프로세스의 pid ( pid_t 정수형) 를 반환하고, 자식에게는 0을 반환함. 이를 이용하여 자식 프로세스에게 특정 명령을 시킬 수 있음.

pipe

#include pipe();

두 프로세스가 생산자-소비자 모델에 따라 통신할 수 있게 해주는 원형 버퍼임. 즉, 한 프로세스가 쓰고 다른 프로세스가 읽는 선입선출 형태의 큐라 할 수 있음.

자식 프로세스는 생성 시점에 부모 프로세스가 사용중인 메모리 영역을 복사해오지만, 그 이후로는 두 프로세스 간에 직접 정보를 교환하는 것이 불가능함. 이 때 프로세스 간 정보 교환 채널이 되어주는 것이 파이프임.

파이프에는 일정한 크기의 공간이 할당되어 있으며, 단방향 데이터 전송 기능을 수행함. 인자로 전달된 배열에는 파이프의 양 끝단을 가리키는 파일 디스크립터가 입력됨. pipefd[0] 과 pipefd[1] 에 입력된 파일 디스크립터가 각각 파이프의 읽기와 쓰기를 위한 채널임.

waitpid

pid_t waitpid(pid_t pid, int *stat_loc, int options);

fork() 함수로 자식 프로세스를 생성하면 부모 프로세스와 자식 프로세스는 순서에 관계 없이 실행되고, 먼저 실행을 마친 프로세스는 종료됨.

이 때 좀비 프로세스 같은 불안정 상태의 프로세스가 발생하는데 이를 방지하려면 프로세스 동기화 함수를 수행해서 부모 프로세스와 자식 프로세스를 동기화 시켜야 함.

동기화 후에 자식 프로세스는 if (pid == 0) 일 경우 구문을 수행한 뒤 종료하며, 부모 프로세스의 경우 wait() 를 통해 자식 프로세스가 종료된 뒤 나머지 구문을 수행하고 종료함.

WIFEXITED

WIFEXITED(status);

exit() 를 호출하기 위한 인자나 return 값이 설정되고 종료된 자식 반환 코드의 최하위 8비트를 평가함.

자식 프로세스가 정상적으로 종료 되었다면 0 을 반환함.

execve

#include int execve(const char *path, char *const argv[], char *const envp[]);

path 가 가리키는 파일을 실행함.

매개변수 const char *path : 실행 파일의 디렉토리 포함 전체 파일의 명 char *const argv[] : 인수 목록

반환값 성공 시, 0 반환 실패 시, -1 반환

open

#include int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);

이미 존재하는 파일을 열거나 새로운 파일을 생성하는 함수임.

정상적으로 열렸으면 0 , 오류가 발생했다면 -1 을 반환함.

flags 옵션 O_RDONLY : 읽기 전용으로 오픈함. O_RDWR : 파일 읽고 쓰기 모두 가능하게 함. O_CREAT : 파일이 존재하지 않으면 새로 생성함. O_TRUNC : O_WRONLY 또는 O_RDWR 로 열 때, 이미 존재하는 파일이면 파일 내용을 삭제하여 파일 크기를 0으로 만듬.

mode 옵션 → 파일에 대한 access 권한을 설정함. chmod 설정을 해준다고 보면 됨.

close

open 으로 열린 파일을 닫음.

dup2

#include int dup2(int fd, int fd2);

fd 의 값을 fd2 로 지정해서 복제하는 함수로, fd2 가 이미 열려있으면 fd2 를 닫은 후 복제가 됨.

성공 시 새 파일 디스크립터를 반환하고, 실패 시 -1 을 반환함.

perror

오류 메시지를 strerr 로 출력함.

exit

프로그램을 종료하는 함수임.

exit(0) 은 정상 종료, exit(1) 은 에러 메시지 종료를 뜻함.

from http://leejiwonn.tistory.com/12 by ccl(A) rewrite - 2021-11-09 20:02:05