[42seoul] - pipex
pipex
5th Project in 42seoul
Goal
Pipex 프로그램 작성
리눅스의 pipe를 구현하기
$> ./pipex file1 cmd1 cmd2 file2
file1
및file2
는 파일이름
cmd1
및cmd2
는 Shell 명령어
Pipex는 아래의 명령을 Shell에서 실행되는 것과 동일하게 처리해야 한다.
$> < file1 cmd1 | cmd2 > file2
$> ./pipex infile ``ls -l'' ``wc -l'' outfile
명령은
< infile ls -l | wc -l > outfile
와 동일해야 한다.
Bonus
다중 파이프 구현하기
$> ./pipex file1 cmd1 cmd2 cmd3 ... cmdn file2
위 명령어는 다음과 같아야 한다.
$> < file1 cmd1 | cmd2 | cmd3 ... | cmdn > file2
사용 가능 함수
int open(const char *pathname, int flags);
- pathname : 파일의 경로와 이름, (절대경로, 상대경로 모두 가능)
- flags : 파일을 어떻게 열지 결정하는 플래그, 읽기전용 O_RDONLY, 쓰기전용 O_WRONLY, 읽기쓰기 O_RDWR
- 반환 : 성공적으로 열면 파일 디스크립터 반환, 아니면 음수 반환
- 파라미터 : 3번 째 파라미터가 있을 경우에는 O_CREAT로 인해 파일이 생성될 때 부여되는 파일 접근권한이 들어간다.
ex)data = open(argv[1], O_RDONLY, 0777);
. - O_TRUNC : O_WRONLY 또는 O_RDWR로 open시에 이미 존재하는 파일이면 파일의 내용을 삭제하여 파일의 크기를 0으로 만듭니다.
ssize_t read(int fd, void *buf, size_t nbytes);
- fd : 파일 디스크립터
- buf : 파일에서 읽어 들인 입력값을 저장할 버퍼, 어떤 자료형으로 읽어올지 몰라 void* 형이다.
- nbytes : 얼마만큼 읽어오는 바이트수
- 반환 : 정상적으로 파일내용을 읽어오면 nbytes값 반환, 아니면 0반환
int close(int fd);
- fd : 파일 디스크립터
- 반환 : 정상작동시 0반환, 아니면 -1반환
ssize_t write(int fd, const void *buf, size_t n);
- fd : 파일 디스크립터
- buf : 파일에 쓰기를 할 내용을 담은 버퍼
- n : 파일에 쓸 바이트 개수
- 반환 : 정상적으로 파일쓰면 n값 반환, 아니면 -1반환
void *malloc(size_t size);
- 헤더 :
stdlib.h
- 헤더 :
void free(void* ptr);
- 헤더 :
stdlib.h
- 헤더 :
int dup2(int oldfd, int newfd);
- 설명 : oldfd 디스크립터에서 newfd로 파일을 복제한다. newfd가 이미 열려있을 경우 close후 복제한다. (엄밀히 말하면 newfd를 oldfd로 바꾼다)
- 헤더 :
unistd.h
- oldfd : 복사하려는 원본 파일 디스크립터
- newfd : 복사되는 파일 디스크립터
- 반환 : 정상작동 시 -1이외의 값, 아니면 -1반환
int execve(const char *filename, char *const argv[], char *const envp[]);
- 헤더 :
unistd.h
- 설명 : 현재 실행되는 프로그램의 기능을 끄고 filename 프로그램을 실행한다.
- argv : 인수 목록
- envp : 환경변수 목록
- 헤더 :
pid_t fork(void);
- 설명 : 자식프로세스를 만들기 위해 사용되는 프로세스 생성 함수이다.
- 헤더 :
unistd.h
- 반환 : 실패일 때만 -1반환, 부모 프로세스(원본 프로세스)에서는 자식프로세스(생성된 프로세스)의id반환, 자식프로세스에서는 0반환, (부모일 때 자식프로세스를, 자식일 때 0을 반환)
void perror(const char *str);
- str : 출력할 문자열
- 설명 : 에러 메세지를 출력하는 함수이다.
char *strerror(int errno);
- 헤더 :
errno.h
- errno : 에러 번호
- 반환 : 에러 번호에 상응하는 에러 메세지
- 헤더 :
void exit(int status);
- 헤더 :
stdlib.h
- 설명 : c프로그램 종료함수, return은 함수를 종료할 때 사용하고 exit는 프로세스를 종료할 때 사용하고 main함수에서 return은 프로세스를 종료함. 표준 라이브러리 헤더 중
에 EXIT_SUCCESS 와 EXIT_FAILURE라는 매크로 상수값이 정의 되어 있다.
- 헤더 :
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
pipe
int pipe(filedes[2]);
- filedes : 0인덱스는 읽기, 1은 쓰기
- 반환 : 성공시 0, 실패 -1
- 프로세스간 통신하는 방법을 담을 함수
pipe함수는 단방향 통신이라 사용하지 않는 fd는 닫아줘야한다.
pipe wirter 쪽에서 close를 하면 EOF가 reader한테 넘어간다.
reader 쪽에서 close를 하면 writer 쪽으로 SIGPIPE 시그널이 간다. - 참고 : https://velog.io/@hidaehyunlee/minishell-5.-%ED%8C%8C%EC%9D%B4%ED%94%84Pipe-%EC%B2%98%EB%A6%AC
access
-int access(const char *pathname, int mode);
- pathname : 파일경로
- mode : R_OK : 읽기 권한 여부, W_OK : 쓰기 권한 여부, X_OK : 실행 권한 여부, F_OK : 파일존재여부, (R,W,X 는 파일존재여부 모두 포함)
- 헤더 :
unistd.h
- 반환 : 성공시 0, 실패시 -1
fcntl
- 파일 처리 헤더
sys/wait
- 프로세스 관련 헤더
프로세스
- 부모 프로세스가 fork()함수로 인해 자식 프로세스를 생성했을 때, fork()함수가 리턴되는 순간부터 2개의 프로세스가 동작한다.
- 부모 프로세스가 자식 프로세스의 종료상태를 얻기위해서는 wait()함수가 사용한다.
wait / waitpid
- wait는 자식 프로세스 어느하나라도 종료시 부모 프로세스가 대기상태에서 풀림
- waitpid는 특정 자식 프로세스가 종료시 부모 프로세스가 대기상태에서 풀림
-
wait
- 헤더 :
sys/wait.h
pid_t wait(int *statloc);
- 반환 : 성공시 프로세스id 반환, 실패시 -1 반환
- statloc : 상태값을 담는다
- 동작 :
- 자식 프로세스가 동작 중이면 호출 차단이 차단되기 때문에 상태를 얻어올 때까지 대기
- wait() 함수 호출자가 시그널을 받을 때까지 대기
- 자식 프로세스가 종료된 상태라면 즉시 호출이 반환되어 상태를 얻음, 이 때 wait() 함수는 자식 프로세스의 프로세스 ID를 반환
- 자식 프로세스가 없다면 호출이 즉시 반환되며, 에러값을 반환 (-1)
waitpid
pid_t waitpid(pid_t pid, int *statloc, int options)
- 헤더 :
sys/wait.h
- 반환 : 성공시 pid, 오류시 -1, 그 외 0
- pid : 특정 자식 프로세스
- statloc : 자식 프로세스의 종료 상태 정보
- options : 주로 WNOHANG 과 0 을 사용
- WNOHANG 상수 사용 시 자식프로세스 종료까지 부모프로세스가 block되지 않음
- 0 값 사용 시 자식프로세스 종료까지 부모프로세스가 block처리 된다. (즉 wait와 같은 처리방식) - 링크 : https://velog.io/@t1won/Unix
exec 계열 함수
- 링크 : https://velog.io/@kyj93790/Pipex-%EC%82%AC%EC%9A%A9%EA%B0%80%EB%8A%A5-%ED%95%A8%EC%88%98-execve-fork-pipe-waitwaitpid