Skip to content

io 모듈

uhm0311 edited this page Apr 12, 2022 · 1 revision

io_write(), io_read()

io 모듈은 연결이 수립된 socket file descriptor를 통해 send() system call과 recv() system call을 호출하여 arcus-memcached 서버와 실질적인 통신을 담당합니다.

io 모듈의 진입은 memcached_io_write() 함수, memcached_io_read() 함수 등으로 이뤄집니다.

memcached_io_write(), memcached_io_writev()

send() system call을 호출하기 위해 진입점이 되는 함수로는 memcached_io_write() 함수와 memcached_io_writev() 함수가 있습니다.

memcached_io_write() 함수는 byte array를 매개변수로 받고, memcached_io_writev()는 vector 객체의 array를 매개변수로 받습니다.

내부 동작은 두 함수 모두 _io_write() 함수를 사용합니다.

memcached_io_write() 함수는 byte array를 곧바로 _io_write() 함수에 전달하고 memcached_io_writev() 함수는 vector 객체 array를 반복문으로 순회하며 vector 객체에 담긴 byte array를 _io_write() 함수에 전달합니다.

_io_write()

_io_write() 함수는 byte array를 8KB의 write buffer 단위로 잘라 io_flush() 함수를 호출하도록 합니다.

io_flush()

  • send() system call을 호출하는 함수입니다.

  • send() system call을 호출했을 때 socket의 read buffer가 가득 차서 실패할 경우 repack_input_buffer() 함수를 호출하여 read buffer를 임시적으로 다른 buffer에 옮겨두고 재시도합니다.

  • 다른 buffer도 가득 차 있을 경우 process_input_buffer() 함수를 호출합니다. process_input_buffer() 함수에서는 arcus-memcached response에 대한 콜백 함수가 지정되어 있을 경우 read buffer를 소비하고 콜백을 호출합니다.

  • 다른 buffer도 가득 차 있고 response 콜백 함수도 지정되어 있지 않은 경우 io_wait() 함수를 호출합니다.

io_wait()

  • io_wait() 함수는 connect 모듈의 connect_poll() 함수와 유사하게 동작하여 poll() system call을 통해 socket이 write 가능한 상태인지 확인합니다.

  • connect_poll() 함수는 socket이 write 가능한 상태인지만을 확인하는 반면, io_wait() 함수는 send() system call을 사용하는 상황이라면 socket이 write 가능한지를 확인하고 recv() system call을 사용하는 상황이라면 socket이 read 가능한지를 확인합니다.

  • send() system call에서 socket의 read buffer가 가득 찬 경우 외에 다른 실패 상황, 혹은 io_wait() 함수에서 poll() system call이 실패한 상황에서는 memcached_quit_server() 함수를 호출하여 read buffer와 write buffer를 비우고 socket 연결을 해제합니다.

memcached_io_read(), memcached_io_readline()

recv() system call을 호출하기 위해 진입점이 되는 함수로는 memcached_io_read() 함수와 memcached_io_readline() 함수가 있습니다.

memcached_io_readline() 함수는 read buffer에서 \n으로 끝나는 한 라인을 읽기 위해 사용되며, read buffer가 비워져 있을 경우 내부적으로 memcached_io_read() 함수를 사용합니다.

memcached_io_read() 함수는 read buffer가 비어 있으면 _io_fill() 함수를 호출하여 read buffer를 채웁니다.

read buffer가 비어 있지 않으면 read buffer의 크기인 8KB 단위로 반복하여 read buffer를 소비해서 매개변수의 byte array에 데이터를 memcpy() system call로 복제합니다.

_io_fill()

recv() system call을 호출하는 함수입니다. read buffer의 크기인 8KB 단위로 recv() system call을 호출합니다.

recv() system call에서 EINTR 에러가 날 경우 재시도를 합니다.

ETIMEDOUT, EWOULDBLOCK, EAGAIN, ERESTART인 경우 io_wait() 함수를 통해 socket이 read 가능한 상태인지 확인합니다.

io_wait() 함수에서 성공하면 recv() system call을 재시도하고, 실패할 경우엔 연산 수행 중으로 마크한 뒤 _io_fill() 함수를 종료합니다.

EINTR 에러나 io_wait() 함수를 호출하는 에러를 제외하면 memcached_quit_server() 함수를 통해 read buffer와 write buffer를 비우고 socket 연결을 해제합니다.