我在linux中开发了一个包含无限循环while(1)
的C应用程序。
有些指针是动态分配的,并且在无限循环下很有用,所以解除内存的唯一时间是在while(1)
,ctrl-z
,ctrl-c
之后中断kill -9 apppid
,killall appname
。
所以我的想法是将新的处理程序与内存事件信号解除关联。
void deallocatehandler(int signal){ printf("Memory Deallocation\n"); exit(0);}
int main(){
signal(SIGINT, &deallocatehandler);
signal(SIGTSTP, &deallocatehandler);
signal(SIGKILL, &deallocatehandler);
while(1){
/**
Some code here
**/
}
}
如果我按ctrl-c或ctrl-z调用处理程序,但问题出在SIGKILL上。命令kill -9
和killall
无法启动处理程序。
有人知道为什么吗?是否有建议纠正它?
答案 0 :(得分:5)
SIGKILL的全部意义在于无论如何都要杀死这个过程。这就是为什么你不被允许处理它。
在大多数情况下,您从SIGTERM开始,为进程提供良好退出的机会。当SIGTERM不起作用时,SIGKILL通常用作最后的手段。毕竟,SIGTERM的预期行为是进程退出。如果不是,你就知道出了什么问题。
来自manual
SIGTERM信号是用于导致程序终止的通用信号。与SIGKILL不同,此信号可以被阻止,处理和忽略。这是礼貌地要求程序终止的正常方式。
...
SIGKILL信号用于立即终止程序。它无法处理或忽略,因此总是致命的。也无法阻止此信号。
在同一份文件中,您还可以阅读这个有趣的内容
实际上,如果SIGKILL无法终止进程,那么它本身就构成了一个您应该报告的操作系统错误。
答案 1 :(得分:3)
您无法捕获SIGKILL
和SIGSTOP
信号。所以你的信号处理程序不会做任何事情。
当您的进程收到SIGKILL时,您无能为力,更不用说任何内存清理了。
在Linux上,内存将在程序退出时清除,因此这可能不是问题。
通常这种清除退出是为SIGTERM完成的。
正确的答案是不发送SIGKILL(只有在kill -9
本身不起作用时才应使用kill
)。
这不是请求进程终止自身的方式。首先发送SIGTERM,如果它不起作用,则发送SIGKILL。
答案 2 :(得分:2)
man 7 signal
当你SIGKILL进程时,你不要求它很好地终止。您要求内核停止该进程的任何进一步执行。 因此,该过程无法意识到它已收到SIGKILL。
但是对你来说无关紧要,因为只有在SIGTERM没有成功时才会发出SIGKILL。
答案 3 :(得分:2)
所以我的想法是将新的处理程序与内存事件信号解除关联。
不需要!在进程终止后,无论原因是什么,所有内存都从内核中释放出来。因此,您无需手动执行此操作。
使用IPC资源和信号量,您将遇到无法正常处理的问题。
答案 4 :(得分:2)
由于多种原因,你的问题不合适。
首先,当您的进程终止时,释放malloc
内存。如果现代架构不会自动执行此操作,大多数机器将完全无法使用。
其次,一些信号和一些过程终止方法是不可捕获的。所以对于这些,无论如何都没有希望做修理工作。在没有太多清理的情况下终止执行的方法包括一些信号abort
,quick_exit
,_Exit
。
第三,使用信号处理程序进行清理工作是完全矫枉过正的。 C库具有atexit
和at_quick_exit
(自C11以来)为此目的而设计的处理程序。因此,如果在执行终止时必须执行一些特殊操作(例如将一些最终消息写入套接字,清理文件或共享内存),请使用为此发明的工具。
答案 5 :(得分:0)
根据定义,您无法捕获SIGKILL(kill -9)。它被用作杀死进程的“最后手段”方式,因此该进程必须无法捕获它。对于友好的终止请求,请检查SIGTERM(kill -15或kill无特定值)。
但是你通常不想捕捉这样的事件,除非你需要做非常具体的清理行动。内存将被释放,但操作系统;你的程序不需要捕获信号只是为了释放内存。
答案 6 :(得分:0)
man 7 signal
将显示
SIGKILL 9 Term Kill signal
这意味着,当此信号出现时,您无法再对代码进行控制。
引用signal
的定义手册:
The signals SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.