> 技术文档 > 用户态 kill 与 pthread_kill 的区别?

用户态 kill 与 pthread_kill 的区别?

在 Linux 用户态中,pthread_killkill 都能发送系统信号,但它们的作用对象、使用场景和行为有显著区别,核心差异在于信号的接收者不同

1. 作用对象不同

  • kill(pid_t pid, int sig)
    用于向 进程 发送信号,pid 参数指定目标进程的 ID:
    • pid > 0:向 ID 为 pid进程发送信号
    • pid = 0:向当前进程所在进程组的所有进程发送信号
    • pid = -1:向系统中所有有权限发送的进程发送信号(特殊权限下)
    • pid < -1:向进程组 ID 为 |pid| 的所有进程发送信号
  • pthread_kill(pthread_t thread, int sig)
    用于向 同一进程内的特定 线程 发送信号,thread 参数是目标线程的 ID(由 pthread_create 返回)。

2. 信号的处理范围不同

  • kill 发送的信号:属于进程级信号,默认由进程内的 “主线程” 或 “任意线程” 处理(取决于信号处理函数的注册方式)。
    例如,若进程中注册了 SIGINT 的处理函数,用 kill 向该进程发送 SIGINT,会触发进程内的该处理函数(由内核选择一个线程执行)。
  • pthread_kill 发送的信号:属于线程级信号,专门针对指定线程,信号处理函数在目标线程的上下文中执行。
    例如,向 ‘线程 A’ 发送 SIGUSR1,若该信号已注册处理函数,则处理函数在 ‘线程 A’ 中运行。

3. 特殊信号的行为差异

  • 对于会导致进程终止的信号(如 SIGKILLSIGTERM):
    • 无论用 kill 还是 pthread_kill 发送,最终都会导致整个进程终止(因为线程是进程的一部分,进程终止会带动所有线程终止)。
    • 区别在于:kill 直接针对进程,pthread_kill 虽指定线程,但信号的 “终止进程” 语义会作用于整个进程。
  • 对于可捕获的信号(如 SIGUSR1SIGALRM):
    • kill 发送的信号可能被进程内任意线程捕获(内核调度决定)。
    • pthread_kill 发送的信号只会被目标线程捕获(如果该线程未阻塞此信号)。

4. 使用场景不同

  • kill 的典型场景
    进程间通信,例如:
    • 终端通过 kill 向后台进程发送 SIGTERM 要求其退出
    • 父进程向子进程发送信号控制其行为
  • pthread_kill 的典型场景
    同一进程内的线程间通信,例如:
    • 主线程向阻塞的子线程发送信号,中断其阻塞状态(如从 sleepwait 中唤醒)
    • 通知特定线程处理某个事件

示例对比

#include #include #include #include #include #include // 信号处理函数void sig_handler(int sig) { printf(\"信号 %d 在线程 %lu 中被处理\\n\", sig, pthread_self());}// 子线程函数void *thread_son_func(void *arg) { printf(\"子线程 %lu 启动\\n\", pthread_self()); //与ps -T -p 得到的线程ID无关,这样打印也不太规范 while (1) { sleep(1); // 模拟阻塞 } return NULL;}int main() { signal(SIGUSR1, sig_handler); // 注册信号处理函数 pthread_t tid; pthread_create(&tid, NULL, thread_son_func, NULL); sleep(1); //给线程创建留点时间 // 用 pthread_kill 向 \"子线程\" 发送信号 pthread_kill(tid, SIGUSR1); // 信号在子线程中处理 sleep(1); //给信号中打印留点时间 // 用 kill 向当前 \"进程\" 发送信号(可能被任意线程处理) kill(getpid(), SIGUSR1); // 信号可能在主线程或子线程中处理 pthread_join(tid, NULL); return 0;}

输出可能为:

子线程 140610751647488 启动信号 10 在线程 140610751647488 中被处理 // pthread_kill 发送,子线程处理信号 10 在线程 140610759944576 中被处理 // kill 发送,主线程处理(可能不同)

总结

特性 kill pthread_kill 接收者 进程(或进程组) 同一进程内的特定线程 信号处理上下文 进程内任意线程(内核决定) 目标线程本身 主要用途 进程间信号通信 同一进程内线程间信号通信 对进程的影响 可能终止整个进程(如 SIGKILL) 同左(信号语义决定,与线程无关)

简单说:kill 是 “给进程发信号”,pthread_kill 是 “给进程内的某个线程发信号”。

双胞胎育儿