进程间通信 之信号 signal函数(二)

本文探讨了信号处理的两种主要方法:使用signal函数进行简单信号处理,以及利用信号集函数组进行更复杂的信号管理。通过示例代码,展示了如何注册信号处理函数以响应特定信号,如SIGINT和SIGQUIT。

信号的处理

    当系统捕捉到某个信号时,可以忽略信号或是使用指定的处理函数来处理该信号,或者使用系统默认的方式

    信号处理的主要方法有两种。一种是简单的signal函数,另一种是使用信号集函数组;

    signal()函数相当于中断处理函数,但是是一种软中断;

   Signal函数主要用于32种非实时信号处理;

#include<stdio.h>

#include<signal.h>

#include<stdlib.h>



void cancel(int sig)

{
    printf("当前程序取消了crtl+C功能!\n");
}

int main1()

{
    signal(SIGINT,cancel);

    while(1)

    {

        printf(".\n");

        sleep(1);

    }

    return 0;
}



void my_func(int sign_no)

{
    if(sign_no==SIGINT)

        printf("I have get SIGINT\n");

    if(sign_no==SIGQUIT)

        printf("I haev get SIGQUIT\n");
}
int main()

{
    printf("Waiting fro signal SIGINT or SIGPQUIT\n");

    signal(SIGINT,my_func);

    signal(SIGQUIT,my_func);
    pause();
    exit(0);
}













 

 

 

 

 

 

 

 

<think> 我们正在讨论Linux进程间通信中的信号机制,特别是kill函数的详细情况。 根据用户的问题,他要求了解kill函数的详情。同时,根据之前的对话历史,我们已经介绍了信号机制的核心概念、关键特性、应用场景以及一些系统调用,其中提到了kill函数。 现在,我们需要详细解释kill函数: 1. 函数原型:int kill(pid_t pid, int sig); 2. 功能:向指定进程(或进程组)发送一个信号。 3. 参数: pid: 接收信号的进程(或进程组)的ID。它的取值有几种情况: >0:发送给进程ID为pid的进程。 =0:发送给与发送进程属于同一个进程组的所有进程(不包括系统进程)。 -1:发送给所有有权限发送的进程(除init和自身外,通常为当前用户进程)。 <-1:发送给进程组ID等于|pid|的所有进程。 sig: 要发送的信号编号。如果为0,则不发送信号,但会执行错误检查(用于检查目标进程是否存在)。 4. 返回值: 成功时返回0。 失败时返回-1,并设置errno(常见的错误有:EINVAL-无效的信号;EPERM-权限不足;ESRCH-目标进程不存在)。 5. 权限检查: - 超级用户(root)可以向任何进程发送信号。 - 非超级用户只能向同一用户ID的进程发送信号。 6. 使用场景: - 终止进程(SIGTERM, SIGKILL) - 用户自定义通信(SIGUSR1, SIGUSR2) - 通知进程某些事件(如SIGHUP重新加载配置) 7. 示例:父进程向子进程发送SIGUSR1信号。 8. 注意事项: - 发送信号0(空信号)用于检测目标进程是否存在。 - 不能向init进程(PID=1)发送信号,除非信号是内核明确允许的。 我们将按照以上要点组织回答,并给出一个代码示例。 同时,我们需要在回答末尾添加相关问题。 注意:根据用户要求,我们使用中文回答,并且注意引用格式(在引用内容末尾添加[^1]等)。由于之前的引用[1]和[2]是关于信号机制的,我们在介绍kill函数时可以引用它们。 由于kill函数信号发送的核心函数,我们在介绍时会结合信号机制的一些背景知识,但重点在kill函数本身。 另外,根据用户之前的提问,我们已经在“四、核心系统调用”部分提到了kill,现在要详细展开。 注意:不要重复之前已经写过的内容,但可以适当提及以保持连贯性。 </think> ### Linux 信号机制中的 `kill()` 函数详解 `kill()` 是 Linux 信号机制中**核心的信号发送函数**,用于向指定进程或进程组发送信号。其函数原型为: ```c #include <sys/types.h> #include <signal.h> int kill(pid_t pid, int sig); ``` --- #### 一、参数解析 | **参数** | **类型** | **作用** | **特殊取值示例** | |----------|----------|--------------------------------------------------------------------------|---------------------------------------| | `pid` | `pid_t` | 目标进程/进程组标识符 | `>0`:指定进程ID<br>`0`:同进程组所有进程<br>`-1`:所有有权限的进程<br>`<-1`:进程组ID=`|pid|` | | `sig` | `int` | 信号编号(如 `SIGTERM=15`, `SIGKILL=9`) | `0`:仅检查权限,不发送信号 | --- #### 、返回值与错误码 - **成功**:返回 `0` - **失败**:返回 `-1`,并设置 `errno`: - `EINVAL`:无效信号(如 `sig > 64`) - `EPERM`:权限不足(如非 root 向系统进程发 `SIGKILL`) - `ESRCH`:目标进程不存在(PID 无效) --- #### 三、典型应用场景 1. **终止进程** ```c kill(target_pid, SIGTERM); // 优雅终止 kill(target_pid, SIGKILL); // 强制终止(无法捕获) ``` 2. **进程间通知** ```c kill(pid, SIGUSR1); // 用户自定义事件通知 ``` 3. **进程组控制** ```c kill(-process_group_id, SIGHUP); // 向整个进程组发信号 ``` 4. **进程存在性检查** ```c if (kill(pid, 0) == 0) printf("进程 %d 存在\n", pid); // 信号0仅检查权限 ``` --- #### 四、底层机制 1. **内核处理流程** ```mermaid graph LR A[kill() 系统调用] --> B[内核验证权限] B --> C{目标进程存在?} C -->|是| D[将信号加入目标进程待处理队列] C -->|否| E[返回ESRCH错误] D --> F[触发信号处理机制] ``` 2. **信号传递规则** - 若目标进程**阻塞**该信号(通过 `sigprocmask()`),信号暂存于待处理队列 - 若目标进程**注册处理函数**,内核在进程返回用户态时触发处理函数 - `SIGKILL` 和 `SIGSTOP` 直接由内核处理,无法被捕获或忽略[^1] --- #### 五、安全实践要点 1. **权限控制** - 非 root 用户只能向**同一用户ID的进程**发送信号 - 特权进程(root)可向任意进程发送信号 2. **原子操作** 多线程环境中建议配合 `pthread_kill()` 使用,避免竞争条件: ```c pthread_kill(thread_id, SIGUSR1); // 向特定线程发信号 ``` 3. **实时信号优化** 需传递数据时,优先选用实时信号(`SIGRTMIN` 至 `SIGRTMAX`): ```c union sigval value; value.sival_int = 123; sigqueue(pid, SIGRTMIN, value); // 附带整型数据 ``` --- #### 六、代码示例:父子进程通信 ```c #include <signal.h> #include <unistd.h> #include <stdio.h> void handler(int sig) { if (sig == SIGUSR1) write(STDOUT_FILENO, "Received SIGUSR1!\n", 18); } int main() { pid_t child_pid = fork(); if (child_pid == 0) { // 子进程 signal(SIGUSR1, handler); while(1) pause(); // 等待信号 } else { // 父进程 sleep(1); kill(child_pid, SIGUSR1); // 发送信号 wait(NULL); // 等待子进程结束 } return 0; } ``` > 输出:`Received SIGUSR1!` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值