三十一、Linux 进程与信号——SIGCHLD 信号、kill和raise函数以及alarm函数
31.1 SIGCHLD 信号
- 子进程状态发生变化(子进程结束)产生该信号,父进程需要使用 wait 调用来等待子进程结束并回收它。
- 避免僵尸进程
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h> void sig_handler(int signo)
{
printf("child process deaded, signo: %d\n", signo); /** 当父进程捕获到 SIGCHLD 信号后要调用 wait
* 函数去回收子进程,否则子进程会成为僵尸进程 */
wait();
} void out(int n)
{
int i;
for(i = ; i < n; i++) { printf("%d out %d\n", getpid(), i);
sleep();
}
} int main(void)
{
if(signal(SIGCHLD, sig_handler)){
perror("signal sigchld error");
} pid_t pid = fork();
if(pid < ) { perror("fork error");
exit();
} else if(pid > ) {
/** parent process */
out();
} else {
/** child process */
out();
} return ;
}
31.2 信号发送
- 除了内核和超级用户,并不是每个进程都可以向其他的进程发送信号
- 一般的进程只能向具有相同 uid 和 gid 的进程发送信号,或向相同进程组中的其他进程发送信号
- 常用的发送信号的函数由 kill()、raise()、alarm()、settitimer()、abort()等。
31.2.1 kill() 函数 和 raise() 函数
#include <signal.h>
int kill(pid_t pid, int signo);
- 函数功能:向指定的进程发送某一个信号
- 函数参数:
- pid:接受信号进程的 pid
- pid > 0 将信号发给进程 ID 为 pid 的进程
- pid == 0 将信号发给与发送进程同一进程组的所有进程
- pid < 0 将该信号发送给进程组 ID 等于 pid 的绝对值
- pid == -1 将该信号发送给发送进程有权限向他们发送信号的系统上的所有进程
- signo:要发送的信号值
- pid:接受信号进程的 pid
- 返回值:成功返回0,出错返回 -1
- 说明:kill 函数将信号发送给进程或进程组
- 0 为空信号,常用来检测特定的进程是否存在
#include <signal.h>
int raise(int signo);
- 函数功能:向进程本身发送一个信号,相当于 kill(getpid(), sig)
- 函数参数:
- signo:要发送的信号值
- 返回值:成功返回0,出错返回 -1
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h> #define KILLSELF 0 /** 定义信号处理函数
* signo 进程捕获到的信号
*/
void sig_handler(int signo)
{
printf("%d, %d occured\n", getpid(), signo);
} int main(void)
{
/** 向内核登记信号处理函数以及信号值 */
if(signal(SIGTSTP, sig_handler) == SIG_ERR) {
perror("signal sigtstp error");
} if(signal(SIGINT, sig_handler) == SIG_ERR) {
perror("signal sigint error");
} if(signal(SIGUSR1, sig_handler) == SIG_ERR) {
perror("signal usr1 error");
} if(signal(SIGUSR2, sig_handler) == SIG_ERR) {
perror("signal usr2 error");
}
/*
if(signal(SIGKILL, SIG_IGN) == SIG_ERR) {
perror("signal sigtstp error");
} if(signal(SIGSTOP, SIG_IGN) == SIG_ERR) {
perror("signal sigint error");
}
*/
int i = ;
while(i < ) {
printf("%d out %d\n", getpid(), i++);
if(i == ) {
#ifdef KILLSELF
kill(getpid(), SIGKILL);
#endif
sleep();
}
sleep();
} /** 向进程自己发送 SIGUSR1 和SIGUSR2 信号 */
raise(SIGUSR1);
kill(getpid(), SIGUSR2);
return ;
}
31.2.2 alarm() 函数
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
- 函数说明:
- alarm 函数可设置定时器,当定时器超时,产生 SIGALRM 信号
- 信号由内核产生,在指定的 seconds 秒之后,给进程本身发送一个 SIGALRM 信号。
- 参数为 0,取消以前设置的定时器
- 返回值:
- 0 或以前设置的定时器时间余留秒数
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h> void sig_handler(int signo)
{
if(SIGALRM == signo) {
printf("clock time out\n");
alarm(); ///< 重新设置定时器(周期性的定时)
}
} void out_data(void)
{
int i = ;
while(i <= ) {
double d = drand48();
printf("%-10d: %lf\n", i++, d);
if(i == )
alarm(); ///< 取消定时器
sleep(1);
}
} int main(void)
{
if(signal(SIGALRM, sig_handler) == SIG_ERR) {
perror("signal sigalrm error");
} // 设置定时器
alarm();
printf("begin running main\n");
out_data();
printf("end running main\n");
return ;
}
三十一、Linux 进程与信号——SIGCHLD 信号、kill和raise函数以及alarm函数的更多相关文章
- 《linux 进程管理》- ps/top/kill/nice
一:进程简述 二:ps 查看进程 语法 ps * -A 列出所有进程,和 -e 同等效果 * -a 列出不和本终端有关系的所有进程 * -w 显示加宽,可以显示较多信息 * -u 显示有效使用者相关的 ...
- 信号的发送kill,raise,alarm,setitimer,abort,sigqueue
1.kill函数 int kill(pid_t pid, int sig); 发送信号给指定的进程. (1) If pid is positive, then signal sig is sent t ...
- (三)Linux Shell编程——Shell常用命令(输出、判断、循环、函数、包含)
3. 常用命令 3.1 输出 3.1.1 echo命令 echo是Shell的一个内部指令,用于在屏幕上打印出指定的字符串.命令格式: echo arg name="coding" ...
- 实验三:Linux进程管理(HDU)
2.设计内容 把下面的几个网址的内容看懂,关于Linux的通信机制就会有个基本的了解了,后面的这几个代码也应该可以看得懂了. 管道通信:https://blog.csdn.net/ljianhui/a ...
- linux下的僵尸进程处理SIGCHLD信号
什么是僵尸进程? 首先内核会释放终止进程(调用了exit系统调用)所使用的所有存储区,关闭所有打开的文件等,但内核为每一个终止子进程保存了一定量的信息.这些信息至少包括进程ID,进程的终止状态,以及该 ...
- [转] linux下的僵尸进程处理SIGCHLD信号
什么是僵尸进程? 首先内核会释放终止进程(调用了exit系统调用)所使用的所有存储区,关闭所有打开的文件等,但内核为每一个终止子进程保存了一定量的信息.这些 信息至少包括进程ID,进程的终止状态,以及 ...
- linux下的僵尸进程处理SIGCHLD信号【转】
转自:http://www.cnblogs.com/wuchanming/p/4020463.html 什么是僵尸进程? 首先内核会释放终止进程(调用了exit系统调用)所使用的所有存储区,关闭所有打 ...
- 第9章 Linux进程和信号超详细分析
9.1 进程简单说明 进程是一个非常复杂的概念,涉及的内容也非常非常多.在这一小节所列出内容,已经是我极度简化后的内容了,应该尽可能都理解下来,我觉得这些理论比如何使用命令来查看状态更重要,而且不明白 ...
- 僵尸进程与SIGCHLD信号
什么是僵尸进程? 首先内核会释放终止进程(调用了exit系统调用)所使用的所有存储区,关闭所有打开的文件等,但内核为每一个终止子进程保存了一定量的信息.这些信息至少包括进程ID,进程的终止状态,以及该 ...
随机推荐
- ELK部署详解--logstash
logstash.yml # Settings file in YAML## Settings can be specified either in hierarchical form, e.g.:# ...
- springAop 使用@Around,@After等注解时,代码运行两边的问题
springAop使用@Around,@After等注解时,代码运行两边的问题 将@Component注解删掉就好了
- Spring 官方教程:使用 Restdocs 创建 API 文档
https://mp.weixin.qq.com/s?__biz=MzU0MDEwMjgwNA==&mid=2247483998&idx=1&sn=6ae5fa795d36b1 ...
- jquery 事件的绑定,触发和解绑
js和jquery绑定的区别? HTML或原生js是单一对应绑定的,绑多了只留最后一个.jQuery是追加绑定的,绑多少执行多少.这个在每一本jQuery的书中都是首先提到的事情. jquery绑定与 ...
- @Async的简单用法总结
前言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时 候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在Spring 3 ...
- 跟着 underscore 学节流
更多内容请参考:我的新博客 在上一篇文章中,我们了解了为什么要限制事件的频繁触发,以及如何做限制: debounce 防抖 throttle 节流 上次已经说过防抖的实现了,今天主要来说一下节流的实现 ...
- python datetime 字符串 时间戳
#把datetime转成字符串 def datetime_toString(dt): return dt.strftime("%Y-%m-%d-%H") #把字符串转成dateti ...
- 关于ComponentName组件名称的使用
ComponentName,顾名思义,就是组件名称,通过调用Intent中的setComponent方法,我们可以打开另外一个应用中的Activity或者服务. 实例化一个ComponentName需 ...
- (栈)leetcode856 Score of Parentheses
Given a balanced parentheses string S, compute the score of the string based on the following rule: ...
- qemu与libvirt编译与安装
qemu与libvirt编译与安装 一 .qemu编译前准备 以下链接为的本次编译环境为前提继续进行. http://www.cnblogs.com/grglym/p/7891253.html 1.安 ...