zqurgy

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

signal

  • signal源码位置:、
    • 信号集合../sched/signal.h
    • 信号结构体:../signal_types.h
    • signal函数:..\kernel\signal.c

sigio的概述流程

  • 对于网络IO来说,一旦收到数据,信号机制会发送sigio这个信号
    • 简单使用sigio,udp可以使用,tcp不行
  • 网卡接收到数据帧,并发送给协议栈

  • 网络协议栈处理原生包(raw package),再发送给应用程序

  • 应用程序进一步处理

signal的工作流程

  • signal函数和kill函数属于系统调用

  • 从三个方面进行梳理

    • 对于进程内部,这些信号集合如何保存?
    • 调用signal函数时,是怎么保存到进程内部?
    • 其他进程调用某个命令(kill -9 pid)时,这个信号是如何发送?

  1. 对于进程内部,这些信号集合如何保存?

    • 信号集合用一个结构体数组保存struct k_sigaction action[_NSIG];;
    • 数组大小为64,多处定义#define _NSIG 64;
    • struct k_sigaction- 》维护struct sigaction-》维护struct sigaction
    struct sighand_struct {
    ...
    wait_queue_head_t signalfd_wqh;
    struct k_sigaction action[_NSIG];// 数组维护
    };
    struct sigaction {
    ...
    __sighandler_t _sa_handler;
    void (*_sa_sigaction)(int, struct siginfo *, void *);
    };
  2. 调用signal函数时,是怎么保存到进程内部?

    • 系统调用内部调用关键函数do_sigaction()
    • 将当前进程中信号数组的第X为进行覆盖
      • X为信号的值#define SIGIO 29-》总共32个信号
    int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact{
    struct task_struct *p = current, *t;//当前进程的指针
    struct k_sigaction *k;// 第一问中提过
    ...
    k = &p->sighand->action[sig-1];//提取出信号集合中该信号对应的位置
    ...
    *k = *act;//该信号的对应位置进行覆盖,如sigio是29,会对索引第28位进行覆盖
    ...
    }
    • 额外说明

      第一层:`SYSCALL_DEFINE2(signal, int, sig, __sighandler_t, handler)`;
      第二层:int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact);
  3. 其他进程调用某个命令(kill -9 pid)时,这个信号是如何发送?

    • 系统调用内部套层调用关键函数signalfd_notify()
    • 中间套层的函数中会找到kill要发送的pid是否存在,并且找到那个进程
    • 发送信号给该进程,并将其唤醒
    static inline void signalfd_notify(struct task_struct *tsk, int sig) {
    if (unlikely(waitqueue_active(&tsk->sighand->signalfd_wqh)))
    wake_up(&tsk->sighand->signalfd_wqh);
    }
    #define wake_up(x) __wake_up(x, TASK_NORMAL, 1, NULL)
    • 额外说明

      1层:`SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)`;
      2层:static int kill_something_info(int sig, struct kernel_siginfo *info, pid_t pid);
      3层:static int kill_proc_info(int sig, struct kernel_siginfo *info, pid_t pid);
      4层:int kill_pid_info(int sig, struct kernel_siginfo *info, struct pid *pid);
      5层:int group_send_sig_info(int sig, struct kernel_siginfo *info,
      struct task_struct *p, enum pid_type type);
      6层:int do_send_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *p,enum pid_type type);
      7层:int send_signal_locked(int sig, struct kernel_siginfo *info,
      struct task_struct *t, enum pid_type type);
      8层:static int __send_signal_locked(int sig,
      struct kernel_siginfo *info,struct task_struct *t, enum pid_type type, bool force);
      9层:static inline void signalfd_notify(struct task_struct *tsk, int sig);
      • 第二层:进行pid的判断

posted on   ZqurGy  阅读(143)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示