libev 라 이브 러 리 사용법
libev 는 고성능 이벤트 순환 라 이브 러 리 로 libevent 라 이브 러 리 보다 성능 이 좋 으 며 epoll 모델 을 기반 으로 한 패키지 입 니 다.Nodejs 는 그것 을 베이스 라 이브 러 리 로 사용 하 는 것 이다.libev 의 공식 문 서 는 여기 있 습 니 다. 문서 가 비교적 깁 니 다.본 고 는 안의 예 를 결합 하여 그것 의 용법 에 대해 간단 한 정 리 를 한다.
Contents
먼저 공식 적 인 예 부터 시작한다.
// a single header file is required
#include <ev.h>
#include <stdio.h> // for puts
// every watcher type has its own typedef'd struct
// with the name ev_TYPE
ev_io stdin_watcher;
ev_timer timeout_watcher;
// all watcher callbacks have a similar signature
// this callback is called when data is readable on stdin
static void
stdin_cb (EV_P_ ev_io *w, int revents)
{
puts ("stdin ready");
// for one-shot events, one must manually stop the watcher
// with its corresponding stop function.
ev_io_stop (EV_A_ w);
// this causes all nested ev_run's to stop iterating
ev_break (EV_A_ EVBREAK_ALL);
}
// another callback, this time for a time-out
static void
timeout_cb (EV_P_ ev_timer *w, int revents)
{
puts ("timeout");
// this causes the innermost ev_run to stop iterating
ev_break (EV_A_ EVBREAK_ONE);
}
int
main (void)
{
// use the default event loop unless you have special needs
struct ev_loop *loop = EV_DEFAULT;
// initialise an io watcher, then start it
// this one will watch for stdin to become readable
ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ);
ev_io_start (loop, &stdin_watcher);
// initialise a timer watcher, then start it
// simple non-repeating 5.5 second timeout
ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.);
ev_timer_start (loop, &timeout_watcher);
// now wait for events to arrive
ev_run (loop, 0);
// break was called, so exit
return 0;
}
이 예 는 먼저 이벤트 순환 을 만 든 다음 두 개의 이 벤트 를 등 록 했 습 니 다. 표준 입력 이벤트 와 시간 초과 이 벤트 를 읽 습 니 다.터미널 입력 이나 시간 초과 후 이벤트 순환 을 끝 냅 니 다.
이벤트 순환
libev 를 사용 하 는 핵심 은 이벤트 순환 입 니 다. ev 를 사용 할 수 있 습 니 다.default_loop 또는 evloop_new 함수 가 순환 을 만 들 거나 EV 를 직접 사용 합 니 다.DEFAULT 매크로, 구별 은 evdefault_loop 에서 만 든 이벤트 순환 은 스 레 드 가 안전 한 것 이 아니 라 evloop_new 가 만 든 이벤트 순환 은 신호 와 하위 프로 세 스 의 관찰 기 를 포착 할 수 없습니다.대부분의 경우 아래 와 같이 사용 할 수 있 습 니 다.
if (!ev_default_loop (0))
fatal ("could not initialise libev, bad $LIBEV_FLAGS in environment?");
또는 백 엔 드 를 명확 하 게 선택 하 십시오:
struct ev_loop *epoller = ev_loop_new (EVBACKEND_EPOLL | EVFLAG_NOENV);
if (!epoller)
fatal ("no epoll found here, maybe it hides under your chair");
동적 분배 순환 이 필요 하 다 면 ev 를 사용 하 는 것 을 권장 합 니 다.loop_new 와 evloop_destroy 。
하위 프로 세 스 를 만 든 후 이벤트 순환 을 사용 하려 면 하위 프로 세 스에 서 ev 를 호출 해 야 합 니 다.default_fork 또는 evloop_fork 는 백 엔 드 의 커 널 상 태 를 다시 초기 화 합 니 다. 각각 ev 에 대응 합 니 다.default_loop 와 evloop_new 에서 사용 합 니 다.
ev_run 시작 이벤트 순환.두 번 째 매개 변 수 는 0 일 때 활동 하지 않 은 이벤트 모니터 나 ev 를 호출 할 때 까지 계속 실행 되 고 처 리 됩 니 다.break 。다른 두 개의 수 치 는 EVRUN 이다.NOWAIT 와 EVRUNONCE 。
ev_break 에서 이벤트 순환 을 뛰 어 넘 습 니 다.두 번 째 매개 변 수 는 EVBREAK 입 니 다.ONE 혹은 EVBREAKALL 에서 가장 안쪽 으로 튀 어 나 온 ev 를 지정 합 니 다.run 또는 모든 포 함 된 evrun 。
ev_suspend 와 evresume 은 프로그램 이 끊 겼 을 때 이벤트 순환 을 일시 정지 하고 다시 시작 하 는 데 사 용 됩 니 다.
옵 저 버
다음은 관찰 기 를 만 듭 니 다. 주로 유형, 트리거 조건, 리 셋 함 수 를 포함 합 니 다.이벤트 순환 에 등록 하고 등록 조건 을 충족 시 킬 때 관찰 기 를 터치 하여 리 셋 함 수 를 호출 합 니 다.
위의 예 에는 IO 관찰 기와 타이머 관찰 기 가 포함 되 어 있 으 며 주기 적 관찰 기, 신호 관찰 기, 파일 상태 관찰 기 등 도 있다.
관찰 기 초기 화 및 설정 evinit 와 evTYPE_set, ev 직접 사용 가능TYPE_init 。
특정 이벤트 순환 에 관찰 기 를 시작 하여 ev 사용TYPE_start 。 ev_TYPE_stop 관찰 기 를 멈 추고 메모 리 를 방출 합 니 다.
libev 는 관찰 기 를 4 가지 상태 로 나 누 었 습 니 다. 초기 화, 시작 / 활동, 대기, 정지.
libev 의 관찰 기 는 우선 순위 도 지원 합 니 다.
서로 다른 유형의 관찰 기 는 상세 하 게 설명 하지 않 고 공식 적 인 예 만 여기에 붙 여 라.
ev_io
표준 입력 가 져 오기:
static void
stdin_readable_cb (struct ev_loop *loop, ev_io *w, int revents)
{
ev_io_stop (loop, w);
.. read from stdin here (or from w->fd) and handle any I/O errors
}
ev_io stdin_readable;
ev_io_init (&stdin_readable, stdin_readable_cb, STDIN_FILENO, EV_READ);
ev_io_start (loop, &stdin_readable);
ev_timer
60s 를 만 든 후 시작 하 는 타이머:
static void
one_minute_cb (struct ev_loop *loop, ev_timer *w, int revents)
{
.. one minute over, w is actually stopped right here
}
ev_timer mytimer;
ev_timer_init (&mytimer, one_minute_cb, 60., 0.);
ev_timer_start (loop, &mytimer);
10s 시간 초 과 된 시간 초 과 를 만 듭 니 다:
static void
timeout_cb (struct ev_loop *loop, ev_timer *w, int revents)
{
.. ten seconds without any activity
}
ev_timer mytimer;
ev_timer_init (&mytimer, timeout_cb, 0., 10.); /* note, only repeat used */
ev_timer_again (&mytimer); /* start timer */
ev_run (loop, 0);
// and in some piece of code that gets executed on any "activity":
// reset the timeout to start ticking again at 10 seconds
ev_timer_again (&mytimer);
ev_periodic
한 시간 단위 의 주기 타이머 만 들 기:
static void
clock_cb (struct ev_loop *loop, ev_periodic *w, int revents)
{
... its now a full hour (UTC, or TAI or whatever your clock follows)
}
ev_periodic hourly_tick;
ev_periodic_init (&hourly_tick, clock_cb, 0., 3600., 0);
ev_periodic_start (loop, &hourly_tick);
또는 사용자 정의 주기 계산 방식:
#include <math.h>
static ev_tstamp
my_scheduler_cb (ev_periodic *w, ev_tstamp now)
{
return now + (3600. - fmod (now, 3600.));
}
ev_periodic_init (&hourly_tick, clock_cb, 0., 0., my_scheduler_cb);
현재 시간 부터 시작 하려 면:
ev_periodic hourly_tick;
ev_periodic_init (&hourly_tick, clock_cb,
fmod (ev_now (loop), 3600.), 3600., 0);
ev_periodic_start (loop, &hourly_tick);
ev_signal
SIGINT 를 받 았 을 때 정리 하기:
static void
sigint_cb (struct ev_loop *loop, ev_signal *w, int revents)
{
ev_break (loop, EVBREAK_ALL);
}
ev_signal signal_watcher;
ev_signal_init (&signal_watcher, sigint_cb, SIGINT);
ev_signal_start (loop, &signal_watcher);
ev_child
fork 새 프로 세 스 입 니 다. 프로 세 스 가 끝 날 때 까지 child 프로 세 서 를 설치 합 니 다.
ev_stat
ev_child cw;
static void
child_cb (EV_P_ ev_child *w, int revents)
{
ev_child_stop (EV_A_ w);
printf ("process %d exited with status %x
", w->rpid, w->rstatus);
}
pid_t pid = fork ();
if (pid < 0)
// error
else if (pid == 0)
{
// the forked child executes here
exit (1);
}
else
{
ev_child_init (&cw, child_cb, pid, 0);
ev_child_start (EV_DEFAULT_ &cw);
}
/ etc / passwd 에 변화 가 있 는 지 모니터링:
기타 기능
static void
passwd_cb (struct ev_loop *loop, ev_stat *w, int revents)
{
/* /etc/passwd changed in some way */
if (w->attr.st_nlink)
{
printf ("passwd current size %ld
", (long)w->attr.st_size);
printf ("passwd current atime %ld
", (long)w->attr.st_mtime);
printf ("passwd current mtime %ld
", (long)w->attr.st_mtime);
}
else
/* you shalt not abuse printf for puts */
puts ("wow, /etc/passwd is not there, expect problems. "
"if this is windows, they already arrived
");
}
...
ev_stat passwd;
ev_stat_init (&passwd, passwd_cb, "/etc/passwd", 0.);
ev_stat_start (loop, &passwd);
libev 는 사용자 정의 관찰 기, 스 레 드 에서 사용 하 는 등 다른 유용 한 기능 도 많이 지원 합 니 다. 공식 문 서 를 보십시오.
파 이 썬 바 인 딩
libev 는 C 와 C + + 인 터 페 이 스 를 제공 하고 많은 다른 언어 도 대응 하 는 제3자 인 터 페 이 스 를 제공 합 니 다.
libev 의 Python 확장 은 pyev 입 니 다. 문서 참조http://packages.python.org/pyev/ 。
libev 의 기본 기능 은 pyev 에서 기본적으로 대응 하 는 바 인 딩 이 있 습 니 다.
공식 적 으로 두 가지 예 를 들 어 그 중의 기본 적 인 용법 을 보 여 주 는 예 를 들 어
import signal
import pyev
def sig_cb(watcher, revents):
print("got SIGINT")
loop = watcher.loop
# optional - stop all watchers
if loop.data:
print("stopping watchers: {0}".format(loop.data))
while loop.data:
loop.data.pop().stop()
# unloop all nested loop
print("stopping the loop: {0}".format(loop))
loop.stop(pyev.EVBREAK_ALL)
def timer_cb(watcher, revents):
watcher.data += 1
print("timer.data: {0}".format(watcher.data))
print("timer.loop.iteration: {0}".format(watcher.loop.iteration))
print("timer.loop.now(): {0}".format(watcher.loop.now()))
if __name__ == "__main__":
loop = pyev.default_loop()
# initialise and start a repeating timer
timer = loop.timer(0, 2, timer_cb, 0)
timer.start()
# initialise and start a Signal watcher
sig = loop.signal(signal.SIGINT, sig_cb)
sig.start()
loop.data = [timer, sig] # optional
# now wait for events to arrive
loop.start()
링크:
http://www.yeolar.com/note/2012/12/16/libev/
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
집 서버 설계 (하드웨어 편)자신의 Redmine이나 ownCloud를 운용하기 위해 사쿠라 VPS, DigitalOcean, OpenShift 등을 놀랐습니다만, 침착 해 왔으므로 현상을 정리하고 싶습니다. 먼저 하드웨어 구성을 정리합니다. ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.