2021 06 05 (토)
1. 학습 날짜 : 20210605(토)
2. 학습 시간 : 13 : 00 ~
3. 학습 주제 : push_swap 피드백, pipe 프로그램 구현 자료조사
4. 동료 학습 방법 : 동료 1명
5. 학습 목표 :
- Redirection에 대한 조사
- 사용가능 함수들 중 모르는 함수에 대해 조사
◦ open
◦ close
◦ read
◦ write
◦ malloc
◦ waitpid
◦ wait
◦ free
◦ pipe
◦ dup
◦ dup2
◦ execve
◦ fork
◦ perror
◦ strerror
◦ exit
- 프로그램을 어떻게 구현할 지 동료와 의논한다.
- 목표 기한 설정
- 오늘까지 subject 구현 방법 완료.
6. 학습 내용 :
c++ 평가
요구사항 분석
You will put all the common functions in the ClapTrap class, but the specific functions
must remain where they are. In other words, you must make sure that the FragTrap
and ScavTrap classes contain only what isn’t shared between the both of them, and put
everything they both share in the parent class.
construction/destruction chaining
NinjaTrap에 대한 설명
push_swap 피드백
요구사항 분석
Your objective is to code the Pipex program.
Pipex 프로그램이란 무엇인가?
- 만들어야 할 프로그램 이름.
- 정확히 어떤 프로그램인가?
- ..?
pipex는 어떻게 작동해야하는가?
$> ./pipex file1 cmd1 cmd2 file2 #cmd1, #cmd2 : shell명령어.
위의 명령어는
$> < file1 cmd1 | cmd2 > file2
위와 같이 동작해야한다.
예제
$> ./pipex infile ls -l wc -l outfile
은
< infile ls -l | wc -l > outfile
과 같이 동작해야하고
$> ./pipex infile ``grep a1'' ``wc -w'' outfile
는
< infile grep a1 | wc -w >
과 같이 동작해야한다.
⁉️ :
<
,>
는 뭔가?⁉️ : 위의 명령어는 어떤 동작을 하는가?
Redirection :
unix 에서는 data stream 이라는 개념을 이용하여 장치를 추상화 함으로써 프로그래머가 어떤 종류의 장치를 사용하는지 알 필요 없이 동일하게 open, read, write 할 수 있게 하였고 또한 프로그램 실행시 자동으로 입, 출력 장치를 연결하여 많은 부담을 덜 수 있게 하였습니다
stream 은 디스크상의 파일이나 컴퓨터에 연결되는 여러 장치들을 통일된 방식으로 다루기 위한 가상적인 개념입니다.
stream
여러 입/출력 장치를 stream에 연결 하여 stream에서 알아서 데이터를 입출력 장치에 대해 처리.

standard stream 도 각각 /dev/stdin, /dev/stdout, /dev/stderr 에 파일로 존재합니다.

기본 사용법 과 default value
$ cat infile
hello
world
$ wc 0< infile 1> outfile
$ cat outfile
2 2 12
$ wc 0< infile 1> outfile
: wc
0< infile
1> outfile
wc
: shell command. STDIN으로부터 입력을 받을때까지 대기.0<
,1>
: stream fd / number + stream input / stream outputoutfile
: file 인자.
0< infile
: infile을 stdin으로 보내는게 무슨 의미? - wc
와 연관지어 생각해보면 wc
명령어 + infile을 stdin으로 넘겨줌
1> outfile
: 0< infile
을 실행한 뒤, stdout을 redirecting 하여 outfile로 보냄.
n< arg
: arg를 fd n
stream의 입력으로 redirecting
n> arg
: arg를 fd n
stream 의 출력으로 redirecting

요약 : 터미널 한 줄의 명령어 내에서 각 stream에 대한 redirecting이 가능하다.
우리가 쓸 건 stdin, stdout, stderr에 대한 redirecting.
$ wc 0< infile 1> outfile
: stream의 변경 - stdin에 infile, 표준출력의 stream에 있는 데이터를 outfile로 출력.

⚙️<
, >
, >>
기호 좌측값은 공백없이 붙여야합니다. 그렇지 않으면 명령의 인수로 인식이 됩니다.
⚙️>
, >>
기호의 우측값은 파일이름이 올경우는 괜찮지만 FD 번호가 올경우는 &
기호를 붙여줘야 합니다. 그렇지 않으면 FD 숫자가 파일이름이 됩니다.
⁉️ : 이 경우도 처리해주어야하는가?
⁉️ Redirection 의문점 : STDOUT과 STDIN을 가리키는 fd가 바뀌면 STDOUT/STDIN에 어떻게 접근하는가?
shell에 의해, 또는 .c파일 안에서 dup2()
에 의해 Redirecting 된 후, stdin이나 stdout을 가리키는 file descriptor가 사라진다면,
wc 0< infile 1> outfile
이후에는 stdin과 stdout을 사용하지 못하지 않는가...?

싶었는데, shell에 의해 프로세스가 하나 더 생겨서, 해당 프로세스에서 fd를 변경하고, 그 프로세스의 PCB가 변경되는데,
parent process의 PCB의 fd는 원본 그대로이기 때문에 자식프로세스에서 변경한 fd만 영향이 가고, 부모프로세스의 fd에는 영향이 없다.
Redirection 예제
- 3 ----> 1
- 1 ----> outfile
- 1 > &3-
# FD 3 번을 새로 생성하면서 1번에 연결하였습니다.
exec 3>&1 # 그러므로 1번 연결이 3번에 백업된 것과 같습니다.
exec 1> outfile # FD 1 번을 outfile 에 연결해 사용
... # 이후부터는 stdout 출력은 모두 outfile 로 가게됩니다.
...
exec 1>&3- # FD 1 번을 백업해 두었던 3 번에 다시 연결하여 복구하고 3 번은 삭제 (3-)
- 3 ----> &0
- 표준 입력을 infile로 대체.
0 -----> infile. - 0 -----> &3
!/bin/bash
exec 3>&0 # FD 0 번을 사용하기 전에 3 번에 백업
exec 0< infile # infile 을 FD 0 에 입력으로 연결 하므로 화살표 방향이 왼쪽이 됩니다.
# 실제 리소스와의 연결이므로 방향을 올바르게 설정해야 합니다.
# ( 실행하려면 infile 을 준비하세요 )
read var1 # 2 개의 라인을 infile 로부터 읽어들입니다.
read var2
echo read from infile: $var1
echo read from infile: $var2
exec 0>&3- # FD 0 번을 3 번 으로부터 복구하고 3 번은 삭제 (3-)
# FD 0 번을 복구하였으므로 터미널로부터 입력을 받게 됩니다.
read -p "enter your favorite number : " var
echo $var
Redirection 명령어 기호 >
, <
의 뜻 :
File Descriptor 를 설정할 때 사용하는 메타문자란다.
이 메타문자를 사용해서, redirecting
을 하는것.
<
, >
는 redirecting 명령어는 아니다.
FD 를 설정할 때 사용하는 메타문자
- 입력 :
<
- 출력 :
>
( 이 기호를 파일로 연결하면 먼저 기존 파일 내용이 삭제됩니다 )- append :
>>
( 기존 파일 내용이 삭제되지 않고 이후부터 append 됩니다 )- 입, 출력 :
<>
( 이 기호는<
+>
와 같지만 기존 파일 내용이 삭제되지는 않고 출력시 첫라인 부터 overwrite 하게 됩니다. )
>>
의 의미:
기존 fd가 가리키는 file의 뒤에 입력받은 내용을 append
출력이므로 이때 outfile 파일에 내용이 있다면 삭제됩니다. 삭제를 방지하고 append 되게 하려면
>>
을 사용합니다.>
는 데이터를 파일의 처음부터 쓰기 시작하며,>>
는 기존의 내용에 뒤이어서 쓰게 됩니다.
Pipe
- 파이프의 개념과 정의
- chaining 개념/정의
- `파이프라이닝 개념/정의
- Buffered Stream과 파이프
- 파이프의 구현 - user space와 kernel space.
각기 독립적인 역할을 하는 프로그램을 만들어놓고 필요에 따라 선택해서 서로 조합하여 전체를 완성한다
유닉스(Unix)는 단순하지만 매우 가치있는 디자인 철학을 갖고 있는데, 유닉스 파이프(Pipe)의 창시자인 Doug McIlroy
는 다음과 같이 말했다.
“한 가지 일만 아주 잘하는 프로그램들을 작성하라. 프로그램들이 다른 프로그램들과 함께 일할 수 있도록 작성하라. 프로그램들이 텍스트 스트림을 처리할 수 있도록 작성하라. 왜냐하면 그것은 보편적인 인터페이스이기 때문이다.”
원문 :
“Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.”
파이프는 데이터가 한 프로세스에서 다른 프로세스로 전달되도록 하는데, 프로세스의 명령의 출력값들이 스트림에 의해 서로 연결된다.
- Shell 에서 FD 를 pipe 나 socket 에 연결가능하다는 것으로 보아, pipe를 fd에 연결해서 사용하는 것으로 보인다.
- 파이프를 이용해 프롬프트 명령행 상에서 모듈 프로그래밍을 할 수 있습니다.
cat inventory.txt | cut -d ',' -f 3 | grep '^c' | sort
- ⁉️ : 파이프는 IPC (Inter Process Communication) 의 한 방법입니다.
- 파이프를 통해 전달되는 데이터는 단순 byte stream 입니다
파이프 예시

파이프로 연결된 명령은 subshell 에서 실행된다.
아래는 프롬프트 상에서 { echo; sleep 10 ;} | { echo; sleep 10 ;} | { echo; sleep 10 ;}
명령을 실행했을때의 프로세스 상태인데 파이프로 연결된 세 명령 모두 subshell 이 생성된후에 그 아래에서 실행되는것을 볼수있습니다. 그러므로 마지막 명령에서 결과를 어떤변수에 저장한다면 그값은 파이프 실행이 종료되면 사라지게 됩니다.

💡우리 과제에서 fork(), exec()가 필요한 이유
파이프로 연결된 명령들은 순서대로 실행될까?
실행 순서와는 상관없다. (구현상 이유)
파이프의 구현
더욱 구체적으로, 파이프라인의 명령의 실행을 처리하는 코드를 살펴보면, 2개의 정수값을 저장하는 배열(array)이 생성되고,
pipe()
호출은 그 배열에 사용 가능한 2개의 파일 디스크립터 값을(일반적으로 사용가능한 가장 낮은 숫자의 2개의 파일 디스크립터를 사용한다.) 채운다(populate).
pipe() - 2
부모프로세스가 파이프를 생성하고, 이후 자식 프로세스와 부모프로세스가 파이프를 이용하여 통신합니다.
pipe()
호출은파일 디스크립터 n
에 쓰여진(written) 데이터가파일 디스크립터 k
으로부터 읽히도록(read) 만든다.
파이프 함수의 원리
커널영역에 파이프를 만들고(모종의 이유로 파이프를 user 영역에 만들지 않는다. - 아마 보안상 이유일 것.), 커널 영역에서 file을 open해, file descriptor(정확히는 배열안의 fd 2개- n, k
.)를 user영역에 반환한다. 해당 file descriptor들을 user가 사용하여 IPC적용.
pipe으로 데이터를 주고 받을 때, user는 파일에 데이터를 쓰고 읽음으로써 fd를 활용한다.
아래 그림 설명해보기

dup2()
: 새로운 파일 디스크립터 fd2의 file description을 fd로 지정한다.
만약, fd2가 열려있었다면 (fd2의 file description이 있었다면), description을 닫고 새로 열어 fd의 file description으로 지정한다.
dup2
#include <unistd.h>
int dup2(int fd, int fd2);

학습에 도움된 사이트 :
오늘 발견한 문제와 해결방안:
- 자료조사 5시간 했는데 정확히 파이프와 리디렉션에 대한 정의를 공부하지 않았음.
- 감만 잡았지, 정확한 정의에 대해서는 공부하지 않음.
- 일단, 위키피디아 등으로 정확한 정의에 대해서 공부한 후, 사례로 공부하여 사례-정의에 대해 공부하도록 한다.
- 자료가 방대하긴한데... 자료를 잇지 못했다.
- 복습은 했지만 글로 정리하는 시간을 갖지 못했다.
- 위에 정리한 글은 정리글보다는 자료조사 흐름에 가깝다.
- 자료를 정리하는 시간을 하루 1시간 가진다.
- 중간중간에 시간 때우는 일이 있어서 순공부시간이 공부시간보다 적다.
- 체계적인 시간관리 필요.
7. 학습 총평 :
- 시간 때우는 일을 줄이고 집중하는 시간을 늘린다.
- 체계적인 자료조사 방법 / 흐름이 필요할 것 같다.
8. 다음 학습 계획 :
- Redirection 조사 마무리
- Pipe 자료조사 마무리
- 구현 생각.