2011-02-11 28 views

Trả lời

6

Nó rất đơn giản với python 3.

Sau đây là thử nghiệm với python 3.3.3 (cuối cùng!):

#! /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

Tôi tin rằng điều đó là không thể - hệ điều hành chỉ không chuyển thông tin này đến quy trình mục tiêu.

+0

Cảm ơn để làm rõ. –

-2

Không, không thể, hệ điều hành (có lẽ là * nix) không cung cấp thông tin này. Bạn sẽ cần phải sử dụng một số loại IPC khác để giao tiếp từ các tiến trình con của bạn với cha mẹ. Nếu bạn chưa sử dụng nó, bạn nên kiểm tra các mô-đun subprocess mà làm cho các loại điều dễ dàng.

Ví dụ: nếu bạn thiết lập đường ống từ con của bạn xử lý cho cha mẹ, bạn có thể yêu cầu trẻ viết thông báo cho đường ống khi bạn đã gửi tín hiệu trước đó. Quy trình gốc của bạn có thể sử dụng cuộc gọi select để chờ cho đến khi nhận được tin nhắn từ một trong các trẻ em.

Đây chỉ là một cách bạn có thể tiếp cận vấn đề IPC; bạn cũng có thể làm việc với sockets hoặc mô-đun multiprocessing, trong số các cách tiếp cận khác. Không biết nhiều hơn về những gì bạn đang cố gắng làm, thật khó để cho bạn lời khuyên nào thêm.

+0

cảm ơn ... Tôi đã sử dụng mô-đun subprocess. tôi đang sử dụng wait() để chờ. Nhưng tôi muốn sử dụng signal.pause() mà có thể làm cho quá trình cha mẹ ngủ cho đến khi một trong những đứa trẻ chết. Điều này sẽ tiết kiệm chu kỳ CPU. –

5

POSIX Linux không cung cấp thông tin này, kiểm tra người đàn ông sigaction (2): http://linux.die.net/man/2/sigaction

Trong C, tôi cố gắng làm cho nó chạy một cách dễ dàng:

#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; 
} 

trình khá tốt với 3.1 của tôi .6 vanilla kernel và gcc 4.4.5 - nhưng tôi không thể tìm thấy bất kỳ sự hỗ trợ nào cho nó trong python.

Vì vậy, tôi bắt đầu để thử và xây dựng một cái gì đó một mình (nhưng kể từ khi tôi không bao giờ làm C/Python-Tương tác trước đây, nó có thể bằng cách nào đó xoắn lên ...)

tôi ít nhiều giữ gần ví dụ tại http://docs.python.org/extending/extending.html và xây dựng các mô-đun theo 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 để xây dựng các mô-đun:

from distutils.core import setup, Extension 

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

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

xây dựng các mô-đun với

python setup.py build 

Vì vậy, những gì đang còn mất tích là kịch bản python bằng cách sử dụng mô-đun: 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) 

Tất cả mọi thứ hoạt động rất tốt ...lên đến:

python test.py 

hoặc như tôi phải thực sự gọi nó là để có được quyền lib:

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

đầu ra:

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 

Tôi không biết tại sao tôi có được điều này segfault, và tôi đang hết ý tưởng để sửa nó. Tôi đoán nó phải có một cái gì đó để làm với cách c và python tương tác (Tôi có thể nghĩ ra một số lý do, nhưng đó là tất cả chỉ đoán). Có lẽ ai đó có nhiều kinh nghiệm trong tương tác c-python có thể giúp đỡ ở đây (hoặc ít nhất là giải thích, vấn đề chính xác là gì). Chúng tôi có thể có một cách để giải quyết vấn đề ở đó, ít nhất là trên Linux.

Các vấn đề liên quan