如何使用信号处理linux文件系统监视?

如何使用信号处理linux文件系统监视?

linux下c的代码原型如下:
#define _GNU_SOURCE

#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

static volatile int event_fd;

static void handler(int signum, siginfo_t *si, void *data){
event_fd = si->si_fd;
printf("info size:%d, data:%d/n", sizeof(siginfo_t), sizeof(data));
}

int main(int argc, char **argv){
struct sigaction action;
int fd;
action.sa_sigaction = handler;
sigemptyset(&action.sa_mask);
action.sa_flags = SA_SIGINFO;
sigaction(SIGRTMIN+1, &action, NULL);

fd = open("test", O_RDONLY);
fcntl(fd, F_SETSIG, SIGRTMIN+1);
fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_MULTISHOT);

fd = open(".", O_RDONLY);
fcntl(fd, F_SETSIG, SIGRTMIN+1);
fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_MULTISHOT);
while(1){
pause();
printf("got event on fd=%d/n", event_fd);
}
}


我要使用python,可以使用嵌入式方式,如果不是嵌入式方式,将会有1个以上的进程出现。
//#define _GNU_SOURCE
#include "Python.h"
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

typedef void my_handler_t(int, int);
typedef my_handler_t * my_handler;

static void * current_handler;

static volatile int event_fd;
static void default_handler(int signum, siginfo_t * siginfo, void * context){
event_fd = siginfo->si_fd;
printf("event_fd %d, %p, sizeof /n", event_fd, siginfo);
//current_handler(signum, siginfo->si_fd);

PyObject *arglist = Py_BuildValue("(ii)", signum, siginfo->si_fd);
PyObject_Print(arglist, stdout, Py_PRINT_RAW);
printf("arglist end/n");

PyGILState_STATE state;
state = PyGILState_Ensure();

Py_INCREF(arglist);
PyObject *result =
PyEval_CallObject(current_handler, arglist);
Py_DECREF(arglist);

PyGILState_Release(state);
PyObject_Print(result, stdout, Py_PRINT_RAW);
printf("-->result %p/n", result);
//TODO: PyEval_InitThreads
}

typedef void sigaction_handler_t(int, siginfo_t *, void *);
typedef sigaction_handler_t * sigaction_handler;

static PyObject * dnsig_register(PyObject *self, PyObject *args){
int signum;
PyObject *handler;
if(!PyArg_ParseTuple(args, "iO", &signum, &handler))
return NULL;
printf("%d, %p/n", signum, handler);
Py_XINCREF(handler); /* Add a reference to new callback */
//Py_XDECREF(current_handler); /* Dispose of previous callback */
current_handler = handler;

struct sigaction action;
//action.sa_sigaction=(sigaction_handler)handler;
action.sa_sigaction = default_handler;
sigemptyset(&action.sa_mask);
action.sa_flags = SA_SIGINFO;
sigaction(signum, &action, NULL);

Py_INCREF(Py_None);
return Py_None;
}

static PyMethodDef dnsigMethods[]={
{"register", dnsig_register, METH_VARARGS, "register signal handler"},
{NULL, NULL}//, 0, NULL}
};

PyMODINIT_FUNC
initdnsig(void){

(void)Py_InitModule("dnsig", dnsigMethods);
}

int main(int argc, char **argv){
/* Pass argv[0] to the Python interpreter */
Py_SetProgramName(argv[0]);

/* Initialize the Python interpreter. Required. */
Py_Initialize();

/* Add a static module */
initdnsig();

/* Define sys.argv. It is up to the application if you
want this; you can also let it undefined (since the Python
code is generally not a main program it has no business
touching sys.argv...) */
PySys_SetArgv(argc, argv);

/* Do some application specific code */
printf("Hello, brave new world/n/n");

/* Execute some Python statements (in module __main__) */
PyRun_SimpleString("import sys/n");
PyRun_SimpleString("print sys.builtin_module_names/n");
PyRun_SimpleString("print sys.modules.keys()/n");
PyRun_SimpleString("print sys.executable/n");
PyRun_SimpleString("print sys.argv/n");
PyRun_SimpleString("import dm/n");

/* Note that you can call any public function of the Python
interpreter here, e.g. call_object(). */

/* Some more application specific code */
printf("/nGoodbye, cruel world/n");

int fd;
struct sigaction action;
//action.sa_sigaction = handler;
sigemptyset(&action.sa_mask);
action.sa_flags = SA_SIGINFO;
// sigaction(SIGRTMIN+1, &action, NULL);

//fd = open("test", O_RDONLY);
//fcntl(fd, F_SETSIG, SIGRTMIN+1);
//fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_MULTISHOT);

//fd = open(".", O_RDONLY);
//fcntl(fd, F_SETSIG, SIGRTMIN+1);
//fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_MULTISHOT);
//while(1){
// pause();
// printf("got event on fd=%d/n", event_fd);
//}

Py_Exit(0);
}

具体的处理使用python来写,简单灵活多了。
#!/usr/bin/env py
#coding: UTF-8
#

import fcntl,os, signal, time, inspect, struct, traceback, dnsig;

def fmember(attr):
return attr[0]=='f';

handlerCount = 0;
def handler(signum, frame):
global handlerCount;
handlerCount += 1;
print "handle", handlerCount, time.time();
#print inspect.getmembers(frame);

#def sighandler(signum, siginfo, ucontext):
def sighandler(signum, fd):
print signum, fd;
#print signum, str(siginfo), str(ucontext);
#print struct.unpack('iiiiiilllllllllllll', str(siginfo));
pass
#

def dummy(signum):
print 'dummy', signum;
pass
#

#set event handler for SIGIO, otherwise the program will terminate
#signal.signal(signal.SIGIO, lambda signum, stack:None);
#signal.signal(signal.SIGIO, handler);
#signal.sigaction(signal.SIGRTMIN+1, sighandler);
dnsig.register(signal.SIGRTMIN+1, sighandler);
#dnsig.register(signal.SIGRTMIN+1, dummy);

watchDir="test"

filedesc = os.open(watchDir, os.O_RDONLY);
print "fd %s, signum %s, sighandler: %s" %(filedesc, signal.SIGRTMIN+1, sighandler);


count =0;

flags=[fcntl.DN_CREATE, fcntl.DN_MODIFY, fcntl.DN_RENAME];
__innerFlags=reduce(lambda x, y: x | y, flags) | fcntl.DN_MULTISHOT;
#fcntl.DN_MULTISHOT;
try:
try:
#register watching service
print 'register fcntl';
fcntl.fcntl(filedesc, fcntl.F_SETSIG, signal.SIGRTMIN+1);
fcntl.fcntl(filedesc,fcntl.F_NOTIFY, __innerFlags);
while True:
print 'start main loop'
#block until signal received
signal.pause();
print 'signal recievd', time.time();
#count+=1;
#print "EVENT", count
except KeyboardInterrupt:
print "program exit now!"
except:
traceback.print_exec();
finally:
os.close(filedesc);