三十一、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,进程的终止状态,以及该 ...
随机推荐
- Swarm部署集群
swarm-manager 是 manager node,swarm-worker是 worker node.所有节点的 Docker 版本均不低于 v1.12.在master上 docker swa ...
- multiset和set
set集合容器:实现了红黑树的平衡二叉检索树的数据结构,插入元素时,它会自动调整二叉树的排列,把元素放到适当的位置,以保证每个子树根节点键值大于左子树所有节点的键值,小于右子树所有节点的键值:另外,还 ...
- Centos7下源码编译安装python3.6
测试环境: 操作步骤: 1. 下载Python源码包(python3.6.0) 官网下载地址:https://www.python.org/downloads/ 搜狐下载地址:http://mirro ...
- kali源更新
对于新装kali的同学一点存在着更新源的问题 这是对初次安装,进行系统更新的教程 首先需要有gpg_key wget -q -O - https://archive.kali.org/archive- ...
- Zabbix-proxy安装部署
原文链接:https://www.cnblogs.com/irockcode/p/6754659.html 环境: 因为公司需要监控远程客户机,但server端无法主动连接agent端,客户端可以连接 ...
- C/C++ 动态存储分配 malloc calloc realloc函数的用法与区别
C++内存分配 https://blog.csdn.net/zhangxiao93/article/details/43966425
- react-native中timer的注意点
务必在卸载组件前清除定时器! 我们发现很多 React Native 应用发生致命错误(闪退)是与计时器有关.具体来说,是在某个组件被卸载(unmount)之后,计时器却仍然在运行.要解决这个问题,只 ...
- rabbitMQ使用一——helloworld
参考链接 :https://blog.csdn.net/zhulongxi/article/details/72867545 https://www.cnblogs.com/ericli-ericli ...
- 详解python的垃圾回收机制
python的垃圾回收机制 一.引子 我们定义变量会申请内存空间来存放变量的值,而内存的容量是有限的,当一个变量值没有用了(简称垃圾)就应该将其占用的内存空间给回收掉,而变量名是访问到变量值的唯一方式 ...
- firfox中"content-disposition", "attachment;filename=“+filename不能显示文件名字
一般要在浏览器中显示文件名,可以使用以下文件名 // 设置文件名的编码方式,使得文件的名字能够正常安全的显示. filename = URLEncoder.encode(filename, " ...