linux 的进程与线程在源码中都对应到同一个结构体task_struct
, 它位于include/linux/sched.h
中, 他有很多很多成员, 下面我们分析一下主要成员及其作用。
1. 任务列表
有了任务列表, 操作系统就能知道当前任务的下一个任务和上一个任务了。
为什么是双向链表呢?因为可以高效的删除, 并且可以反向遍历。
至于为什么不是数组? 因为要频繁的创建删除, 数组咋行呢。
struct list_head tasks; // 双向链表, 维护任务列表
2. 任务ID
这里的pid_t类型是一个int, 为什么有一个pid还需要有一个tgid呢, 这是因为进程和线程在操作系统眼里都是一个task_struct, 但是总归要区分不是, pid就是这个task_struct的id, tgid则是这个task_struct所属于的group id。
换言之:
- task_struct是进程, pid == tgid
- task_struct是进程, pid != tgid
那为什么需要一个group_leader呢?可以注意到它是一个指针, 自然是为了快速访问这个task_struct的老大了!
pid_t pid; // process ID
pid_t tgid; // thread group ID
struct task_struct *group_leader;
3. 信号处理
上面提到,一个task_struct是有leader的,当操作系统要给一个小组发信号,当然是要发给leader,再由leader转发给小组的每个人,那这些信号都有什么呢?
/* Signal handlers: */
struct signal_struct *signal;
struct sighand_struct __rcu *sighand;
sigset_t blocked;
sigset_t real_blocked;
/* Restored if set_restore_sigmask() was used: */
sigset_t saved_sigmask;
struct sigpending pending;
unsigned long sas_ss_sp;
size_t sas_ss_size;
unsigned int sas_ss_flags;