2009-11-16 19 views
6

सी का उपयोग करके मैं पीआईडी ​​एक्स को बाहर निकलने के लिए कैसे इंतजार कर सकता हूं जब यह मेरी वर्तमान प्रक्रिया का बच्चा नहीं है?यदि एक्स बाल प्रक्रिया नहीं है तो मैं बाहर निकलने के लिए पीआईडी ​​एक्स की प्रतीक्षा कैसे करूं?

Kill(pid, SIGTERM); 
waitpid(pid,NULL,0); 

उपर्युक्त काम नहीं करता है क्योंकि 'पिड' एक बाल प्रक्रिया नहीं है।

उत्तर

4

this answer by chaos देखें:

सामान्य अभ्यास मार (0, पीआईडी) का उपयोग कर और मूल्य वापसी की तलाश में मतदान करने के लिए है -1 और ESRCH की को errno संकेत मिलता है कि प्रक्रिया चला गया है

man page for kill के आधार पर, यह kill(pid,0) हो सकता है। लेकिन विचार वही है।

+0

Andomar - अपने जवाब और इसी तरह के सवाल का जवाब अराजकता ओर इशारा करते हुए के लिए धन्यवाद। मुझे यह देखना चाहिए कि इसे पोस्ट करने से पहले। – Andrew

+1

यह थोड़ा सा रेसी है, क्योंकि पिड ओवरफ्लो कर सकता है और फिर एक नई प्रक्रिया को सौंपा जा सकता है, ताकि आप शुरू में सोचने की तुलना में एक और प्रक्रिया को सत्यापित कर सकें। – user175104

+1

और साथ ही, समय अंतराल में इस तरह की चीजों के लिए मतदान वास्तव में बदसूरत है, क्योंकि यह बैटरी जीवन को कम करता है, और आपके ऐप्स को पावरटॉप पर दिखाई देता है और जब तक आप शर्म में ऐसा नहीं करते हैं तब तक लोग आप पर हंसेंगे। – user175104

3

एक साफ तरीके से ऐसा करने का एकमात्र तरीका (यानी समय अंतराल में मतदान किए बिना, और पीआईडी ​​ओवरफ्लो को जोखिम के बिना) नेटलिंक cn_proc कनेक्टर (जो कि लिनक्स विशिष्ट है) का उपयोग करना है। चारों ओर उदाहरण उदाहरण या दस्तावेज नहीं है। यह एक अच्छा एपीआई नहीं है, लेकिन यह मूल रूप से इसके लिए केवल समझदार एपीआई है।

PROC_EVENT_EXIT के लिए देखो, जो घटना अपने में रुचि रखते हैं है।

http://google.com/codesearch?q=PROC_EVENT_EXIT&hl=en&btnG=Search+Code

+0

ऐसा लगता है कि यह एपीआई वही करता है जो वांछित है, लेकिन मैं इसे काम नहीं कर सकता। मैंने http://netsplit.com/2011/02/09/the-proc-connector-and-socket-filters/ पर नमूना कोड की कोशिश की और https://github.com/pturmel/startmon/blob/master/ main.c लेकिन सॉकेट से कभी भी कुछ भी नहीं पढ़ा जाता है। अगर आपको यह काम करने के बारे में विवरण था तो मुझे बहुत दिलचस्पी होगी। – a3nm

1

यह काम कर रहा है नमूना सदस्यता लें और PROC_EVENT_EXIT/PROC_EVENT_FORK घटनाओं का उपयोग कैसे करें। गिरी पर परीक्षण किया गया 3.3.8

#include <sys/types.h> 
#include <sys/socket.h> 
#include <linux/netlink.h> 
#include <linux/connector.h> 
#include <linux/cn_proc.h> 

#include <stdio.h> 
#include <unistd.h> 
#include <strings.h> 
#include <errno.h> 

#define NL_MESSAGE_SIZE (sizeof(struct nlmsghdr) + sizeof(struct cn_msg) + \ 
        sizeof(int)) 

static int nl_sock; 

int connect_to_netlink() 
{ 
    struct sockaddr_nl sa_nl; /* netlink interface info */ 
    char buff[NL_MESSAGE_SIZE]; 
    struct nlmsghdr *hdr; /* for telling netlink what we want */ 
    struct cn_msg *msg; /* the actual connector message */ 

    /* connect to netlink socket */ 
    nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); 

    if (-1 == nl_sock) { 
     perror("socket failed"); 
     return errno; 
    } 

    bzero(&sa_nl, sizeof(sa_nl)); 
    sa_nl.nl_family = AF_NETLINK; 
    sa_nl.nl_groups = CN_IDX_PROC; 
    sa_nl.nl_pid = getpid(); 

    if (-1 == bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl))) { 
     perror("bind failed"); 
     return errno; 
    } 

    /* Fill header */ 
    hdr = (struct nlmsghdr *)buff; 
    hdr->nlmsg_len = NL_MESSAGE_SIZE; 
    hdr->nlmsg_type = NLMSG_DONE; 
    hdr->nlmsg_flags = 0; 
    hdr->nlmsg_seq = 0; 
    hdr->nlmsg_pid = getpid(); 

    /* Fill message */ 
    msg = (struct cn_msg *)NLMSG_DATA(hdr); 
    msg->id.idx = CN_IDX_PROC; /* Connecting to process information */ 
    msg->id.val = CN_VAL_PROC; 
    msg->seq = 0; 
    msg->ack = 0; 
    msg->flags = 0; 
    msg->len = sizeof(int); 
    *(int*)msg->data = PROC_CN_MCAST_LISTEN; 

    if (-1 == send(nl_sock, hdr, hdr->nlmsg_len, 0)) { 
     perror("send failed"); 
     return errno; 
    } 

    return 0; 
} 

void handle_events() 
{ 
    char buff[CONNECTOR_MAX_MSG_SIZE]; 
    struct nlmsghdr *hdr; 
    struct proc_event *event; 

    fd_set fds; 

    while (1) { 
     FD_ZERO(&fds); 
     FD_SET(nl_sock, &fds); 

     if (0 > select(nl_sock + 1, &fds, NULL, NULL, NULL)) { 
      perror("select failed"); 
      return ; 
     } 

     /* If there were no events detected, return */ 
     if (! FD_ISSET(nl_sock, &fds)) { 
      return ; 
     } 

     /* if there are events, make calls */ 
     if (-1 == recv(nl_sock, buff, sizeof(buff), 0)) { 
      perror("recv failed"); 
      return ; 
     } 

     hdr = (struct nlmsghdr *)buff; 

     if (NLMSG_ERROR == hdr->nlmsg_type) { 
      perror("NLMSG_ERROR"); 
     } else if (NLMSG_DONE == hdr->nlmsg_type) { 

      event = (struct proc_event *)((struct cn_msg *)NLMSG_DATA(hdr))->data; 

      switch(event->what) { 
       case proc_event::PROC_EVENT_EXIT: 
        printf("Process %d (tgid %d) exit with code %d, signal %d\n", 
         event->event_data.exit.process_pid, 
         event->event_data.exit.process_tgid, 
         event->event_data.exit.exit_code, 
         event->event_data.exit.exit_signal); 
        break; 

       case proc_event::PROC_EVENT_FORK: 
        printf("New process %d (tgid %d), parent %d (tgid %d)\n", 
         event->event_data.fork.child_pid, 
         event->event_data.fork.child_tgid, 
         event->event_data.fork.parent_pid, 
         event->event_data.fork.parent_tgid); 
        break; 

       default: 
        break; 
      } 
     } 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    if (!connect_to_netlink()) { 
     handle_events(); 
    } 
    return 0; 
} 

संकलित & रन:

# g++ -o psev psev.cpp 
# ./psev 

आउटपुट:

New process 27465 (tgid 27465), parent 2351 (tgid 2351) 
Process 27465 (tgid 27465) exit with code 0, signal 17 
+0

यह ध्यान दिया जाना चाहिए कि इसके लिए CAP_NET_ADMIN की आवश्यकता है, और एक अप्रतिबंधित उपयोगकर्ता प्रक्रिया में काम नहीं करेगा। –

संबंधित मुद्दे