如果您知道进程的pid是否有办法销毁从该进程创建的漏洞进程树并释放这些进程分配的所有内存?我需要在C程序中找到一种方法,而不必去树的每个进程。
所以这是我在阅读Basile Starynkevitch非常有用的答案后所做的代码。
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
void proctreecreator(int count);
int main()
{
int status,count;
count = 0;
pid_t pid,procapid;
pid = fork();
if (pid < 0) {
perror("main: fork");
exit(1);
}
if (pid == 0)
{
if( setpgid(0,0) <0 ) perror( "main: setpgid" );
proctreecreator(count);
exit(1);
}
procapid=pid;
pid = fork();
if (pid < 0) {
perror("main: fork");
exit(1);
}
if (pid == 0)
{
sleep(1);
printf("I will now destroy the process tree \n");
kill(-procapid, SIGTERM);
exit(0);
}
procapid = waitpid(procapid, &status, 0);
if (procapid < 0) perror( "main: waitpid" );
else printf("Process A and its tree are killed\n");
pid = waitpid(pid, &status, 0);
if (pid < 0) perror("main: waitpid");
else printf("process B exited \n");
return 0;
}
void proctreecreator(int count)
{
pid_t pid;
int status,i;
int *k = (int*)malloc(sizeof(int));
*k=count;
pid_t mypid=getpid();
printf("process with pid : %d created in depth %d \n",mypid,count);
if (count > 3)
{
sleep(5);
free(k);
exit(0);
}
else
{
count++;
pid = fork();
if (pid < 0) {
perror("proctreecreator: fork");
exit(1);
}
if (pid == 0)
{
proctreecreator(count);
exit(1);
}
pid = fork();
if (pid < 0) {
perror("proctreecreator: fork");
exit(1);
}
if (pid == 0)
{
proctreecreator(count);
exit(1);
}
for (i=0; i<2; i++)
{
pid = wait(&status);
if (pid < 0) perror("proctreecreator: wait");
else printf("process %d is now terminated",pid);
}
free(k);
exit(0);
}
}
我对程序的运作方式有一些疑问!使用kill时(-procapid,SIGTERM);是否需要一段时间来销毁进程树,还是取决于树的大小?杀死后是否所有内存都分配了malloc free(-procapid,SIGTERM); ?
答案 0 :(得分:1)
当process被终止时,它已使用的所有virtual memory - heap managed经常mmap(2) malloc
&amp; free
,通常通过shared memory等...... - 已发布(system call除外)。
(强制)终止某个其他进程的kill(2)是signal,它正好向进程(或进程组)发送signal(7)。阅读process group。如果流程树中的所有流程都属于同一个credentials(7)(请参阅killpg(2) ...),则只需要kill
该流程组。另请参阅RDBMS。
您应首先使用kill
SIGTERM
。这为良好行为的程序(如许多setsid(2)服务器)提供了适当处理该信号的机会(例如,释放资源,清理等等)。一秒钟之后,你可以kill
与SIGQUIT
。最后,您可以发送无法捕获的SIGKILL
信号,并始终终止进程。
还阅读有关会话和setpgid(2)(以及进程组的tty demystified)和控制终端的信息。另请参阅job control页面和execve(2) wikipage。
请注意,某些处理仍可继续。想象一下,您的某些流程是batch(1) setpgid(2),即/usr/bin/batch
(或ssh
)
所以你的第一个程序会分叉A
;拨打电话setpgid(0,0)
(有关详细信息,请参阅fork(2))。当然,你的第一个程序需要保留A
的pid(由waitpid(2)返回),让我们假设它在pid_t pid_of_A
;那么您需要稍后kill(-pid_of_A, SIGTERM)
,最后waitpid(pid_of_A, &status_of_A, 0)
(请参阅Advanced Linux Programming ...)。
您已添加以下内容编辑了您的问题:
对程序的运作方式有一些疑问!使用
kill(-procapid, SIGTERM)
时;是否需要一段时间来销毁进程树,还是取决于树的大小?
这真的应该是另一个问题。杀死进程组时kill
的理论复杂性不应该在实践中打扰你。原因是在实践中你没有很多(运行)过程;你只希望 - 你没有运行数百万美元thrashing - 有几十个正在运行的进程(否则你的整个系统和机器将被重载并开始processes)。因此,杀死进程树的实际复杂性并不重要,因为在实践中,您的进程树将只有几十个正在运行的进程(总共有几百个进程,其中大部分都处于空闲状态)。
你也问
在
kill(-procapid, SIGTERM);
之后是否所有内存都分配了malloc?
详细了解fork system call,fork bombs,virtual memory。请理解,每个流程都使用address space并拥有自己的mmap(2),malloc
使用例如Advanced Linux Programming fork(2)更改正在运行的进程的地址空间(仅限)。
当进程终止时,内核将删除整个地址空间。这与kill(
... SIGTERM)
没有直接关系,因为某些进程会捕获SIGTERM
进行有用的清理。 (换句话说,将SIGTERM
发送到某个进程并不总是立即终止它。)
signal(7)正在详细解释,比我必须要好得多。
是的,创建一个流程(使用_exit(2)),终止一个流程(由于某些终止execve(2)或因为它已轻轻地mmap(2) - ed),所以替换正在运行的程序进程中的另一个进程(使用Linux kernel ...),并且更改正在运行的进程的地址空间(malloc
经常使用的asymptotic complexity ...)是复杂且昂贵的操作,但是scheduler做得很好。
进程是非常广泛的资源,因此您不应该拥有大量资源。因此O(1) scheduler不是推理它们的正确概念。你想要“少数”(以及“少数”意味着取决于你的特定系统和硬件)。现在我的i3770K Linux / Debian桌面(带有16Gbytes RAM)有238个进程,其中大多数是空闲的(在终端中运行ps auxw
以查找),只有少数正在运行。最近的Linux内核具有高效{{3}},通常为{{3}}。
传闻Linux非常擅长管理流程,而且在Linux上创建流程被认为比在Windows上更快。