Linux信号-1-TIF_SIGPENDING 标志的设置和清除

基于msm-5.4

一、调用路径

1. 设置的位置

                            recalc_sigpending_and_wake //signal.c
    sysrq_term_op //sysrq.c 【】-e 操作结束所有进程 echo e > /proc/sysrq-trigger
        sysrq_handle_term //sysrq.c
    sysrq_kill_op //sysrq.c 【】 -i选项,kill掉所有进程 echo i > /proc/sysrq-trigger
        sysrq_handle_kill //sysrq.c
            send_sig_all //sysrq.c 对所有进程进行调用
            __do_notify //mqueue.c 没编译到
    hwpoison_user_mappings //memory-failure.c 【】内存操作失败kill掉进程
    memory_failure_dev_pagemap //memory-failure.c
        kill_procs //memory-failure.c
    kill_fasync_rcu //fcntl.c
        send_sigio //fcntl.c
            send_sigio_to_task //fcntl.c
        send_sigurg //fcntl.c
            send_sigurg_to_task //fcntl.c
            group_send_sig_info //signal.c
        oom_kill_memcg_member //oom_kill.c 【】对所有进程发送 SIGKILL 信号
        oom_kill_process //oom_kill.c
            __oom_kill_process //oom_kill.c
        send_sig //signal.c
        send_sig_fault //signal.c
        send_sig_mceerr //signal.c
        aa_audit //audit.c
        __raise_exception //f_mass_storage.c
            send_sig_info //signal.c
            do_send_specific //signal.c
                do_send_sig_info //signal.c
                __group_send_sig_info //signal.c
                force_sig_info_to_task //signal.c
                ptrace_signal //signal.c
                kdb_send_sig //signal.c
                    send_signal //signal.c
                    kill_pid_usb_asyncio //signal.c
                    do_notify_parent //signal.c
                        __send_signal //signal.c
                alarm_handle_timer //alarmtimer.c
                cpu_timer_fire //posix-cpu-timers.c
                posix_timer_fn //posix-timers.c
                    posix_timer_event //posix-timers.c 
                        send_sigqueue //signal.c
                            complete_signal //signal.c
                            zap_other_threads //signal.c
                            do_signal_stop //signal.c
                            retarget_shared_pending //signal.c
                            cgroup_freeze_task //freezer.c
                        freeze_task //freezer.c
                            fake_signal_wake_up //freezer.c
                            zap_process //coredump.c
                                signal_wake_up //signal.h
                                ptrace_signal_wake_up //signal.h
                                ptrace_attach //ptrace.c
                                    signal_wake_up_state //signal.c 设置标志位并唤醒任务
                                        set_tsk_thread_flag(t, TIF_SIGPENDING)

设置的位置一共有:

recalc_sigpending_tsk //signal.c
    set_tsk_thread_flag(t, TIF_SIGPENDING);
calculate_sigpending //signal.c
    set_tsk_thread_flag(current, TIF_SIGPENDING)
signal_wake_up_state //signal.c 先主要看这个
    set_tsk_thread_flag(t, TIF_SIGPENDING)


2. clear的位置

                ret_from_fork //entry.S 【】新fork的任务唤醒时会清除信号pending标志
                    schedule_tail(prev) //core.c
                        calculate_sigpending //signal.c
    SYSCALL_DEFINE4(signalfd4 //signalfd.c
    SYSCALL_DEFINE3(signalfd //signalfd.c
    do_compat_signalfd4 //signalfd.c
        do_signalfd4 //signalfd.c
            signalfd_fops //signalfd.c
                signalfd_read //signalfd.c
                    signalfd_dequeue //signalfd.c
                handle_exception //usb/f_mass_storage.c
                jffs2_garbage_collect_thread //jffs2/background.c 
                    kernel_dequeue_signal //signal.h
    ret_to_user //arm64/entry.S【】返回用户空间信号被处理后pending标志会被清除 ###
        work_pending //arm64/entry.S
            do_notify_resume //signal.c
                do_signal //signal.c
                    get_signal //signal.c
                SYSCALL_DEFINE4(rt_sigtimedwait //signal.c 【】系统调用中有清理逻辑
                SYSCALL_DEFINE4(rt_sigtimedwait_time32 //signal.c
                COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait_time64 //signal.c
                    do_sigtimedwait //signal.c
                        dequeue_signal //signal.c
                get_signal //signal.c
                        dequeue_synchronous_signal //signal.c
                user_single_step_report //ptrace.h
                seccomp_send_sigsys //seccomp.c
                force_sig //signal.c
                force_sig_mceerr //signal.c
                force_sig_bnderr //signal.c
                force_sig_pkuerr //signal.c
                force_sig_ptrace_errno_trap //signal.c
                    force_sig_info //signal.c
        arm64_notify_die //traps.c
        bad_el0_sync //traps.c
    single_step_handler //debug-monitors.c
    brk_handler //debug-monitors.c
        send_user_sigtrap //debug-monitors.c
            arm64_force_sig_fault //arm64/kernel/traps.c 
                force_sig_fault //signal.c
                user_enable_single_step //ptrace.c
                    force_sig_fault_to_task //signal.c
                        force_sig_info_to_task //signal.c
                        get_signal //signal.c 上面已经有调用路径了
                        __set_task_blocked //signal.c
                        do_sigtimedwait //signal.c
                    allow_signal //signal.h 【】内核有自己的信号逻辑!!!
                    allow_kernel_signal //signal.h
                    disallow_signal //signal.h
            call_usermodehelper_setup //umh.c
            call_usermodehelper_setup_file //umh.c
                call_usermodehelper_exec_work //umh.c
                    call_usermodehelper_exec_sync //umh.c
                        kernel_sigaction //signal.c
                        copy_process //fork.c 【】创建任务时会清理pending信号标志
                            recalc_sigpending //signal.c
                                clear_thread_flag(TIF_SIGPENDING)


clear信号的位置还有:

    flush_signals //signal.c
        clear_tsk_thread_flag(t, TIF_SIGPENDING);

    do_freezer_trap
        clear_thread_flag(TIF_SIGPENDING)

    __exit_signal(tsk) //exit.c
        clear_tsk_thread_flag(tsk, TIF_SIGPENDING);

    zap_pid_ns_processes //pid_namespace.c
        clear_thread_flag(TIF_SIGPENDING);

    cgroup_leave_frozen
        set_thread_flag(TIF_SIGPENDING);

    zap_threads
        clear_tsk_thread_flag(tsk, TIF_SIGPENDING);

    clear_thread_flag(TIF_SIGPENDING) //st33zp24.c

    __tty_check_change
        set_thread_flag(TIF_SIGPENDING);

    wait_for_tpm_stat //tpm_tis_core.c
        clear_thread_flag(TIF_SIGPENDING);


注1: signalfd 是用于 同步化信号处理 的机制,通过文件描述符将信号转化为可读事件。Android中只有这两个位置有使用:

# TDIR=/proc; let RSS=0; for P in `ls $TDIR | grep "^[0-9]"`; do echo $P; ls -l /proc/$P/fd | grep signalfd; done
1 //init进程
lrwx------ 1 root root 64 1970-01-01 12:11 6 -> anon_inode:[signalfd]
31265 //update_engine进程
lrwx------ 1 root root 64 2025-05-07 14:08 10 -> anon_inode:[signalfd]


注2:umh.c中提供的call user mode helper 功能,是内核态触发用户空间进程执行的核心机制(内核创建用户进程并执行),典型应用场景比如内核模块加载。

// kernel/module.c
static int load_module(..., const char *modname) {
    char *argv[] = { "/sbin/modprobe", modname, NULL };
    call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
}


3. 小结

看起来 TIF_SIGPENDING 标志位主要是在任务被信号唤醒时设置,在返回用户空间处理信号时恢复

 

posted on 2025-05-20 21:39  Hello-World3  阅读(40)  评论(0)    收藏  举报

导航