当前位置: 首页 > news >正文

Linux进程6-alarm闹钟定时终止、raise发送信号、abort终止、pause挂起进程验证

目录

1.alarm函数

1.1关键点

1.2单个alarm函数定时

1.3两个alarm函数定时

2.raise函数

2.1核心行为‌

2.2 raise与 kill 的区别

2.3程序:

3.abort函数

4.pause 函数

4.1 pause简单挂起

4.2父进程挂起,子进程发信号


1.alarm函数

函数原型:

#include <unistd.h>unsigned int alarm(unsigned int seconds);功能:定时器,闹钟,当设定的时间到达时,会产生SIGALRM信号参数:seconds:设定的秒数返回值:如果alarm函数之前没有alarm设置,则返回0如果有,则返回上一个alarm剩余的时间

1.1关键点

  1. 信号行为

    • SIGALRM默认终止进程,但可通过信号处理函数自定义行为。
    • 使用signalsigaction注册处理函数。推荐sigaction以确保可移植性。
  2. 覆盖机制

    • 多次调用alarm会覆盖之前的定时器,返回前一个定时器的剩余时间。
    • 调用alarm(0)取消定时器,返回剩余时间。
  3. 精度与限制

    • 精度为秒级。更高精度需用setitimertimer_create
    • sleep等函数可能冲突(因内部使用相同信号),建议改用nanosleep避免干扰。
  4. 多线程与进程

    • 定时器是进程级别的,多线程中需注意线程安全。
    • fork后子进程不继承定时器;exec会取消定时器。

 应用场景

  • 超时控制:如阻塞I/O操作设置超时,防止无限等待。
  • 任务调度:定时执行特定任务(需结合信号处理)。

1.2单个alarm函数定时

程序:

#include <stdio.h>
#include <unistd.h>int main(int argc, char *argv[])
{unsigned int i;unsigned int sec;//当执行到alarm之后,代码会接着往下执行,当设定的时间到后,//会产生SIGALRM终止信号sec = alarm(5);printf("alarm返回值 = %d\n", sec);while(1){i++;printf("程序运行 第 %d 次\n",i);sleep(1);}return 0;
}

运行结果:alarm设置5秒的闹钟,程序运行5秒后,产生SIGALRM终止信号执行结束。

1.3两个alarm函数定时

程序:

#include <stdio.h>
#include <unistd.h>int main(int argc, char *argv[])
{unsigned int i;unsigned int sec;//当执行到alarm之后,代码会接着往下执行,当设定的时间到后,//会产生SIGALRM终止信号//如果alarm之前没有设置其他闹钟,则返回0,如果之前设置了,则返回之前剩余的秒数//如果一个程序中出现多个alarm闹钟,第一个如果没有到达指定的时间就遇到第二个//则第一个的闹钟时间清除,按照第二个alarm闹钟的时间继续向下运行sec = alarm(5);printf("alarm返回值 = %d\n", sec);sleep(2);//阻塞2秒sec = alarm(8);//返回上一个闹钟剩余时间printf("当前alarm 前面有alarm函数 返回值 = %d\n", sec);while(1){i++;printf("程序运行 第 %d 次\n",i);sleep(1);}return 0;
}

运行结果:

如果一个程序中出现多个alarm闹钟,第一个如果没有到达指定的时间就遇到第二个则第一个的闹钟时间清除,按照第二个alarm闹钟的时间继续向下运行。

程序中第一个闹钟先设置5秒,睡眠阻塞2秒,闹钟时间还剩余3秒,接着又遇见第二个闹钟设置8秒,第一个闹钟时间清零,闹钟时间按第二个闹钟运行。

2.raise函数

函数原型:

#include <signal.h>
int raise(int signum);功能:
给调用进程本身发送一个信号。参数:
signum:要发送的信号编号(如 SIGINT、SIGTERM 等)返回值:
成功返回 0,失败返回非0。

2.1核心行为

  1. ‌向自身进程发送信号‌
    raise(sig) 等价于 kill(getpid(), sig),但 raise 是标准 C 库函数,可移植性更强。

  2. ‌触发信号处理逻辑‌
    若已通过 signal() 或 sigaction() 注册了信号处理函数,调用 raise 会执行对应的处理逻辑。

  3. ‌默认行为‌
    若未捕获信号,执行信号的默认动作(如 SIGTERM 会终止进程)。

2.2 raise与 kill 的区别

raise(sig) 等价 kill(getpid(), sig)

  • raise 是进程内操作的简化版本,无需指定进程ID。
  • raise 是标准 C 库函数,可移植性更强。
特性raisekill
目标进程仅当前进程 (getpid())可指定任意进程或进程组
信号来源进程内部主动触发通常由外部进程发送
可移植性标准 C 库函数,跨平台兼容POSIX 系统调用

2.3程序:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>int main(int argc, char const *argv[])
{int num = 0;while(1){      sleep(1);num++;printf("程序运行 第 %d 次\n",num);//当循环执行5秒后,进程退出if(num == 5){//使用raise给当前进程本身发送信号raise(SIGTERM); //默认终止信号//  raise(SIGALRM); //闹钟终止//  raise(SIGINT); //终止,终端按下 Ctrl+C//kill(getpid(), SIGALRM);}}return 0;
}

运行结果:

3.abort函数

函数原型:

#include <stdlib.h>
void abort(void);功能:
向进程发送一个 SIGABRT 信号,默认情况下进程会退出。
默认行为是终止进程并生成核心转储文件(core dump)注意:即使 SIGABRT 信号被加入阻塞集,一旦进程调用了 abort 函数,
进程也还是会被终止,且在终止前会刷新缓冲区,关文件描述符。

程序:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>int main(int argc, char const *argv[])
{int num = 0;while(1){sleep(1);num++;printf("程序运行 第 %d 次\n",num);//当循环执行5秒后,进程退出if(num == 5){abort();//终止运行}}return 0;
}

运行结果:

4.pause 函数

函数原型:

#include <unistd.h>
int pause(void);功能:
将调用进程挂起直至捕捉到信号为止。这个函数通常用于判断信号是否已到。返回值:
直到捕获到信号,pause 函数才返回-1,且 errno 被设置成 EINTR。

4.1 pause简单挂起

(1)pause简单挂起返回值测试

程序:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>void alarm_handler(int sig) 
{printf("定时器触发 SIGALRM 信号(%d)\n", sig);
}int main()
{signal(SIGALRM, alarm_handler);alarm(3);  // 设置 3 秒定时int ret = pause();  // 等待定时器信号if (ret == -1) {if (errno == EINTR) {printf("pause 被 SIGALRM 中断\n");} else{perror("pause 错误");}}return 0;
}

运行结果:

(2)pause简单挂起,阻值while(1)运行

程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>int main(int argc, char *argv[])
{int num = 0;alarm(3);//设置3秒定时闹钟,3秒后,产生SIGALRM终止信号执行结束while(1){      sleep(1);num++;printf("程序运行 第 %d 次\n",num);pause();  // 进程挂起,等待信号}return 0;
}

运行结果:程序正常运行while(1)应每过一秒打印一次,加入pause进程挂起,等待信号,直到闹钟定时3秒后,发送终止信号,程序运行结束。

4.2父进程挂起,子进程发信号

程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>int main(int argc, char *argv[])
{pid_t pid;int num = 0;pid = fork();if(pid < 0){perror("fail to fork");//创建失败exit(1);//退出}else if(pid > 0) //父进程的代码区{printf("父进程运行... \n");//使用pause阻塞等待捕捉信号pause();// 进程挂起,等待信号}else //子进程的代码区 {printf("子进程运行... \n");while(1){sleep(1);//阻塞1秒num++;printf("子进程运行 第 %d 次 \n", num);if(num == 3){printf("给父进程发送终止信号 \n");//给父进程发送终止信号	kill(getppid(), SIGTERM);exit(1);//退出}}}return 0;
}

运行结果:

相关文章:

  • 新能源汽车充电桩:多元化运营模式助力低碳出行
  • List findIntersection getUnion
  • 【Python进阶】数据可视化:Matplotlib从入门到实战
  • springboot项目配置springMVC
  • MATLAB Coder 应用:转换 MATLAB 代码至 C/C++ | 实践步骤与问题解决
  • mockMvc构建web单元测试学习笔记
  • C++学习:六个月从基础到就业——C++学习之旅:STL容器详解
  • [特殊字符]【Qt自定义控件】创意开关按钮 - 丝滑动画+自定义样式+信号交互 | 附完整源码
  • OpenLDAP 管理 ELK 用户
  • PHP通讯录网站源码无需sql数据库
  • 【中级软件设计师】程序设计语言基础成分
  • 从零开始创建MCP Server实战指南
  • STM32外部中断与外设中断区别
  • Element Plus表格组件深度解析:构建高性能企业级数据视图
  • Vue2-指令语法
  • C++静态与动态联编区别解析
  • Windows安装Hadoop(图文解说版)
  • 【华为HCIP | 华为数通工程师】821—多选解析—第十二页
  • Spring中配置 Bean 的两种方式:XML 配置 和 Java 配置类
  • NDSS 2025|侧信道与可信计算攻击技术导读(二)系统化评估新旧缓存侧信道攻击技术
  • 董明珠的接班人还是董明珠
  • 视频丨习近平同阿塞拜疆总统会谈:两国建立全面战略伙伴关系
  • 瞭望:高校大门要向公众打开,不能让“一关了之”成为常态
  • 《国语汇校集注》:以1900余条注解,揭示隐微,提供思考
  • 山西公布商标侵权典型案例:一工厂生产价值三百多万假“维达”纸被查
  • 体坛联播|利兹联、伯恩利重返英超,北京淘汰北控队晋级四强