2011-02-11 21 views

Odpowiedz

6

To bardzo proste z Pythona 3.

Poniżej jest testowany z Pythona 3.3.3 (wreszcie!):

#! /usr/bin/python3 

import signal 
import time, os 

def callme(num, frame): 
    pass 

# register the callback: 
signal.signal(signal.SIGUSR1, callme) 

print("py: Hi, I'm %d, talk to me with 'kill -SIGUSR1 %d'" 
     % (os.getpid(),os.getpid())) 

# wait for signal info: 
while True: 
    siginfo = signal.sigwaitinfo({signal.SIGUSR1}) 
    print("py: got %d from %d by user %d\n" % (siginfo.si_signo, 
              siginfo.si_pid, 
              siginfo.si_uid)) 
-3

Uważam, że nie jest to możliwe - system operacyjny po prostu nie przekazuje tych informacji do procesu docelowego.

+0

Dzięki za wyjaśnienie. –

-2

Nie, to niemożliwe, system operacyjny (prawdopodobnie * nix) po prostu nie podaje tych informacji. Będziesz musiał użyć innego rodzaju IPC do komunikacji z procesów potomnych do rodzica. Jeśli jeszcze go nie używasz, powinieneś sprawdzić moduł subprocess, który ułatwia tego typu rzeczy.

Na przykład, jeśli skonfigurujesz potoki z procesów potomnych do rodzica, możesz poprosić dziecko, aby napisało wiadomość do potoku, gdy wcześniej wysłałeś sygnał. Twój proces nadrzędny może używać wywołania select, aby czekać, aż otrzyma wiadomość od jednego z dzieci.

To tylko jeden ze sposobów podejścia do problemu IPC; można również pracować z modułem sockets lub multiprocessing, wśród innych podejść. Nie wiedząc więcej o tym, co próbujesz zrobić, trudno jest ci udzielić więcej porad.

+0

dzięki ... Korzystam już z modułu podprocesu. używam wait(), aby czekać. Ale chciałem użyć signal.pause(), która mogłaby sprawić, że proces rodzicielski spał, dopóki jedno z dzieci nie umrze. Pozwoli to zaoszczędzić cykle procesora. –

5

POSIX Linux ma dostarczania tych informacji, sprawdź sigaction Man (2): http://linux.die.net/man/2/sigaction

w C, udało mi się dostać to działa w prosty sposób:

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

static void my_handler(int signum, siginfo_t *siginfo, void *context) { 
    printf("Got signal '%d' from process '%d' of user '%d'\n", 
     signum, siginfo->si_pid, siginfo->si_uid); 
} 

int main(void) { 
    struct sigaction act; 
    memset(&act, '\0', sizeof(act)); 
    act.sa_sigaction = &my_handler; 
    act.sa_flags = SA_SIGINFO; 
    sigaction(SIGUSR1, &act, NULL); 
    printf("Hi, my pid is %d\ntalk to me with 'kill -SIGUSR1 %d'\n", getpid(), getpid()); 
    while(1) 
     sleep(1000); 
    return 0; 
} 

działa całkiem dobrze z moim 3,1 .6 jądro wanilii i gcc 4.4.5 - ale nie mogłem znaleźć żadnego wsparcia dla niego w pythonie.

więc zacząłem próbować zbudować coś na własną rękę (ale ponieważ nigdy nie zrobiłem C/python-Interaction wcześniej, to pewnie jakoś skręcone w górę ...)

jestem mniej lub bardziej trzymając się blisko Podany przykład http://docs.python.org/extending/extending.html i budowy modułu według http://docs.python.org/extending/building.html#building

sigpidmodule.c

#include <Python.h> 
#include <signal.h> 

static PyObject *callback = NULL; 

static void direct_handler(int signum, siginfo_t *siginfo, void *context) { 
    int pid = (int) siginfo->si_pid; 
    printf("c: Signal reached c handler: signum=%d, pid=%d, handler=%p\n", 
     signum, pid, callback); 
    if (callback != NULL) { 
     PyObject *arglist = Py_BuildValue("(i,i)", signum, pid); 
     printf("c: calling python callback\n"); 
     PyObject *result = PyObject_CallObject(callback, arglist); 
     // decrease reference counter 
     Py_DECREF(arglist); 
     Py_DECREF(result); 
    } 
} 

static PyObject *sigpid_register(PyObject *self, PyObject *args) { 
    PyObject *result = NULL; 
    PyObject *temp; 
    if (PyArg_ParseTuple(args, "O:set_callback", &temp)) { 
     if (!PyCallable_Check(temp)) { 
      PyErr_SetString(PyExc_TypeError, "parameter must be callable"); 
      return NULL; 
     } 
    } 
    Py_XINCREF(temp);  // inc refcount on new callback 
    Py_XDECREF(callback); // dec refcount on old callback 
    callback = temp;  // replace old callback with new 
    printf("c: callback now: %p\n", (void *) callback); 
    // return None 
    Py_RETURN_NONE; 
} 

static PyObject *sigpid_ping(PyObject *self, PyObject *args) { 
    if (callback != NULL) { 
     PyObject *arglist = Py_BuildValue("(i,i)", 42, 23); 
     printf("c: calling callback...\n"); 
     PyObject *result = PyObject_CallObject(callback, arglist); 
     // decrease ref counters 
     Py_DECREF(arglist); 
     Py_DECREF(result); 
    } 
    // return None: 
    Py_RETURN_NONE; 
} 

static PyMethodDef SigPidMethods[] = { 
    {"register", sigpid_register, METH_VARARGS, "Register callback for SIGUSR1"}, 
    {"ping", sigpid_ping, METH_VARARGS, "Test if callback is working"}, 
    {NULL, NULL, 0, NULL}, 
}; 

PyMODINIT_FUNC initsigpid(void) { 
    // initialize module: 
    (void) Py_InitModule("sigpid", SigPidMethods); 
    // set sighandler: 
    struct sigaction act; 
    memset(&act, '\0', sizeof(act)); 
    act.sa_sigaction = &direct_handler; 
    act.sa_flags = SA_SIGINFO; 
    sigaction(SIGUSR1, &act, NULL); 
} 

setup.py do budowy modułu:

from distutils.core import setup, Extension 

module1 = Extension('sigpid', sources= ['sigpidmodule.c']) 

setup (name='SigPid', version='1.0', 
    description='SigPidingStuff', 
    ext_modules = [module1]) 

budowę modułu z

python setup.py build 

Tak, to wciąż brakuje skrypt python za pomocą modułu: test.py

import sigpid 
import time, os 

def callme(num, pid): 
    ''' 
    Callback function to be called from c module 
    ''' 
    print "py: got %d from %d\n" % (num, pid) 

# register the callback: 
sigpid.register(callme) 

print "py: Hi, I'm %d, talk to me with 'kill -SIGUSR1 %d'" %(os.getpid(),os.getpid()) 
# wait for signal while doing nothing: 
while True: 
    time.sleep(1) 

Wszystko działa bardzo dobrze ...do:

python test.py 

lub jak mam właściwie nazwać to, aby uzyskać prawo lib:

PYTHONPATH=build/lib.linux-i686-2.6 python test.py 

wyjściowa:

c: callback now: 0xb744f534 
py: Hi, I'm 2255, talk to me with 'kill -SIGUSR1 2255' 
(from other term: kill -SIGUSR1 2255) 
c: Signal reached c handler: signum=10, pid=2948, handler=0xb744f534 
c: calling python callback 
Segmentation fault 

nie wiem dlaczego mam to segfault i brakuje mi pomysłów, aby to naprawić. Myślę, że to musi mieć coś wspólnego z interakcją c i Pythona (mogę myśleć o pewnych przyczynach, ale to wszystko tylko zgadywanie). Może ktoś z większym doświadczeniem w interakcji c-python może pomóc (lub przynajmniej wyjaśnić, jaki jest dokładnie problem). Możemy mieć sposób na rozwiązanie tego problemu, przynajmniej na Linuksie.

Powiązane problemy