리눅스에 관한 더 많은 정보와 예제를 담은 리눅스 교재를 배포했습니다. 아래의 페이지에서 리눅스 교재를 받아가세요.

https://reakwon.tistory.com/233

 

리눅스 프로그래밍 note 배포

티스토리에 리눅스에 관한 내용을 두서없이 여지껏 포스팅했었데요. 저도 제 포스팅을 찾기가 어렵기도 하고 티스토리에서 코드삽입을 하게 되면 이게 일자로 쭉 쓰여져있는 x같은 현상이 생겨

reakwon.tistory.com

 

readn, writen

네트워크같은 환경에서 어마어마한 데이터가 쓰여질 경우 일반 read함수로는 전부 읽어올 수 없는 상황이 발생할 수 있습니다. 또 반대의 경우에도 마찬가지입니다. 큰 데이터가 한번에 쓰여질 경우 write함수로는 쓰여지지 않을 수 있습니다. 아래와 같은 두가지의 상황이 발생하기 때문인데요.

1) read 연산이 요청보다 작은 바이트를 되돌려줄 경우에는 이는 오류가 아닙니다. 단지, 더 읽어야할 데이터가 있다는 뜻입니다. 2) write 역시 요청보다 작은 바이트를 돌려줄 수 있는 경우가 있는데, 커널의 출력 버퍼가 꽉 찼을때 이런 경우가 발생합니다.

1), 2)는 어떻게 해결할 수 있을까요? 답은 데이터가 요청된 값이 될때까지 읽거나 쓰는 것입니다. 이런 함수가 아래의 readn, writen 함수입니다.

- 아래의 코드는 Advanced Programming in the UNIX Environment 3판을 참고하여 만든 코드입니다.

 rean 함수

ssize_t readn(int fd, void *data, size_t n){
        size_t left;    //남은 바이트
        size_t read_n;  //읽은 바이트

        left = n;

        while(left > 0){
                if((read_n = read(fd, data, left)) < 0){
                        if(left == n) return -1;
                        else break;
                }else if(read_n == 0) break;
                left -= read_n; //얼마나 남았는지 갱신
                data += read_n; //남은 바이트 읽기 위해 포인터 이동
        }

        return n-left;
}

 

readn 함수를 보면 while문을 통해서 계속 다 읽을때까지 read를 호출하는 것을 볼 수 있습니다. read가 0을 반환하면 다 읽었다고 판단하여 while 루프를 종료하고 빠져나오면 됩니다.

 

writen 함수

ssize_t writen(int fd, const void *data, size_t n){
        size_t left;    //쓰기까지 남은 바이트
        ssize_t written_n;      //쓴 바이트

        left = n;

        while(left > 0){
                if((written_n = write(fd, data, left)) <0){
                        if(left == n) return -1;
                        else break;
                }else if(written_n == 0) break;
                left -= written_n;      //얼마나 남았는지 갱신
                data += written_n;      //남은 바이트 쓰기 위해 포인터 이동
        }

        return n-left;
}

 

writen 함수 역시 계속 data를 쓸때까지 while 루프로 계속 write를 호출하는 것을 볼 수 있습니다. write가 0을 반환하게 되면 다 썼다는 의미로 반복문을 빠져나오고 writen 함수가 종료됩니다.

 

readn, writen 함수는 read, write함수와 동일하게 사용이 가능합니다. 이 함수들은 socket과 같은 네트워크, 파이프, FIFO 등에서 대량의 바이트를 읽거나 쓰기위한 함수라는 것을 기억하시기 바랍니다. 일반 파일 IO에서는 read, write만 사용해도 무관합니다.

반응형
블로그 이미지

REAKWON

와나진짜

,

리눅스 네트워크 프로그래밍에 관한 더 많은 정보와 예제를 담은 리눅스 교재를 배포했습니다. 아래의 페이지에서 리눅스 교재를 받아가세요.

https://reakwon.tistory.com/233

 

리눅스 프로그래밍 note 배포

티스토리에 리눅스에 관한 내용을 두서없이 여지껏 포스팅했었데요. 저도 제 포스팅을 찾기가 어렵기도 하고 티스토리에서 코드삽입을 하게 되면 이게 일자로 쭉 쓰여져있는 x같은 현상이 생겨

reakwon.tistory.com

 

netstat

네트워크의 connection, routing table, interface 통계 등 네트워크 전반의 정보들을 나타내어주는 명령어입니다. netstat 명령어를 사용함으로써 시스템의 port들이 어떤 상태인지를 확인할 수 있게 됩니다. 예를 들어 현재 서버에서 socket이 열려서 client의 연결을 대기 중인 상태라면 listen 상태가 됩니다. 

netstat을 어떻게 사용하는 지 알아봅시다.

기본적으로 netstat만을 사용하면 열린 모든 socket들에 대해서 보여줍니다. 그런데 기본적으로 LISTENING 상태는 보여주지 않습니다. LISTENING 상태의 socket을 함께 보고싶으시면 아래의 설명할 -a, 혹은 -l 옵션을 지정해주어야합니다.

 

※  여기서 Active Internet connections, Active UNIX domain sockets라고 하여서 약간 다르게 나타나는게 보이시죠? Internet connections는 여러분이 알고 있는 네트워크 상의 connection을 의미하지만, UNIX Domain Sockets(UDS라고도 합니다.)은 시스템 내부에서 사용하는 socket으로 인터넷을 사용하지 않고 통신하기 위한 IPC 기법입니다. socket 파일을 통해서 통신합니다. ls -l 명령을 입력했을때 앞에 s가 바로 그 socket 파일입니다. 복잡한 네트워크를 사용하지 않기 때문에 아래에서 보겠지만 State가 Internet connections보다는 간단합니다. 함수는 인터넷 socket과 동일하게 사용합니다. 

 

netstat를 그냥 사용하면 정신없을 수도 있으니까 아래의 option들을 적절히 이용해서 사용하도록 합시다.

옵션 설명
-l Listening 중인 socket을 표시합니다.
-p socket을 사용하는 pid와 program 이름을 보여줍니다.
-n 주소등을 number로 표시합니다(ex localhost를 127.0.0.1 로 표현)
-i interface의 정보를 보여줍니다.
-t tcp 사용 socket을 보여줍니다.
-u udp 사용 socket을 보여줍니다.
-r routing table을 보여줍니다.
-a listening과 non-listening 상태 모두를 보여줍니다.
-c 매 초마다 명령을 계속적으로 실행합니다.

 

netstat -nltp : listen 중인 tcp를 사용하는 socket을 표시하는데, 그 socket을 사용하는 프로그램도 같이 표시. 주소를 숫자로 표현 

 

netstat -nltp | grep port 번호 : 특정 port가 어떤 상태인지 알아보려면 grep을 이용해서 찾을 수 있습니다.

 

netstat -r : 라우팅 테이블의 정보를 확인할 수 있습니다.

 

 

State

netstat을 사용하면 State라는 socket의 상태를 볼 수 있는데, Internet connection과 UDS를 아래의 표로 정리하였습니다.

- Internet 

State 설명
ESTABLISHED socket이 연결이 성립된 상태입니다.
SYN_SENT socket이 syn 패킷을 보냈으며 연결을 시도하려고 하는 상태입니다.
SYN_RECV socket이 연결 요청을 받은 상태입니다.
FIN_WAIT1 socket이 닫혔고, 연결이 해제되고 있는 상태입니다.
FIN_WAIT2 연결이 닫혔으며, socket은 remote end로부터 shutdown을 기다리고 있는 상태입니다.
TIME_WAIT close 이후 socket이 여전히 네트워크에 남아있는 패킷을 처리하기 위해  대기 중인 상태입니다. 일정시간이 지난 후 이 상태는 사라집니다.
CLOSE socket이 사용중이지 않는 상태입니다.
CLOSE_WAIT remote end가 연결을 해제하였고, 이 컴퓨터의 socket이 닫히기를 기다리고 있는 상태입니다. 
LAST_ACK remote end에서 shut down되었고, socket이 닫힌 상태입니다. 하지만 최종 ack 응답은 기다리는 상태입니다.
LISTEN socket이 연결을 위해서 listening 중인 상태입니다. 
CLOSING 양쪽 모두 socket이 닫혔지만, 페킷을 완전히 못받은 상태입니다, 즉, 페킷이 유실되었다는 의미입니다.
UNKNOWN 어떠한 이유에서 socket의 상태를 알수가 없는 상태입니다.

 

모두 알필요는 없으며, LISTEN, ESTABLISHED, WAIT과 관련된 것만 봐도 상관없을 것 같네요.

 

- Unix Domain Socket(UDS)

State 설명
FREE socket이 할당되지 않았습니다.
LISTENING connection을 대기하고 있습니다.  internet의 LISTENING과 같습니다.
CONNECTING connection을 막 하고 있는 상태입니다.
CONNECTED 연결이 된 상태입니다. internet의 ESTABLISHED 상태와 같습니다.
DISCONNECTING socket이 연결 해제 중입니다.
(empty) socket이 연결되지 않은 상태입니다.
UNKNOWN 절대로 발생할 수 없는 상태입니다. 

 

하지만 netstat은 오래된 프로그램이라서 ss 명령어로 대체가 되었습니다. 나중에 시간이 있으면 ss 명령어에 대해서 포스팅하도록 하겠습니다.

반응형
블로그 이미지

REAKWON

와나진짜

,

segmentation fault (core dumped)

이런 무시무시한 문구가 떴는데, 눈을 씻고 찾아봐도 coredump 파일을 찾을 수가 없었습니다. 분명 메시지는 coredump 파일 생성됐다고 써있는데 말이죠... 내눈이 잘못된건가, 아니면 내가 영어를 못하는건가.. 

그래서 제가 찾은 coredump를 찾는 몇가지 해결 방법을 알려드리도록 할게요. 

1. ulimit으로 core dump size를 확인

아래와 같은 명령어로 core file size를 확인합니다. 

# ulimit -a

 

0 이상이어야합니다. 그러니까 이 부분을 고쳐하겠죠. 0보다 크면 되긴하지만, unlimited로 바꿔보도록 합시다. 

# ulimit -c unlimited

 

 

위처럼 unlimited로 바뀐것을 알 수 있습니다. 이제 프로그램을 실행시키면 coredump 파일이 생성될 수도 있습니다. 물론 저처럼 두번째 문제가 있을때는 coredump 파일이 생성되지 않을 수도 있으니, 2번까지 확인해보세요.

한가지 더, ulimit으로 설정한 core dump size는 일시적입니다. 즉, reboot은 당연하고 세션이 끊어지면 초기화된다는 것이죠. 터미널 접속시 바로 설정되도록 적용하려면 아래와 같이 /etc/security/limites.conf 파일을 설정하시면 됩니다. 

# vi /etc/security/limits.conf

맨 아래에 아래와 같이 추가하여 저장하시면 반영구적으로 적용됩니다.

 

 

2. /proc/sys/kernel/core_pattern 편집하여 현재 디렉토리에 coredump 생성

원래 coredump 파일을 프로그램 실행 위치에 생성되는 것으로 알고 있는데, 저의 경우에는 그게 아니었습니다. 도대체 왜 나만 안되는거야 이러고 있을 때 google 형님께 여쭈어본 결과 /proc/sys/kernel/core_pattern에서 설정할수 있다고 하십니다. 이 파일이 coredump 파일을 어떻게 생성하는지 정의하고 있는데, 열어보면 어떤 이상한 경로로 되어있을 가능성이 있습니다. 저는 과감하게 바꿔줬습니다. 

# echo "core.%e.%p" > /proc/sys/kernel/core_pattern

 

%e와 %p는 format문자로 저도 모릅니다. google형님이 알려준대로 썼으니까요. 이제 바꿔주고 coredump되는 실행파일을 실행시켜주면 그 디렉토리에 coredump 파일이 뜨게 됩니다.

 

core 덤프 파일이름을 보면 %e는 프로그램 이름, %p는 pid인 듯 보이네요.

 

여러분도 저처럼 삽질에 시간쓰지 마시라고 공유합니다. 그럼 이만 포스팅 마칩니다~

반응형
블로그 이미지

REAKWON

와나진짜

,