:
을 스플릿하고 전부 확인해봐야하겠음코드는 짧은 것을 알고 있으나 많은 이론 지식을 알고 있어야 한다.
예외처리 및 어떤 문제 발생 시 왜 일어나고 어떻게 해결하는지 defense하는게 관건으로 생각한다.
이번에는 따로 코드설명을 넣지 않으려 합니다.
- 메인 매개변수 개수 예외처리 체크
- pipe 함수 예외처리 체크
- fork 예외처리
- pid값을 통한 부모자식 분기
- 부모프로세스에 waitpid를 적용하여, 자식프로세스가 끝나야 작동되도록
- 메인 매개변수 인덱스 1, 2를 활용하여 아래와 같이 실행
- 파일 만들기
- 표준입출력 fd 변경
- 명령어 실행
- 메인 매개변수 인덱스 3, 4를 활용하여 아래와 같이 실행
- 파일 만들기 (권한도 같이 부여)
- 표준 입출력 fd 변경
- 명령어 실행
리다이렉션(Redirection)
리눅스에서 프로그램은 보통 세 개의 파일 서술자를 열게 됨.
cmd
에서 출력하는 것을 file_name
에 덮어쓰기 저장 stderr
로 출력된 내용이기 때문. 💡 위 명령어의 경우
ls -l 10 > tt.txt
는ls -l 10 1> tt.txt
와 같은 동작을 한다. 즉, fd 1의 값인 stdout을 저장한다는 뜻이다.
ls -l 10 2> tt.txt
로 에러문구를 저장할 수 있다.
cmd
에서 출력하는 것을 file_name
의 마지막에 추가하여 저장
file_name
의 파일 내용을 표준입력으로 사용
한다는 의미.
💡
ls
명령어같이 표준입력을 받지 않는 경우argv(argument vector
)를 통해 사용자 입력을 받고 있음.
cmd1의 표준출력
을 cmd2의 표준입력
으로 받는다.
💡 42를 통해 사용해본 함수는 예제를 넣지 않음.
unistd.h
*pathname
: 체크하고자 할 디렉토리 또는 파일명mode
: 마스크 값을 통해 파일 존재 여부 및 권한 여부 확인0
, 실패시 -1
int main(void)
{
char *path = "./test.txt";
if (0 == access(path, F_OK))
{
write(1, "@\n", 2);
}
else
{
write(1, "$\n", 2);
}
return (0);
}
fcntl.h
*filename
flags
양의 정수인 파일 디스크립터
, 실패 시 -1
unistd.h
*pathname
0
, 실패 시 -1
rm 프로그램이 이 호출을 사용한다.
💡 하드링크, 심볼릭 링크
[리눅스, 유닉스] 파일링크 ln 명령어- 심볼릭 링크(소프트링크)와 하드링크 원리, I-node 아이노드
unistd.h
close
0
, 실패 시 -1
unistd.h
fd
: 파일 디스크립터*buf
: 파일을 읽어드릴 버퍼nbytes
: 버퍼크기읽은 바이트 수
, 실패 시 -1
💡 사전 조사라 모르는 내용이 대부분이지만, 우선 대강의 내용을 알고 과제를 진행하면서 숙달해보자
sys/wait.h
*wstate
: 종료상태를 알 수 있고, NULL 전달 가능fork 함수 사용하여 프로세스 생성
<설명 굳>
unistd.h
종료된 자식 프로세스 id
, 실패 시 -1
리눅스 wait 함수 : 자식 프로세스가 종료될 때 까지 기다린다.
[리눅스] 프로세스 생성과 특징, 종료 (fork, wait), 예제 코드
<고아프로세스 설명있음>
sys/wait.h
pid
: 감시할 자식 프로세스 id*status
: 자식 프로세스의 종료 상태 정보options
: 대기를 위한 옵션종료된 자식 프로세스 id
, 실패 시 -1
unistd.h
fd[2]
: fd가 2개임0
, 실패 시 -1
[리눅스] 파이프(pipe) 개념과 예제
[Programming/C] pipe() 함수
<부모자식간 표준입출력 방법>
unistd.h
fd
: fd로 전달받은 파일디스크립트를 복제하여 반환-1
unistd.h
fd
: fd로 전달받은 파일디스크립트를 복제하여 반환fd2
: 새 디스크립트의 값을 fd2
로 지정하고, 만약 fd2가 열려있다면, 닫은 후 복제가 됨.-1
[리눅스] dup, dup2 설명 및 쉬운 사용법, 사용 예제(그림 포함)
unistd.h
*path
: 전체 파일 명*arg
: 인수 목록envp[]
: 환경설정목록-1
/bin/@@
형식의 path가 있어야 하는 것 같다.#include <unistd.h>
#include <stdio.h>
int main(int argc, char * const *argv, char **envp)
{
char *arr[] = {"ls", "-al", NULL};
int returnv = execve("/bin/ls", arr, envp);
printf("value = %d\n", returnv);
}
stdio.h
*str
: 시스템 오류 메세지 다음에 이어 출력할 사용자 정의 메세지cstring.h
errnum
: 오류번호, 이 값을 통해 발생하였떤 오류에 알맞는 오류 메세지를 가리키는 포인터를 리턴시킴stdlib.h
pipe에서 안쓰는 fd를 닫아주지 않으면 쓰기가 일어날 수 있다고 판단하여 EOF를 반환하지 않고, 프로세스를 종료하지 않음.
What happens if a child process won't close the pipe from writing, while reading?
해당 함수를 사용하면 프로세스의 바이너리 파일이 바뀌게 되어 아무리 아래에 프로그래밍하여도 작동하지 않는다.
free를 하지 않은 공간이 있을 경우에도 프로세스를 종료할 때, 할당한 메모리를 OS에서 자동으로 해제시켜준다.
다만, malloc한 공간의 주소를 잃어버릴 경우 결과 상관없이 leaks를 조심하여햐 한다.
[리눅스] 재지정, 리다이렉션(redirection: >, <)과 파이프(|) 개념과 쉬운 설명
<리다이렉션>
IPC - 03. pipe() 를 통한 프로세스 통신
<pipe와 fd[2]를 잘 설명한 사이트>
[리눅스] dup, dup2 설명 및 쉬운 사용법, 사용 예제(그림 포함)
<dup2 함수 설명>
리눅스 waitpid 함수 : 자식 프로세스를 기다린다.
<wait와 프로세스 등을 자세히 정리한 블로그>
6.2.2 Creating Pipes in C
<pipe와 dup에 관한 자세한 설명>
What happens if a child process won't close the pipe from writing, while reading?
<왜 안쓰는 fd는 close 해야 하는지>
와우~ 과제를 하며 공부한 내용이 총망라돼있네요.
과제 처음 하는 사람들에게 도움도 되고, 나중에 복습할 때도 좋을 것 같습니다.
나중에 저도 과제 정리할 때 많은 참고가 될 것 같네요. 잘 봤습니다!👍