在kernel space monitor 系统调用来观察userspace进程的行为。

1.简介

近期遇到在userspace的进程随机关闭fd 0的问题,最后导致其他进程使用fd 0时出现coredump。

如果能够在close系统调用中检查所有的进程调用close时,通过传入参数是否为0来找出问题,会比较方便。

2.做法

 a.out是我们需要monitor的进程,因为它可能是线程,所以我们通过tgid来找到进程的pid。

通过struct_tast *tsk; 来获取进程的task,最后发信号也是给进程。

1     if (fd == 0){
2         tsk = pid_task(find_pid_ns(tid, task_active_pid_ns(current)), PIDTYPE_PID);
3         pr_err("DENNIS: fd 0 is be close for %s-%d tid %d tsk %s
", current->comm, current->pid, current->tgid, tsk->comm);
4         if (!strncmp(tsk->comm, "a.out", sizeof("a.out"))){
5             extern int do_send_sig_info(int sig, struct siginfo *info, struct task_struct *p,enum pid_type type);
6             do_send_sig_info(SIGABRT, SEND_SIG_FORCED, tsk, true);
7         }
8     }

 3. 看到 stack overflow中介绍pid 与tgid比较好的介绍,这里直接粘贴来了。

内核中,每个线程都有自己的ID,称为PID(尽管将其称为TID或线程ID可能更有意义),并且它们还具有TGID(线程组ID),它是线程的PID这开始了整个过程。

简而言之,当创建一个新进程,它显示为一个线程,其中PID和TGID都是相同(新)编号。

当一个线程启动另一个线程时,该启动的线程会获得其自己的PID(因此调度程序可以独立调度它),但是它从原始线程继承了TGID。

这样,内核可以愉快地调度线程,而与线程所属的进程无关,而将进程(线程组ID)报告给您。

以下线程层次结构可能会有所帮助(a)

                      USER VIEW
 <-- PID 43 --> <----------------- PID 42 ----------------->
                     +---------+
                     | process |
                    _| pid=42  |_
                  _/ | tgid=42 | \_ (new thread) _
       _ (fork) _/   +---------+                  
      /                                        +---------+
+---------+                                    | process |
| process |                                    | pid=44  |
| pid=43  |                                    | tgid=42 |
| tgid=43 |                                    +---------+
+---------+
 <-- PID 43 --> <--------- PID 42 --------> <--- PID 44 --->
                     KERNEL VIEW

您可以看到,启动一个新进程(左侧)会为您提供一个新的PID一个新的TGID(两者都设置为相同的值),而启动一个新线程(右侧)会为您提供一个新的PID,同时保持相同的值TGID作为启动它的线程。

4. 列一下Linux的信号。

SIGHUP       1          /* Hangup (POSIX).  */                          终止进程     终端线路挂断
SIGINT       2          /* Interrupt (ANSI).  */                        终止进程     中断进程 Ctrl+C
SIGQUIT      3          /* Quit (POSIX).  */                            建立CORE文件终止进程,并且生成core文件 Ctrl+
SIGILL       4          /* Illegal instruction (ANSI).  */              建立CORE文件,非法指令
SIGTRAP      5          /* Trace trap (POSIX).  */                      建立CORE文件,跟踪自陷
SIGABRT      6          /* Abort (ANSI).  */
SIGIOT       6          /* IOT trap (4.2 BSD).  */                      建立CORE文件,执行I/O自陷
SIGBUS       7          /* BUS error (4.2 BSD).  */                     建立CORE文件,总线错误
SIGFPE       8          /* Floating-point exception (ANSI).  */         建立CORE文件,浮点异常
SIGKILL      9          /* Kill, unblockable (POSIX).  */               终止进程     杀死进程
SIGUSR1      10         /* User-defined signal 1 (POSIX).  */           终止进程     用户定义信号1
SIGSEGV      11         /* Segmentation violation (ANSI).  */           建立CORE文件,段非法错误
SIGUSR2      12         /* User-defined signal 2 (POSIX).  */           终止进程     用户定义信号2
SIGPIPE      13         /* Broken pipe (POSIX).  */                     终止进程     向一个没有读进程的管道写数据
SIGALARM     14         /* Alarm clock (POSIX).  */                     终止进程     计时器到时
SIGTERM      15         /* Termination (ANSI).  */                      终止进程     软件终止信号
SIGSTKFLT    16         /* Stack fault.  */
SIGCLD       SIGCHLD    /* Same as SIGCHLD (System V).  */
SIGCHLD      17         /* Child status has changed (POSIX).  */        忽略信号     当子进程停止或退出时通知父进程
SIGCONT      18         /* Continue (POSIX).  */                        忽略信号     继续执行一个停止的进程
SIGSTOP      19         /* Stop, unblockable (POSIX).  */               停止进程     非终端来的停止信号
SIGTSTP      20         /* Keyboard stop (POSIX).  */                   停止进程     终端来的停止信号 Ctrl+Z
SIGTTIN      21         /* Background read from tty (POSIX).  */        停止进程     后台进程读终端
SIGTTOU      22         /* Background write to tty (POSIX).  */         停止进程     后台进程写终端
SIGURG       23         /* Urgent condition on socket (4.2 BSD).  */    忽略信号     I/O紧急信号
SIGXCPU      24         /* CPU limit exceeded (4.2 BSD).  */            终止进程     CPU时限超时
SIGXFSZ      25         /* File size limit exceeded (4.2 BSD).  */      终止进程     文件长度过长
SIGVTALRM    26         /* Virtual alarm clock (4.2 BSD).  */           终止进程     虚拟计时器到时
SIGPROF      27         /* Profiling alarm clock (4.2 BSD).  */         终止进程     统计分布图用计时器到时
SIGWINCH     28         /* Window size change (4.3 BSD, Sun).  */       忽略信号     窗口大小发生变化
SIGPOLL      SIGIO      /* Pollable event occurred (System V).  */
SIGIO        29         /* I/O now possible (4.2 BSD).  */              忽略信号     描述符上可以进行I/O
SIGPWR       30         /* Power failure restart (System V).  */
SIGSYS       31         /* Bad system call.  */
SIGUNUSED    31

来源:https://www.cnblogs.com/frisk/p/11602973.html

5.进程如何接受信号。

可以参考之前的介绍:https://www.cnblogs.com/smilingsusu/p/12845474.html

原文地址:https://www.cnblogs.com/smilingsusu/p/13933562.html