int getsockopt(int socket, int level, int option_name, void *restrict option_value, socklen_t *restrict option_len);
int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len);
socket
: socket으로 소켓 디스크립터
level
: 프로토콜 레벨 (SOL_SOCKET, IPPROTO_IP, IPPROTO_TCP, IPPROTO_IPV6 등)
option_name
: 옵션 이름
option_value
: 설정할 옵션 값.다양한 형태의 option value가 올 수 있기 때문에 void *로 선언되어 있음
option_len
: len of option_value
프로토콜 레벨마다 지정할 수 있는 option이 다름
https://learn.microsoft.com/ko-kr/windows/win32/winsock/socket-options
https://m.blog.naver.com/kbm0996/221040731183
socket programming 관련 예제에선 SOL_SOCKET 레벨의 SO_REUSEADDR
옵션을 보통 추가로 세팅해주는 것 같다.
현재 socket option을 가져올 수 있는 함수. setsockopt랑 똑같이 사용하면 된다. 대신 이번엔 option_value랑 option_len에 값이 담겨 옴.
https://www.freebsd.org/cgi/man.cgi?query=EV_SET&sektion=3&apropos=0&manpath=FreeBSD%2B10.0-RELEASE
커널 큐를 새로 만들고 해당 kqueue descriptor 를 리턴해줌.
kqueue는 fork() 시 복사되지 않음.
특정 kqueue에 모니터링할 이벤트를 등록할 수 있음
int
kevent(int kq, const struct kevent *changelist, int nchanges,
struct kevent *eventlist, int nevents,
const struct timespec *timeout);
kq
: kqueue descriptor
changelist
: 등록할 이벤트 목록
nchanges
: 등록할 이벤트 개수
eventlist
: 감지된 이벤트 목록
nevents
: 감지된 이벤트 개수
timeout
: blocking이 몇 초 이상 지속되면 timeout시킬지. 0으로 세팅하면 이벤트 일어나기까지 계속 blocking.
kevent struct를 쉽게 세팅할 수 있는 매크로 함수.
kevent의 구조는 다음과 같음
struct kevent {
uintptr_t ident; /* identifier for this event */
short filter; /* filter for event */
u_short flags; /* action flags for kqueue */
u_int fflags; /* filter flag value */
int64_t data; /* filter data value */
void *udata; /* opaque user data identifier */
uint64_t ext[4]; /* extensions */
};
ident
: event를 구분할 수 있는 식별자. 보통 file descriptor.
filter
: 커널 필터
flags
: 이벤트에서 수행할 작업 플래그
fflags
: 필터별 플래그
data
: 필터별 데이터 값
udata
: 사용자 정의값
변경되지 않고 커널 안팎으로 전달되며 어떤 방식으로도 사용되지 않는다. 전적으로 애플리케이션에 따르게 된다. kevent의 애플리케이션용 식별자로 이용될 수 있다.
ext
: 커널과 주고받는 확장 데이터
ext[0]과 ext[1]의 사용은 filter에 의해 정의 된다. 만약 필터가 사용하지 않는다면 변경되지 않고 그대로 복사된다. ext[2]와 ext[3]은 항상 커널을 통해 전달된다. 애플리케이션이 추가 컨텍스트를 사용할 수 있게 한다.
flag | meagning |
---|---|
EV_ADD | kqueue에 이벤트를 추가한다. re-adding시 기존 이벤트의 매개변수가 수정되며, 중복 항목이 생성되진 않는다. |
EV_ENABLE | kevent가 트리거된 경우 event를 반환하도록 허용한다. |
EV_DISABLE | kevent가 이벤트를 반환하지 않도록 이벤트를 비활성화한다. 필터 자체는 비활성화 되지 않는다. |
EV_DISPATCH | event가 전달된 직후 이벤트를 disable하게 만든다. |
EV_DELETE | kqueue에서 이벤트를 지운다. close(fd)를 할 때 fd에 관련된 이벤트가 자동으로 삭제된다. |
EV_RECEIPT | 대량의 changes를 만드려 할 때 그 중 하나라도 error를 일으키면, eventlist에 에러를 일으킨 이벤트가 배치되고, flags가 EV_ERROR로 세팅된다. 이렇게 하면 changelist에서 어떤 이벤트가 에러를 발생시켰는지 식별할 수 있다. |
EV_ONESHOT | 특정 이벤트가 트리거된 이후 사용자가 이벤트를 수집하면 kqueue에서 삭제된다. DISABLE은 비활성화만 하는 것. ONESHOT은 아예 kqueue에서 삭제해버리는 것. |
EV_CLEAR | 사용자가 이벤트를 수집하고 나면 상태를 리셋시킬 수 있는 플래그.(여기서 말하는 states가 정확히 뭔진 모르겠음.) 현재 state가 아니라 state transitions를 보고하는 filter에서 유용함. 일부 filter에선 자동으로 이 플래그를 설정하고 있을 수 있음 |
EV_EOF | 필터별 EOF를 나타내기 위해 사용할 수 있음. socket programming의 경우 disconnection을 감지하는 데 사용할 수 있음 |
EV_ERROR | changelist 처리 도중 오류가 발생하면 EV_ERROR와 함께 eventlist에 이벤트를 배치한다. |
사실상 EVFILT_READ
, EVFILT_WRITE
만 보면 될 듯
filter | meaning |
---|---|
EVFILT_READ | descriptor를 identifier로 사용하고 읽을 수 있는 데이터가 있을 때마다 return 된다. listen()으로 전달된 Socket의 경우 보류중인 incomming connection이 있을 때 return 된다. data에는 listen backlog가 포함된다. 다른 Socket의 경우 읽을 수 있는 데이터가 있을 때 return 된다. data에는 읽을 수 있는 protocol data의 바이트가 포함된다. |
EVFILT_WRITE | descriptor를 identifier로 사용하고 디스크립터에 쓸 수 있을 때마다 return 된다. Socket의 경우 data에는 쓰기 버퍼에 남아 있는 공간의 양이 포함된다. reader가 연결이 끊기면 filter는 EV_EOF로 세팅된다. |
EVFILT_EMPTY | descriptor를 identifier로 사용하고 쓰기 버퍼에 남은 데이터가 없을 때마다 return 된다. |
EVFILT_AIO | asynchronous I/O system 관련된 필터. kevent()에 바로 등록되진 않는 대신 aio_sigevent 멤버로 등록된다고 한다. 비동기 I/O관련 필터인듯. |
EVFILT_VNODE | file descriptor를 identifier, 감시할 events, fflags로 사용한다. 디스크립터에서 요청된 이벤트 중 하나 이상이 발생하면 return 된다. |
EVFILT_PROC | process ID를 identifier, 감시할 events, fflags로 사용한다. 프로세스가 요청된 이벤트 중 하나 이상을 수행하면 return 된다. |
EVFILT_PROCDESC | pdfork()로 받은 process descriptor를 identifier, 감시할 events, fflags로 사용한다. 관련 프로세스가 요청된 이벤트 중 하나 이상을 수행하면 return 된다. |
EVFILT_SIGNAL | 모니터할 signal 번호를 identifiler로 사용하고 프로세스로부터 해당 signal이 전달되면 return 된다. signal(), sigaction()과 coexist하며 우선순위는 더 낮다. |
EVFILT_TIMER | ident로 식별되는 임의의 타이머를 설정한다. timer를 추가하는 순간, data는 타이머를 작동할 순간을 지정한다. 반환시 data에는 kevent()에 대한 마지막 호출 이후 timeout이 만료된 횟수가 포함된다. |
EVFILT_USER | 커널 메커니즘과 관련이 없지만 user level code에 의해 트리거 되는 ident로 식별되는 사용자 이벤트를 설정한다. |