簡體   English   中英

如果X不是子進程,如何等待PID X退出?

[英]How do I wait for PID X to exit if X is not a child process?

使用c當我不是當前進程的子進程時,如何等待PID X退出?

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

以上不起作用,因為'pid'不是子進程。

這是工作示例如何訂閱和使用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

通過混亂看到這個答案

通常的做法是使用kill(0,pid)進行輪詢並查找返回值-1和ESRCH的errno以指示進程已消失

基於kill手冊頁 ,它可能是kill(pid,0) 但這個想法是一樣的。

以干凈的方式執行此操作的唯一方法(即,沒有時間間隔輪詢,並且沒有PID溢出的風險)是使用Netlink cn_proc連接器(特定於Linux)。 周圍沒有太多示例代碼或文檔。 它不是一個很好的API,但它基本上只適用於合理的API。

尋找PROC_EVENT_EXIT,這是您感興趣的事件。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM