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\n", 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