kill,alarm,raise,abort,pause,signal等函数的使用

本文详细介绍了UNIX和类UNIX系统中的六个关键信号处理函数:kill用于发送信号,alarm设置定时器,raise发送信号给当前进程,abort强制进程终止,pause暂停进程,以及signal定制信号处理。每个函数的功能、用法和示例都进行了详述。

1.1 kill

kill函数是UNIX和类UNIX操作系统中的一个标准库函数,主要用于向指定进程发送信号。

#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int signum);

pid_t pid 是进程ID,int signum 是信号的编号。

kill函数的作用是将signum指定的信号发送到pid指定的进程

  • pid > 0:将信号发送给进程ID为pid的进程。
  • pid = 0:将信号发送给当前进程所在的整个进程组中的所有进程。
  • pid < 0:将信号发送给进程组ID等于pid的绝对值的进程组中的所有进程。
  • pid = -1:将信号发送给系统中的所有进程,这个进程组号等于pid的绝对值。

kill函数的成功返回值为0,失败返回值为-1

此外,调用kill函数的进程必须有权限向目标进程发送信号。通常,只有root用户才能向所有进程发送信号,而非root用户只能向与自己用户ID相同的进程发送信号

案例

 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <signal.h>
 #include <sys/types.h>
 
  int main()
  {
     pid_t pid;
 
     pid = fork();
     if(pid < 0)
     {
         perror("fail to fork");
         exit(1);
     }
     else if(pid > 0) //父进程的代码区
    {
         while(1)
         {
             printf("This is parent peocess\n");
             sleep(1);
         }
    }
     else //子进程的代码区 
    {
     printf("This is son process\n");
     //子进程在3秒之后,让父进程退出
    sleep(3);
     //使用kill给父进程发送信号,然后父进程接收到信号后直接退出就可以了
    kill(getppid(), SIGINT);
     }
      return 0;
   }

执行结果

 1.2 alarm函数

alarm函数是UNIX和类UNIX系统中的一种标准库函数,它的主要作用是为当前进程设置一个定时器。

当设定时间到达后,定时器会向当前进程发送SIGALRM信号。

这个信号的默认行为是终止进程,但如果进程中有一个已注册的信号处理

### pthread_killraiseabort 与 SIGABRT 的关系及调试方法 在多线程程序中,`pthread_kill`、`raise` 和 `abort` 都可能触发 `SIGABRT` 信号,从而导致程序异常终止。它们各自的作用如下: - **pthread_kill**:用于向指定的线程发送信号。在多线程环境中,可以用于向特定线程发送 `SIGABRT` 信号,以触发该线程的异常终止行为。其调用形式为 `int pthread_kill(pthread_t thread, int sig)`,其中 `thread` 是目标线程的 ID,`sig` 是要发送的信号。如果目标线程没有对该信号进行处理,则可能导致整个进程终止[^1]。 - **raise**:用于向当前线程发送信号。在单线程程序中等价于 `kill(getpid(), sig)`,而在多线程程序中等价于 `pthread_kill(pthread_self(), sig)`。调用 `raise(SIGABRT)` 会向当前线程发送 `SIGABRT` 信号,若未处理该信号,则程序将中止运行[^1]。 - **abort**:直接向当前进程发送 `SIGABRT` 信号,其行为等价于 `kill(getpid(), SIGABRT)`。调用 `abort()` 会立即终止程序,并可能生成核心转储文件(core dump),以便后续调试分析。该函数通常在断言失败、异常处理未捕获或程序检测到不可恢复错误时被调用[^1]。 在多线程程序中,使用信号机制需特别小心。默认情况下,`SIGABRT` 是一个终止信号,且不能被忽略。为了在多线程程序中更可控地处理此类信号,可以通过 `pthread_sigmask` 设置信号掩码,将异步信号的处理转换为同步处理。例如,可以将所有信号的处理集中到一个专用线程中,从而避免其他线程因信号中断而导致状态不一致的问题[^2]。 ### SIGABRT 导致闪退的常见原因 程序因 `SIGABRT` 闪退通常与以下几种情况有关: - **断言失败(Assertion Failure)**:程序中使用 `assert()` 检查条件,若条件为假,`assert()` 会调用 `abort()`,导致程序终止并发送 `SIGABRT` 信号。此类问题通常出现在调试阶段,但若未及时处理,也可能在生产环境中出现[^3]。 - **C++ 异常未被捕获**:当程序抛出一个异常但没有对应的 `catch` 块时,`std::terminate()` 会被调用,而其默认实现通常会调用 `std::abort()`,从而触发 `SIGABRT` 信号[^3]。 - **内存分配失败**:某些标准库实现(如 glibc)在内存分配失败时可能调用 `abort()`,尤其是在使用 `new` 或 `malloc()` 时未能分配足够的内存[^3]。 - **第三方库错误处理**:一些库在检测到严重错误(如非法参数、状态不一致)时会主动调用 `abort()` 来终止程序[^3]。 ### 调试 SIGABRT 闪退的方法 为了有效分析和定位 `SIGABRT` 闪退问题,可以采用以下方法: - **使用 GDB 捕获崩溃堆栈**:通过 GDB 运行程序,当程序因 `SIGABRT` 崩溃时,GDB 会自动停止执行并显示当前堆栈信息,从而帮助定位 `abort()` 的调用位置。可以使用 `bt` 命令查看堆栈跟踪。 ```bash gdb ./my_program run # 程序崩溃后 bt ``` - **启用核心转储(Core Dump)**:配置系统生成核心转储文件,程序崩溃后可通过 GDB 加载 core 文件进行分析。 ```bash ulimit -c unlimited # 运行程序后生成 core 文件 gdb ./my_program core ``` - **检查日志信息**:查看程序日志,确认是否在崩溃前有断言失败、内存分配失败或其他错误信息输出。 - **使用 Valgrind 检测内存问题**:Valgrind 可以检测内存泄漏、非法访问等问题,有助于发现导致 `abort()` 的潜在原因。 ```bash valgrind --leak-check=full ./my_program ``` - **设置信号处理函数**:可以在程序中注册 `SIGABRT` 的信号处理函数,打印调试信息或进行清理操作,避免程序直接崩溃。 ```c #include <signal.h> #include <stdio.h> #include <stdlib.h> void sigabrt_handler(int sig) { fprintf(stderr, "Caught SIGABRT, performing cleanup...\n"); exit(1); } int main() { signal(SIGABRT, sigabrt_handler); abort(); // 触发 SIGABRT return 0; } ``` ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值