KQUEUE(2)

명칭
kqueue, kevent - 커널 이벤트 통지 메카니즘

프로그램 라이브러리
libc

서식
<sys/types.h> <sys/event.h> <sys/time.h> int kqueue(void) int kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout) EV_SET(&kev, ident, filter, flags, fflags, data, udata)

해설
kqueue() (은)는, 필터로 불리는 작은 커널 코드의 실행 결과에 근거해, 이벤트의 발생이나 있는 상태의 성립을 유저에게 통지하는 일반적인 방법을 제공합니다. kevent 는 (ident, filter)의 페어에 의해 식별됩니다. 여기서, ident 는 식별자, filter 는 필터를 나타냅니다. 1 개의 kqueue 에는, 같은 kevent 가 복수 존재할 수 없습니다.

필터는, kevent 의 초기 등록시에 이전부터 존재한 상태를 검출하기 위해서 실행됩니다. 또, 어느 이벤트가 평가를 위해서(때문에) 필터에게 건네질 때마다 실행됩니다. 상태를 보고 해야 한다고 필터가 결정되었을 경우에는, 그 kevent 는 유저가 회수할 수 있도록(듯이) kqueue 에 놓여집니다.

유저가 kqueue 로부터 kevent 를 회수하려고 했을 때에도, 필터가 실행됩니다. 필터의 실행에 의해, 그 이벤트를 방아쇠 한 상태가 성립하고 있지 않는 것 하지만 나타났을 경우에는, 그 kevent 는 kqueue 로부터 삭제되어 유저에게 건네지지 않습니다.

필터를 방아쇠 하는 이벤트가 다수 있는 경우에서도, kqueue 안에 kevent 가 복수 놓여지는 것은 아닙니다. 대신에, 필터는 복수의 이벤트를 단일의 kevent 구조체에 모읍니다. 파일 기술자에 대한다 close() 의 호출은, 그 기술자를 참조하고 있는 모든 kevent 를 삭제합니다.

kqueue() (은)는 신규의 커널 이벤트 큐를 생성해 기술자를 돌려줍니다. 큐는 fork(2) 그리고 생성된 child process에는 계승되지 않습니다. 그렇지만, RFFDG 플래그없이 rfork(2) 하지만 불려 갔을 경우에는, 기술자 테이블이 공유되어 2 개(살)의 프로세스간에 kqueue 의 공유가 가능하게 됩니다.

kevent() (은)는, 큐에 이벤트를 등록해, 보류중의 모든 이벤트를 유저에게 돌려주기 위해서(때문에) 사용됩니다. changelist 하 kevent 구조체의 배열에의 포인터입니다. 이 구조체는 <sys/event.h> 그리고 정의되고 있습니다. 보류중의 이벤트를 큐로부터 읽어들이기 전에, changelist 에 포함되어 있는 모든 변경을 적용합니다. nchanges 하 changelist 의 크기를 줍니다. eventlist (은)는 kevent 구조체의 배열에의 포인터입니다. nevents 하 eventlist 의 크기를 결정합니다. timeout 하지만 NULL 가 아닌 포인터의 경우에는, timespec 구조체이다고 해석되어, 이벤트를 기다리는 최대 대기 시간을 지정합니다. timeout 하지만 NULL 포인터의 경우에는, kevent() (은)는 무기한으로 기다립니다. 폴링의 효과를 얻기 위해서(때문에)는, timeout 인수에, 0 을 나타낸다 timespec 구조체를 가리키는 비 NULL 의 포인터를 주어야 합니다. changelist (와)과 eventlist 용으로 같은 배열을 사용할 수가 있습니다.

EV_SET() (은)는 kevent 구조체의 초기화를 간단하게 하는 매크로입니다.

kevent 구조체는 다음과 같이 정의되고 있습니다.

    struct kevent {
    	uintptr_t ident;	/* 이 이벤트의 식별자 */
    	short	  filter;	/* 이벤트의 필터 */
    	u_short	  flags;	/* kqueue 의 액션 플래그 */
    	u_int	  fflags;	/* 필터 플래그치 */
    	intptr_t  data;		/* 필터 데이터치 */
    	void	  *udata;	/* 불투명한 유저 데이터 식별자 */
    };

struct kevent 의 필드는 이하와 같습니다.

ident
    이 이벤트를 식별하기 위해서 사용되는 값입니다. 엄밀한 해석은 연결시킬 수 있었던 필터에 의해 결정됩니다만, 보통은 파일 기술자로서 해석됩니다.

filter
    이 이벤트를 처리하기 위해서 사용되는 커널 필터를 식별합니다. 미리 정의된 시스템 필터는 후술 되어 있습니다.

flags
    이벤트 발생시에 실행해야 할 액션입니다.

fflags
    필터 고유의 플래그입니다.

data
    필터 고유의 데이터의 값입니다.

udata
    변경되지 않고 커널을 통해 건네받는 불투명한 유저 정의의 값입니다.

flags 필드는 이하의 값을 포함할 수가 있습니다.

EV_ADD
    이벤트를 kqueue 에 추가합니다. 기존의 이벤트를 다시 추가하면(자), 원의 이벤트의 파라미터가 변경됩니다. 중복 하는 엔트리가 생기는 것은 아닙니다. 이벤트를 추가하면(자), EV_DISABLE 플래그에 의해 덧쓰기되지 않는 한은 자동적으로 유효하게 됩니다.

EV_ENABLE
    이벤트가 방아쇠 되었을 경우에, kevent() 하지만 그 이벤트를 돌려주는 것을 허가합니다.

EV_DISABLE
    이벤트를 무효로 합니다. 이것에 의해 kevent() (은)는 그 이벤트를 돌려주지 않게 됩니다. 필터 자신은 무효로 되지 않습니다.

EV_DELETE
    kqueue 로부터 이벤트를 삭제합니다. 파일 기술자가 연결시킬 수 있고 있는 이벤트는, 그 기술자의 마지막 클로우즈시에 자동적으로 삭제됩니다.

EV_ONESHOT
    필터가 최초 방아쇠 되었을 때에 마셔, 이벤트가 돌아가도록(듯이) 합니다. 유저가 이벤트를 kqueue 로부터 회수한 다음에, 그 이벤트는 삭제됩니다.

EV_CLEAR
    유저가 이벤트를 회수한 후에, 그 상태를 리셋트 합니다. 이것은 현재 상태가 아니고, 상태의 변화를 보고하는 필터에 유용합니다. 몇개의 필터는 내부에서 이 플래그를 자동적으로 세트 하고 있다 일지도 모르는 것에 주의해 주세요.

EV_EOF
    그 필터 고유의 EOF 상태인 것을 나타내기 위해서(때문에), 필터가 이 플래그를 세트 하는 일이 있습니다.

EV_ERROR
    후술의 반환값 (을)를 참조해 주세요.

미리 정의된 시스템 필터를 다음에 나타냅니다. 인수는 kevent 구조체의 fflags 및 data 필드를 경유해 교환할 수가 있습니다.

EVFILT_READ
    식별자에 기술자를 인수로서 취합니다. 읽어들여 가능한 데이터가 있을 때 돌아옵니다. 이 필터의 행동은, 그 기술자의 형태에 의해 조금 다릅니다.

    소켓  사전에 listen() 에게 건네진 소켓의 경우, 보류중의 다음의 접속이 있을 때 돌아옵니다. data 에는 listen 의 백 로그 (backlog)의 크기가 들어가 있습니다.

        그 외의 소켓 기술자의 경우, 소켓 버퍼의 SO_RCVLOWAT 의 값을 기준으로 해, 읽어들이는 데이터가 있을 때 돌아옵니다. 필터를 추가할 경우에, fflags 에 NOTE_LOWAT 를 설정해 data 에 새로운 최저 기준치를 지정하는 것으로써, 이 값을, 필터마다의 최저 기준치로 덧쓰기하는 것이 가능합니다. 돌아올 때는, data 에는 소켓 버퍼안의 바이트수가 들어가 있습니다.

        소켓의 읽기측이 절단 되었을 경우에는, 필터는 flags 에 EV_EOF 도 설정합니다. 여기서 에러가 일어났을 경우에는, fflags 에 소켓 에러를 돌려줍니다. 소켓 버퍼안에 보류중의 데이터가 남아 있어도, (접속이 끊어진 것을 나타낸다) EOF 가 돌려주어지는 일이 있습니다.

    vnode
        파일 포인터가 파일의 최후 (EOF)가 아닐 때에 돌아옵니다. data (은)는 현재 위치로부터 파일의 최후 (EOF)까지의 오프셋(offset)가 들어가 있습니다. 이 값은 부일지도 모릅니다.

    FIFO 와 파이프
        읽어들여야 할 데이터가 있을 때 돌아옵니다. data 에는 유효한 바이트수가 들어가 있습니다.

        마지막 기입측이 절단 했을 때에, 필터는 flags 에 EV_EOF 를 세트 합니다. EV_CLEAR 를 건네주는 것으로, 이 플래그를 클리어 할 수가 있어 필터는 데이터를 읽어들일 수 있도록(듯이) 되는 것을 돌아오지 않고 다시 기다립니다.

EVFILT_WRITE
    식별자에 기술자를 인수로서 취합니다. 그 기술자가 기입해 가능하게 될 때마다 돌아옵니다. 소켓, 파이프 및 FIFO 에서는, data 에는 기입 버퍼의 나머지 area의 크기가 들어가 있습니다. 읽기측이 절단 했을 때에, 필터는 EV_EOF 를 세트 합니다. FIFO 의 경우, EV_CLEAR 를 사용해 이것을 클리어 할 수가 있습니다. 이 필터는 vnode 를 서포트하고 있지 않는 것에 주의해 주세요.

    소켓의 경우, 최저 기준치 및 소켓 에러의 취급은 EVFULT_READ 의 경우와 같습니다.

EVFILT_AIO
    비동기 입출력 리퀘스트의 sigevent 부분의, sigev_notify_kqueue 에는 이벤트를 부가하는 kqueue 의 기술자를 넣어 sigev_value 에는 udata 의 값을 입금시켜 sigev_notify 에는 SIGEV_KEVENT 를 넣어, 비동기 입출력 리퀘스트를 묻습니다. aio_* 함수가 불려 갔을 때, 그 이벤트는 지정된 kqueue 에 등록됩니다. aio_* 함수가 돌려주었다 aiocb 구조체를 ident 인수에 세트 합니다. 이 필터는 aio_error 와 같은 조건으로 돌아옵니다.

    다른 방법으로서 ident 에 kqueue 기술자를 넣어 kevent 구조체를 초기화해, 그 주소를 비동기 리퀘스트의 aio_lio_opcode 필드에 두는 일도 가능합니다. 그렇지만, 이 접근는 64 비트 포인터의 아키텍쳐에서는 동작하지 않을 것입니다 해, 목표로 해야 하는 것이 아닙니다.

EVFILT_VNODE
    파일 기술자를 식별자에, 감시하는 이벤트를 fflags 에 인수로서 취합니다. 지정한 기술자에 대해 요구된 이벤트가 1 개 이상 발생했을 때에 돌아옵니다. 감시하는 이벤트를 이하에 나타냅니다.

    NOTE_DELETE
        기술자가 참조하는 파일에 대해 unlink() 하지만 불렸습니다.

    NOTE_WRITE
        기술자가 참조하는 파일에 대해 기입이 일어났습니다.

    NOTE_EXTEND
        기술자가 참조하는 파일의 사이즈가 확장되었습니다.

    NOTE_ATTRIB
        기술자가 참조하는 파일의 속성이 변경되었습니다.

    NOTE_LINK
        파일의 링크수가 변경되었습니다.

    NOTE_RENAME
        기술자가 참조하는 파일이 rename 되었습니다.

    NOTE_REVOKE
        파일에의 액세스가 revoke(2) 에 의해 무효로 되었는지, 혹은, 하위층의 파일 시스템이 mount 되고 있지 않습니다.

    돌아올 때, fflags 에 필터를 방아쇠 한 이벤트가 들어가 있습니다.

EVFILT_PROC
    감시하는 프로세스 ID 를 식별자에, 감시하는 이벤트를 fflags 에 인수로서 취합니다. 요구된 이벤트를 1 개 이상 프로세스가 실행할 경우에 돌아옵니다. 어느 프로세스가 다른 프로세스를 정상적으로 볼 수가 있는 경우에는, 이벤트를 그 프로세스에 연결시킬 수가 있습니다. 감시하는 이벤트를 다음에 나타냅니다.

    NOTE_EXIT
        프로세스가 종료했습니다.

    NOTE_FORK
        프로세스가 fork() (을)를 불렀습니다.

    NOTE_EXEC
        프로세스가 execve(2) 또는 유사한 호출에 의해, 신규의 프로세스를 실행했습니다.

    NOTE_TRACK
        fork() 의 호출을 넘어, 프로세스를 추적합니다. parent process는 fflags 필드에 NOTE_TRACK 를 세트 해 돌아와, 한편, child process는 fflags 에 NOTE_CHILD 를 data 에 parent process의 PID 를 세트 해 돌아옵니다.

    NOTE_TRACKERR
        이 플래그는, 시스템이 child process에의 이벤트를 연결시킬 수가 없었을 때에 돌아옵니다. 통상, 이것은 자원의 제한에 의해 생깁니다.

    돌아올 때, fflags (은)는 필터를 방아쇠 한 이벤트가 들어가 있습니다.

EVFILT_SIGNAL
    감시하는 시그널 번호를 식별자에 인수로서 취합니다. 주어진 시그널이 프로세스에 배송되었을 때에 돌아옵니다. 이것은 signal() 및 sigaction() 의 구조와 공존해, 낮은 우선 순위를 가지고 있습니다. 비록 그 시그널이 SIG_IGN 와 마크 되고 있었다고 해도, 필터는 프로세스에 배송되려고 한 시그널 모두를 기록합니다. 통상의 시그널 배송 처리의 뒤에, 이벤트 통지가 발생합니다. data 에는 kevent() (을)를 마지막으로 호출하고 나서의 시그널 발생의 회수가 돌아갑니다. 이 필터는 내부에서 자동적으로 EV_CLEAR 플래그를 세트 합니다.

EVFILT_TIMER
    ident 그리고 식별되는, 임의의 타이머를 설정합니다. 타이머를 추가하는 경우, data (은)는 타임 아웃을 밀리 세컨드 단위로 지정합니다. EV_ONESHOT 를 지정하지 않는 한, 타이머는 주기적입니다. data 에는, kevent() (을)를 마지막으로 호출하고 나서의 타임 아웃의 회수가 돌아갑니다. 이 필터는 내부에서 자동적으로 EV_CLEAR 플래그를 세트 합니다.

반환값
kqueue() (은)는 신규의 커널 이벤트 큐를 생성해, 파일 기술자를 돌려줍니다. 커널 이벤트 큐의 생성시에 에러가 있었을 경우에는, 값 -1 이 돌려주어져 errno 가 세트 됩니다.

kevent() 하 eventlist 에 배열되고 있는 이벤트의 수를 돌려줍니다. 이 수는, 최대 nevents 그리고 주어진 값까지입니다. changelist 의 요소의 처리중에 에러가 발생해, 한편 eventlist 에 충분한 여지가 있는 경우에는, flags 에 EV_ERROR 하지만 세트 되어 data 에 시스템 우류가 세트 된 이벤트가, eventlist 에 놓여집니다. 아주 없으면, -1 하지만 돌려주어 errno 하지만 에러 상태를 나타내기 위해서(때문에) 세트 됩니다. 마감 시간의 경우에는, kevent() (은)는 0 을 돌려줍니다.

에러
kqueue() 함수는 이하의 경우에 실패합니다.

[ENOMEM]
    커널이 커넬 큐를 위한 충분한 메모리의 할당해에 실패했습니다.

[EMFILE]
    프로세스의 기술자 테이블이 만배입니다.

[ENFILE]
    시스템 파일 테이블이 만배입니다.

kevent() 함수는 이하의 경우에 실패합니다.

[EACCES]
    프로세스가 필터를 등록하는 권한을 가지고 있지 않습니다.

[EFAULT]
    kevent 구조체의 읽어들여 또는 기입으로 에러가 있었습니다.

[EBADF]
    지정된 기술자가 유효하지는 않습니다.

[EINTR]
    마감 시간전이나, 돌아오기 위한 어떠한 이벤트가 kqueue 에 놓여지기 전에, 시그널이 배송되었습니다.

[EINVAL]
    지정된 시한 또는 필터가 무효입니다.

[ENOENT]
    수정 또는 삭제되어야 할 이벤트가 발견되지 않습니다.

[ENOMEM]
    이벤트 등록을 위한 메모리가 없습니다.

[ESRCH]
    연결시키기 위해서(때문에) 지정한 프로세스가 존재하지 않습니다.

관련 항목
aio_error(2), aio_read(2), aio_return(2), poll(2), read(2), select(2), sigaction(2), write(2), signal(3)

역사
kqueue() 및 kevent() 함수는 FreeBSD 4.1 그리고 처음으로 등장했습니다.

저자
kqueue() 시스템과 이 메뉴얼 페이지는 Jonathan Lemon <jlemon@FreeBSD.org> 하지만 썼습니다.

버그
현재는, UFS 파일 시스템에 속하지 않는다 vnode(9) (을)를 감시할 수가 없습니다.