2021 06 07(월)
1. 학습 날짜 : 20210607(월)
2. 학습 시간 : 12:00 ~
3. 학습 주제 : pipex 자료조사, 구현방법의 생각
4. 동료 학습 방법 : 동료 1명
5. 학습 목표 :
- pipex 자료조사
- Redirection 설명할 수 있을 때 까지 자료조사, 이해
- Pipe 설명할 수 있을 때 까지 자료조사, 이해
- pipex 구현 방법 생각해보고, Design 해보기 - main 문 중심 Design
6. 학습 내용 :
Redirection - file descriptor 메타문자의 정의
https://www.guru99.com/linux-redirection.html
Redirection is a feature in Linux such that when executing a command, you can change the standard input/output devices. The basic workflow of any Linux command is that it takes an input and give an output.
이 세 개의 표준 스트림은 사용자의 터미널에 부착된다.
3< input.txt
, 4> output.txt
에 관해
3< input.txt:
< input.txt
는 상당히 익숙한데 비해 3 < input.txt
는 익숙치 않다.
3< input.txt
는 어떤 의미를 가질까?
만약, 원래 3번 파일로부터의 입력을 받는 프로그램이 존재한다면 -프로그램x 로 정의, input.txt
로부터의 입력을 받도록 redirection시켜준다.
예) 프로그램x가 표준입력이 아닌 3번 파일로부터의 입력을 받는 프로그램이라면, 3번 파일을 읽지 않고, input.txt라는 파일로 입력을 준다.
프로그램x 3< input.txt
그림 :

4> output.txt :
만약, 원래 어떤 프로그램x가 4번 파일(fd==4)에 출력작업을 한다고 가정하고, 그런 프로그램 x가 존재한다고 했을 때, 4> output.txt
는 fd==4가 아닌 output.txt
에 데이터출력작업을 행한다.
표준입력과 표준출력에 대해
https://www.guru99.com/linux-redirection.html
Whenever you execute a program/command at the terminal, 3 files are always open, viz., standard input, standard output, standard error.
stdin : 별도의 리다이렉션 없이 프로그램을 시작한 경우, 표준 입력 스트림은 키보드에서 받아온다.
표준 입력(Standard input)은 프로그램에 입력되는 데이터의 표준적인 출처(장비나 파일)를 일컬으며 *stdin* 으로 줄여 표현한다.
stdout : 리다이렉션 없이 표준 출력은 프로그램을 시작한 텍스트 터미널이 된다.
표준 출력(Standard output)은 프로그램에서 출력되는 데이터의 표준적인 방향(장비나 파일)을 일컬으며 크게 표준 출력(*stdout*)과 표준 에러(*stderr*)로 구분할 수 있다.
어떤 프로그램에 있어 만약 대부분의 입력과 출력이 한 출처로부터만 발생한다면 사용자가 명시하지 않는 이상 기본적으로 사용할 입력과 출력을 프로그램 개발 시에 지정할 수 있으면 좋을 것이다. 이렇게 한 프로그램이 기본적으로 사용할 입출력 대상을 ‘표준 입출력’이라고 한다.
우리의 예제 프로그램 ‘쉘’은 키보드 입력을 표준 입력으로 하고 모니터 콘솔 출력을 표준 출력으로 한다.
표준 입출력은 사용자가 다른 입출력 매체를 지정하지 않았을 때의 기본 입출력 매체라고 이야기했다
pipe(int fd[2]) 의 순서에 대해
왜 fd[0]이 읽는 stream, fd[1]이 쓰는 stream일까?
https://architectophile.tistory.com/9?category=880956
그리고 여기에서 알아야 할 매우 중요한 개념이 있는데, 나는 이것을 이해하기 위해 위의 다이어그램들을 그려보며 생각해야 했다. 내가 처음에 얘기했던 것처럼 위의 다이어그램들은 데이터가 왼쪽에서 오른쪽으로 흐르는 모델이라는 것을 잘 생각해보자. 파일 디스크립터는 배열 안에서 설정되어 4에 쓰여진 데이터가 3에서 읽히도록 된다. 하지만 당신은 왜 4가 왼쪽으로 가고 3이 오른쪽으로 가는지 궁금해할 수 있다.
여기서 핵심적인 내용은 바로pipe()
호출에 의해 설정되는읽기(read)
,쓰기(write)
액션은 바로 파이프를 사용하는 양쪽의 2개의프로세스
들의 관점에서 정의된다는 것이다. 따라서pipe()
호출에 4를writable end
로 설정하면\, 그것은 첫 번째 명령(sort
)의 프로세스가 출력(output)을쓰기(write)
하는\ 파이프의 입력(input)을 전달받는 파이프의 왼쪽 파일 디스크립터가 되는 것이다. 반대로pipe()
호출에 3을readable end
로 설정하면\, 그것은 두 번째 명령(grep
)의 프로세스가 입력(input)을읽기(read)
하는\ 파이프의 출력(output)을 전달하는 파이프의 오른쪽 파일 디스크립터가 되는 것이다.
해석 : 양쪽 2개의 프로세스의 관점에서 정의된다는 것 == sort | wc
일 때, 파이프는 sort에서 데이터를 읽어들인 후에 wc에 데이터를 write 해야하기 때문에 int fd[2]
의 순서가 fd[0] == read , fd[1] == write의 순서로 저장된다.
dup()와 dup2
dup() : 먼저 dup 함수는 입력 인자로 열려진 파일 디스크립터를 전달하면 같은 물리적 파일을 연 새로운 파일 디스크립터를 반환합니다. 이와 같이 열면 두 개의 파일 디스크립터는 커널의 같은 파일 테이블 엔트리를 참조합니다
dup2() : dup2 함수는 첫 번째 인자로 열려진 파일 디스크립터를 전달하고 두 번째 인자로 파일 디스크립터를 전달하면 첫 번째 인자로 열려진 파일 디스크립터가 참조하는 파일 테이블 엔트리를 두 번째 전달한 파일 디스크립터도 참조합니다. 만약 두 번째 인자로 전달한 파일 디스크립터가 열려진 파일 디스크립터일 때는 먼저 닫고 난 후에 복제합니다.
- dup() 와 dup2()의 차이 :
dup()
: 새로운 fd를 만들어 fd 테이블을 연결dup2()
: fd를 지정하여 새로 참조시킬 수 있고, 기존에 열려있는 fd를 지정하여 연결을 끊게 한 뒤 새롭게 참조시킬 수 있음.
shell command 위치
Shell command 위치가 다르기 때문에 추후 프로그램 작성시 execv()
사용에 문제가 있을 것으로 판단.
~ % which touch
/usr/bin/touch
~ % which wc
/usr/bin/wc
~ % which mkdir
/bin/mkdir
~ % which cp
/bin/cp
~ % which pwd
pwd: shell built-in command
~ % which ps
/bin/ps
~ % which bash
/bin/bash
~ % which zsh
/bin/zsh
External, Internal Command :
https://www.geeksforgeeks.org/internal-and-external-commands-in-linux/
- Internal Commands : Commands which are built into the shell. For all the shell built-in commands, execution of the same is fast in the sense that the shell doesn’t have to search the given path for them in the PATH variable, and also no process needs to be spawned for executing it.
Examples: source, cd, fg, etc.- External Commands : Commands which aren’t built into the shell. When an external command has to be executed, the shell looks for its path given in the PATH variable, and also a new process has to be spawned and the command gets executed. They are usually located in /bin or /usr/bin. For example, when you execute the “cat” command, which usually is at /usr/bin, the executable /usr/bin/cat gets executed.
Examples: ls, cat etc.
~ % which pwd
pwd: shell built-in command
pwd
는 shell 의 내부적으로 구현된 command / 툴이다.
물론, 시스템 명령어 상 존재하기도 한다.
~ % which /bin/pwd
/bin/pwd
Internal Command 의 경우, 명령어가 파일로 존재하지 않는다
External Command의 경우, 파일은 /bin
또는 /usr/bin
에 존재한다.
웬만한 external command들은 아래 디렉토리에 존재한다고 한다.
"/bin/"
"/usr/local/bin/",
"/usr/bin/",
"/usr/sbin/",
"/sbin/",
const char *
와 char * const
의 차이. :
The difference is that
const char *
is a pointer to aconst char
, whilechar * const
is a constant pointer to achar
.The first, the value being pointed to can't be changed but the pointer can be. The second, the value being pointed at can change but the pointer can't (similar to a reference).
const char *
: const가 char 를 수식.
char * const
: const가 ptr를 수식.

FILE TREE
📦pipex
┣ 📂includes
┃ ┗ 📜pipex.h
┣ 📂libft
┣ 📂srcs
┃ ┣ 📜initiate.c
┃ ┣ 📜main.c
┃ ┣ 📜redirection.c
┃ ┗ 📜utils.c
┣ 📜.gitignore
┣ 📜Makefile
┗ 📜README.md
pipex.c의 대략적인 흐름
int main(int argc, char **argv)
{
pid_t pid;
t_parsed *parsed[2];
int execv_error[2];
int status;
/*******************
1. agrument가 5개가 아니면?
2. parsing 구조체 초기화
3. parse 진행
4. file path가 valid한가?
5. command가 valid한가?
********************/
if (!(argc == 5 && init_parsed(parsed) && \
parse_argument_vector(argv, parsed) && is_valid_path(parsed)) && \
is_valid_cmd(parsed))
exit(0);
pid = fork(); //프로세스 분기
if (pid == -1)
return (0);
// child process.
if (pid == 0)
{
if (!(redirect_in() && connect_pipe())) // input redirection, pipe연결.
exit(1);
if (run_cmd(parsed, CHILD_INDEX) == -1)
exit(1);
}
//parent process.
waitpid(pid, &status, 0);
if (WIFEXITED(status)) //비정상 종료시 리소스 환원
exit(0);
if (!(redirect_out() && connect_pipe())) // output redirection, pipe연결.
exit(1);
if (run_cmd(parsed, PARENT_INDEX) == -1)
exit(1);
}
학습에 도움된 사이트 :
오늘 발견한 문제와 해결방안:
- 발견한 문제와 해결방안이 딱히 존재하지 않았다.
7. 학습 총평 :
- 좋았다.
- 단지, 과제를 하는 시간동안은 오로지 과제에 집중해야만 하는 것이 아쉽다.
- 중간에 다른 공부도 껴넣었으면 한다.
8. 다음 학습 계획 :
- pipex 마무리
- pipex 개념 정리 마지막