반응형

리다이렉션 구현

이번 시간에는 디스크립터가 공유되는 특별한 케이스를 보여드릴거임.

라이브러리만 사용하는 사람들에겐 생소할 것임.

dup임

dup1 이라고 하는 코드는 

똑같은 코드인데 open을 2번하는게 아니라 1번한거 가지고 그대로 복제를 해온다.

 

즉 나머지는 다 똑같다.

 

<소스코드> dup1_.c

 

dup라는 걸 소스코드를 봤더니..

그것 중 기본적은 dup를 쓴거고

디스크립터를 복제하는 기술임. 3번 디스크립터 복제해서 4번으로 만들자.

어떻게 공유가 될건지가 중요하다

 

gcc dup_1.c

./a.out

hell

 

또 오픈을 한게 아니라 복제한거라면 밑에있는 그림이 달라질거 같다!

open할 떄만 파일이 생성하기 때문에 dup를 하게 되면 내부구조 상

// fd_array 기준으로 봤을 때 

 

 이 fd_array[4] = fd_array[3] 이런식으로 대입한다고 생각하면됩니다. 실제로 커널의 오픈소스에 이렇게 되어있다.! 그렇다는 건 4번도 이렇게 가리키게 하라 라는 뜻.

파일이라는 구조체는 2개의 포인터가 가리키게 때문에

파일 카운트라고 불리우는 f_count라는 레퍼런스 카운팅이 관리가 되고 이 카운트에 의해서 한마리가 관리하면 1이겠지만 2개의 포인터가 관리해서 2로 증분합니다.

그래서 같은 곳을 가르키면 오프셋 도 공유가 된다.

그래서 결론적으로 오프셋을 공유하는 경우다.

 

 그 활용 코드를 리다이렉션이라고 부릅니다.

리다이렉션의 대표주자!! 를 몇마리 보여주면

ls를 파일에 저장하고 싶다?

ls > xxx 하면 화면에 나가야할 정보가 파일로 저장이 된다.

cat xxx하며  그대로 저장된다.

이걸 표준 출력 리다이렉션 이라고 합니다.

이걸 구현할 수 있는가? 당연히 가능하다

 

cp dup_2.c를 구현해보자

 

 우리가 파일의 입력을 받는다. ./a.out xxx

그러면 파일을 쓰기 모드로 열어놓는다.  이걸 O_WRONLY | O_TRUNC | O_CREATE, 0666 의 의미는?

fopen의 w로 연거랑 똑같다. 이것의 의미는 파일을 쓰기모드열고 있으면 덮어쓰고 없으면 생성하고 생성퍼미션까지 준다.

 여기서 무슨 동작을 하나면 close(1); dup(fd);

 

<dup_2.c>

 

./a.out xxx

cat xxx

 

꺽쇠 라디아렉션 = 표준 출력 리다이렉션이랑 같다.

 

close(1);

dup(fd);

 

이 두 줄의 의미를 그대로 재현해 보면

close(1); // fd_array[1] = 0 으로 해라. 즉 닫아라. 표준출력으로 나가는 연결을 끊어버려라.

dup(fd); // fd_array[3] (fd)를 비어있는 곳에 넣어라. 즉 1번쪽에 넣게 된다. 결국 3번이 가리키는 파일도 같은 file에 가리키게 된다.

 

printf("hello world\n"); 는 // wirte(1)에다가 찍는거다!! 근데 1은 fd가 있으므로 파일에 찍히게 된다.

결국 printf 로 썼더라도 파일에 저장되는 구조임.

이게 표준 파일 리다이렉션이라고함.

표준 파일의 리다이렉션. close(1) dup(fd)임!

이렇게하면 쉘의 내부구조도 보이게 됩니다.

 

이번엔 역으로 표준 입력리다이렉션

대표주자가 cat임!!!

 

cat xxx 하면

그냥 화면에 찍히는거 처럼 보이지만

실제로 cat은 

cat < xxx

이렇게 리다이렉션으로 준거임

cat은 실제로 화면에 친 게 화면에 나오는 게 cat임

 

cat은 키보드에 읽어서 화면에 출력하는게 일반적.

꺽쇠로 xxx로 해주면 파일에 입력을 받아서 화면에 출력하라는 말!

바로 cat < xxx 의 의미임

 

표준 입력 리다이렉션이 들어간 코드라고 생각하면됨.

입력된 내용이 화면에 찍히는게 cat이니까 표준입력 리다이렉션을 구현하면 어떻게 짜면 될까?

 

 

 

dup3 코드

 

일반적으로 읽듯이 

 

원래 키보드에서 입력을 받아야하는 당연한 코드가 파일에 입력을 받아서 화면에 뿌렸음

 

 

표준 입력 리다이렉션은 close(0); dup(fd); 임

close(0); // fd_array[0] = 0;

dup(fd); // fd_array[0] = fd_array[3] 하란 얘기임!



이걸 그 유명한 표준 입력 리다이렉션이라고 합니다. (15:18)

cat은 키보드 입력을 받아서 화면에 뿌리고 ctrl+d를 입력하면 끝나는구조 (엔터치면 바로 출력됨)

ctrl+d가 EOF. 우리가 똑같이 cat처럼 짜려면

 

$ stty -a

를 입력하여 ctrl+? 의 키가 무얼 의미하는지 알아보자.

ctrl+d는 end of file을 의미한다.

 

cp dup_3.c cat.c로 해서

인자가 있고 없고의 차이가 있음.

 

 인자가 2개온 경우에만 파일을 열고 리다이렉션 걸게한다.

 

<소스코드 dup_3.c>

 

./a.out

./a.out xxx <---파일명

파일을 읽어서 화면에 뿌림

 

실제 cat은 이런 모습이 될 것입니다.

 

표준 에러출력 리다이렉션, 표준출력 리다이렉션 어펜트?

 

에러를 출력하게 하기? 에러를 영원히 복 ㅗ싶다.

 

$ gcc cat.c > err_log

$ cat err_log

모든 에러는 2번으로 출력이 되기 떄문에 2로 리다이렉션으로 해야한다

즉 위같이하지말고 아래와 같이 해야한다.

$ gcc cat.c 2> err_log

이 코드는 에러가 쌓이지 않고 최종 에러만 남는다

$ cat err_log

 

 

만약

$ gcc cat.2 2>> err_log

이렇게하면

err_log에 쌓이게 된다

 

>>는 append 모드다. (표준 라이브러리는 a모드, 이것이 시스템 콜이면 O_APPEND)

이렇게열면 파일의 끝에 추가가 된다.

 

 

 

 

 

 

 

 

 

 

 

반응형