700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 网络编程(32)—— linux中销毁僵尸进程的四种方法

网络编程(32)—— linux中销毁僵尸进程的四种方法

时间:2023-07-04 03:54:44

相关推荐

网络编程(32)—— linux中销毁僵尸进程的四种方法

一、wait函数

函数原型:

pid_t wait(int *status);

描述:

wait可以回收任意一个僵尸进程,只要系统中存在僵尸进程,调用一次wait,就会回收一个僵尸进程。

参数说明:

status - 当子进程结束之后,其进入僵尸进程状态。其状态变化信息被操作系统放置在内存中某一处位置,而status就是这处位置的指针,通过调用wait函数可以获取这部分位置的数据。

获取到数据之后,通过一系列宏可以获取目前操作系统的状态。如:

WIFEXITED(*status)可以判断该进程是否正常结束(main函数通过return或者exit结束),若正常结束返回true,否则返回false。

WEXITSTATUS(*status)用来获取进程正常结束时main函数的返回值,前提是WIFEXITED(status)返回true。

返回值:

返回被结束僵尸状态进程的进程ID。

举例:

int main()

{

pid_t pid;

int status;

pid=fork();

if(pid==0)

{

exit(10);

}

else

{

pid = wait(&status);

if(WIFEXITED(status))

{

printf("process %d exited,return value = %d\n",pid,WEXITSTATUS(status));

}

}

return 0;

}

缺点:

wait()函数为阻塞函数,也就是说如果操作系统中无僵尸进程的话,程序会一直在wait()处等待,直到出现僵尸进程。

二、waitpid函数

函数原型:

pid_t waitpid(pid_t pid, int *status, int options);

描述:

waitpid()也是用来回收一个僵尸进程,与wait()不同的是,它是非阻塞函数,可以通过设置pid参数回收指定进程ID的僵尸进程,也可以指定回收任意僵尸进程。

参数说明:

status,和wait()函数相同。

pid,指定要回收进程的进程ID,若设为-1,则默认回收任意一个僵尸进程。

options,设置选项,一般情况下设置成WNOHANG,表示不阻塞。

返回值

若存在僵尸进程,返回被结束僵尸状态进程的进程ID;若不存在僵尸进程返回0;若发生错误,返回-1.

举例:

int main()

{

pid_t pid;

int status;

pid=fork();

if(pid==0)

{

sleep(10);

exit(10);

}

else

{

while((pid=waitpid(-1,&status,WNOHANG))==0)

{

puts("wating ...");

sleep(2);

}

if(WIFEXITED(status))

{

printf("process %d exited,return value = %d\n",pid,WEXITSTATUS(status));

}

}

return 0;

}

缺点:

虽然waitpid()不是阻塞函数,但是使用时需要在循环中使用,只有在回收完僵尸进程后才会执行循环之后的代码。

三 signal函数

函数原型:

sighandler_t signal(int signum, sighandler_t handler);

描述:

系统级别的api,向操作系统注册信号和信号处理函数,当操作系统捕获到注册的信号时会调用该信号处理函数。

参数:

signum,向操作系统注册的信号,子进程结束的信号是SIGCHLD。

handler,信号的处理函数,函数原型一般是void handler(int sig)的形式,函数的参数为操作系统捕获的信号,函数的返回值是void

返回值:

返回之前注册的处理该信号的信号处理函数的函数指针。

举例:

void sig_handling(int sig)

{

int status;

pid_t pid;

if(sig==SIGCHLD)

{

pid = waitpid(-1,&status,WNOHANG);

if(WIFEXITED(status))

{

printf("process %d exited,return value=%d\n",pid,WEXITSTATUS(status));

}

}

}

int main()

{

pid_t pid;

signal(SIGCHLD,sig_handling);

pid=fork();

if(pid==0)

{

exit(11);

}

else

{

sleep(10000);

}

return 0;

}

请注意:

1、在信号处理函数sig_handling中,也需要用waitpid()来回收僵尸进程,也就是说signal只是一个注册信号的作用,其本身并没有回收僵尸进程的功能。

2、一旦用signal注册了信号和信号处理函数,一旦发生该信号,会结束进程的sleep()状态,也就是说在父进程的sleep(10000);将会被打断,不会真的睡10000秒。

四 sigaction函数

函数原型:

int sigaction(int signum, const struct sigaction *act,

struct sigaction *oldact);

描述:

signum,和signal一样,表示需要注册的信号。

act,sigaction类型的指针,sigaction类型的定义如下:

struct sigaction {

void (*sa_handler)(int);

void (*sa_sigaction)(int, siginfo_t *, void *);

sigset_t sa_mask;

int sa_flags;

void (*sa_restorer)(void);

};

我们进行使用时,只需填写其sa_handler、sa_mask、sa_flags三个成员,sa_handler为信号处理函数,sa_mask使用sigemptyset()函数进行置空,sa_flags直接赋为0。

oldact,之前注册的sigaction 类型的指针。

返回值:

成功返回0,失败返回-1

举例:

void sig_handling(int sig)

{

int status;

pid_t pid;

if(sig==SIGCHLD)

{

pid = waitpid(-1,&status,WNOHANG);

if(WIFEXITED(status))

{

printf("process %d exited,return value=%d\n",pid,WEXITSTATUS(status));

}

}

}

int main()

{

pid_t pid;

struct sigaction act;

act.sa_handler=sig_handling;

sigemptyset(&act.sa_mask);

act.sa_flags=0;

sigaction(SIGCHLD,&act,0);

pid=fork();

if(pid==0)

{

exit(11);

}

else

{

sleep(10000);

}

return 0;

}

与signal相比,sigaction函数虽然比较繁琐,但是他的长处在于linux系统多版本的兼容性,而部分版本linux是不支持signal函数的,因此在实际的使用中sigaction的使用范围更广。

Github位置:

/HymanLiuTS/NetDevelopment

克隆本项目:

Gitclone git@:HymanLiuTS/NetDevelopment.git

获取本文源代码:

git checkout NL32

---------------------

作者:HymanLiuTS

来源:CSDN

原文:/hyman_c/article/details/53512999

版权声明:本文为博主原创文章,转载请附上博文链接!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。