Linux进程管理
Linux进程管理(一)进程数据结构
Linux内核中使用
task_struct
结构来表示一个进程,这个结构体保存了进程的所有信息,所以它非常庞大,在讲解Linux内核的进程管理,我们有必要先分析这个
task_struct
中的各项成员
双向链表
struct list_head tasks;
Linux将所有的 task_struct 串联成一个双向循环链表
任务ID
pid_t pid;
pid_t tgid;
struct task_struct *group_leader;
- pid:每个进程都有自己的
pid
,它在内核中是唯一的,在Linux中,我们可以使用ps -ef
查看所有的进程,其中 PID 就是进程号。pid可以给用户查看指定进程的信息,可以通过pid给指定的进程发送信号 - tgid:tigd 是 thread group ID,表示线程组id。thread group 是线程组的意思,所谓的线程组是什么意思呢?内核中不管是线程或者是进程都是使用 task_struct 来表示,一个进程也可以称为主线程,由它创建多个线程,这些线程和进程的主线程就称为一个线程组。每个线程都有自己的pid,而 tgid 则等于进程的主线程的 pid,这样也就可以区分谁是主线程,谁是被主线程创建出来的
- group_leader:指向线程组主线程的进程描述符
通过 getpid 返回的是 tgid,也就是说同一个线程组共享一个 pid
信号处理
/* Signal handlers: */
struct signal_struct *signal;
struct sighand_struct *sighand;
sigset_t blocked;
sigset_t real_blocked;
sigset_t saved_sigmask;
struct sigpending pending;
unsigned long sas_ss_sp;
size_t sas_ss_size;
unsigned int sas_ss_flags;
- blocked:sigset_t 是一个位图,每个位都表示一个信号。blocked 表示的是该进程的哪些信号被阻塞暂不处理
- pending:表示进程接收到了哪些信号,需要被处理
- sighand:用户可以定义相应信号的处理方法,其信息保存在这里
- sas_ss_xxx:信号的处理默认使用的是进程用户空间的函数栈,也可以开辟新的栈专门用于信号处理,这三个变量就是用户维护这个栈信息
在 signal 中,定义了 struct sigpending shared_pending,这个 shared_pending 和 pending 的区别是,pending 表示该 task_struct 收到的信号,而 shared_pending 是整个线程组共享的。也就是说,对于 pending 中接收到的信号,只能由这个 task_struct 来处理,而 shared_pending 中收到的信号,可以由线程组中的任意一个线程处理
进程状态
在 task_struct 中,定义了这样几个变量,与进程的状态有关
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
int exit_state;
unsigned int flags;
state 和 exit_state 的定义如下
/* Used in tsk->state: */
#define TASK_RUNNING 0
#define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
#define __TASK_STOPPED 4