Use kqueue to respond to more than one event type -


when event registered kqueue id relating event type supplied; example file descriptor used identify file watch

int kq; struct kevent ke;  kq = kqueue(); fd = open(argv[1], o_rdonly); ev_set(&ke, fd, evfilt_vnode, ev_add, note_delete | note_rename, 0, null); kevent(kq, &ke, 1, null, 0, null);  while (1) {     kevent(kq, null, 0, &ke, 1, null);     /* respond file system event */ } 

now if need respond other event types such signals need new instance of kqueue avoid conflict ident argument of kevent().

kq_sig = kqueue(); struct kevent ke_sig;  /* set handler , ignore sigint */ signal(sigint, sig_ign); ev_set(&ke_sig, sigint, evfilt_signal, ev_add, 0, 0, null); kevent(kq_sig, &ke_sig, 1, null, 0, null); while (1) {     kevent(kq_sig, null, 0, &ke_sig, 1, null);     /* respond signals */ } 

watching more 1 event type appears necessitate multiple threads act on shared state (receiving signal close file descriptor example).

is there more general mechanism sending message 1 thread using kqueue? in cases can conceive of enabling , disabling filter means of edge-triggering kevent.

the kevent struct provides info event occured:

struct kevent {          uintptr_t       ident;          /* identifier event */          int16_t         filter;         /* filter event */          uint16_t        flags;          /* general flags */          uint32_t        fflags;         /* filter-specific flags */          intptr_t        data;           /* filter-specific data */          void            *udata;         /* opaque user data identifier */  }; 

you must interested in:

  • ident in case returns either fd or sigint;
  • filter (still in case) returns either evfilt_vnode or evfilt_signal;
  • fflag in evfilt_vnode tell if file descriptor event note_delete or note_rename.

you can register 2 kevent structures single queue , use these structure members determine if event related file descriptor or signal.

here complete example demonstrates how this:

#include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <string.h> #include <sys/types.h> #include <sys/event.h> #include <sys/time.h>  int main(int argc, char** argv) {     /* single kqueue */     int kq = kqueue();     /* 2 kevent structs */     struct kevent *ke = malloc(sizeof(struct kevent) * 2);      /* initialise 1 struct file descriptor, , 1 sigint */     int fd = open(argv[1], o_rdonly);     ev_set(ke, fd, evfilt_vnode, ev_add | ev_clear, note_delete | note_rename, 0, null);     signal(sigint, sig_ign);     ev_set(ke + 1, sigint, evfilt_signal, ev_add, 0, 0, null);      /* register events */     if(kevent(kq, ke, 2, null, 0, null) < 0)         perror("kevent");      while(1) {         memset(ke, 0x00, sizeof(struct kevent));         if(kevent(kq, null, 0, ke, 1, null) < 0)             perror("kevent");          switch(ke->filter)         {             /* file descriptor event: let's examine happened file */             case evfilt_vnode:                 printf("events %d on file descriptor %d\n", ke->fflags, (int) ke->ident);                  if(ke->fflags & note_delete)                     printf("the unlink() system call called on file referenced descriptor.\n");                 if(ke->fflags & note_write)                     printf("a write occurred on file referenced descriptor.\n");                 if(ke->fflags & note_extend)                     printf("the file referenced descriptor extended.\n");                 if(ke->fflags & note_attrib)                     printf("the file referenced descriptor had attributes changed.\n");                 if(ke->fflags & note_link)                     printf("the link count on file changed.\n");                 if(ke->fflags & note_rename)                     printf("the file referenced descriptor renamed.\n");                 if(ke->fflags & note_revoke)                     printf("access file revoked via revoke(2) or underlying fileystem unmounted.");                 break;              /* signal event */             case evfilt_signal:                 printf("received %s\n", strsignal(ke->ident));                 exit(42);                 break;              /* should never happen */             default:                 printf("unknown filter\n");         }     } } 

note here use single thread, way more efficient , requires no further synchronization in user space.


Comments

Popular posts from this blog

monitor web browser programmatically in Android? -

Shrink a YouTube video to responsive width -

wpf - PdfWriter.GetInstance throws System.NullReferenceException -