进程控制和通信(四)

本文详细介绍了Linux中的进程控制结构task_struct,包括任务ID、亲缘关系、任务状态、权限、运行统计、调度相关、信号处理、内存管理和文件系统等内容。重点讨论了进程状态的多种类型,如运行、等待、退出和暂停,并阐述了进程的权限管理和调度策略的基本原理。
摘要由CSDN通过智能技术生成

在前面的文章中, 我们学习了进程通信的几种方式, 并且也接触到了内核控制进程的结构块task_struct, task_struct的内容主要会分为以下几个部分, 通过这一篇文章可以学习这些部分的大体内容.

task_struct

https://i-blog.csdnimg.cn/blog_migrate/15eab0b783854c7e3139f65658683b6c.png

task_struct

  • 任务ID: 用于区分进程, 是进程的身份证, 比如pid就属于任务ID
  • 亲缘关系: 包含兄弟进程, 父子进程的信息
  • 任务状态: 用于标识当前进程的运行状态, 比如running, runable, stop, wait等;
  • 权限: 进程权限信息, 包括本进程对外以及外对本进程的权限
  • 运行统计: 包括启动时间, cpu占用时间等信息
  • 调度相关: 包含进程优先级, 调度策略等信息
  • 信号处理: 阻塞/等待等信息, 以及信号处理函数(见进程控制和进程通信三)
  • 内存管理: 进程虚拟内存空间
  • 文件与文件系统: 进程文件
  • 内核栈: 内核栈地址

任务ID

和任务ID相关的成员大概有以下:

1
2
3
pid_t				pid;                            // 进程id
pid_t				tgid;                           // 线程group id
struct task_struct		*group_leader;              // 线程group leader

group_leader是指向线程group第一个task的指针. 比如在setpgid函数中会用到.

Linux将current包装为了一个宏, 用来获取在当前CPU上运行的task_struct地址.

1
2
3
4
5
6
DECLARE_PER_CPU(struct task_struct *, current_task);
static __always_inline struct task_struct *get_current(void)
{
	return this_cpu_read_stable(current_task);
}
#define current get_current()

一般, 我们可以调用getpid获取进程的进程id, 实际上getpid返回的是task_structtgid. (当然这个函数的调用栈不是这么简单的, 还涉及到了Linux的namespace概念, 这里就先简单处理了, 以下的接口同样简单处理)

1
2
3
4
SYSCALL_DEFINE0(getpid)
{
	return task_tgid_vnr(current);
}

同样, 我们也可以用gettid获取当前线程的线程id, 实际上gettid返回的是task_structpid.

1
2
3
4
SYSCALL_DEFINE0(gettid)
{
	return task_pid_vnr(current);
}

另外, 也可以通过getppid获取父进程的进程id, 实际上getppid返回的是task_structreal_parenttgid.

1
2
3
4
5
6
7
8
SYSCALL_DEFINE0(getppid)
{
	int pid;
	rcu_read_lock();
	pid = task_tgid_vnr(rcu_dereference(current->real_parent));
	rcu_read_unlock();
	return pid;
}

对内核来说, 没有区分进程和线程的概念, 在内核中, 这两种概念都叫task, 由task_struct结构体管理. 所以, 怎么来区分进程和线程呢? 内核会用pidtgid两个成员区分, pid表示的当前task_struct的id, 可以认为是task_struct的标识符, 每个task都不一样. 如果某个进程/线程创建了一个子线程, 那么就会生成一个新的pid, 但是会继承父结点的tgid.

https://z3.ax1x.com/2021/05/18/gfjEiF.png

pid和tgid

为什么有这两个概念? 我猜是因为从单核单进程时代到多进程时代迁移的遗留问题.

亲缘关系

与task亲缘关系相关的成员如下:

1
2
3
4
5
6
7
/* Real parent process: */
struct task_struct __rcu	*real_parent;
/* Recipient of SIGCHLD, wait4() reports: */
struct task_struct __rcu	*parent;
/* Children/sibling form the list of natural children: */
struct list_head		children;
struct list_head		sibling;

real_parent指向的是真正的parent进程, 如下是进程clone时的一段代码, 可以看到real_parent是指向子(新)进程的父进程. 如果创建的是thread, 则和父进程的real_parent相同.

1
2
3
4
5
6
7
8
/* CLONE_PARENT re-uses the old parent */
if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) {
    p->real_parent = current->real_parent;
    p->parent_exec_id = current->parent_exec_id;
} else {
    p->real_parent = current;
    p->parent_exec_id = current->self_exec_id;
}

parent指向的是给当前进程传递SIGCHLD信号的进程, 这个进程一般是debug进程, 比如GDB调试进程, 这时候parent就是指向的GDB进程.

比如ptrace的link阶段, 就会更新parent的指向.

1
2
3
4
5
6
7
8
void __ptrace_link(struct task_struct *child, struct task_struct *new_parent,
		   const struct cred *ptracer_cred)
{
	BUG_ON(!list_empty(&child->ptrace_entry));
	list_add(&child->ptrace_entry, &new_parent->ptraced);
	child->parent = new_parent;
	child->ptracer_cred = get_cred(ptracer_cred);
}

关于parent的参考信息可见kernelnewbies:parent和real_parent.

children用于存放子进程指针, sibling存放兄弟进程指针;

任务状态

与任务状态相关的一些成员如下:

1
2
3
4
5
/* -1 unrunnable, 0 runnable, >0 stopped: */
volatile long			state;
/* Per task flags (PF_*), defined further below: */
unsigned int			flags;
int				exit_state;

以下是关于state的描述:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* Used in tsk->state: */
#define TASK_RUNNING			0x0000
#define TASK_INTERRUPTIBLE		0x0001
#define TASK_UNINTERRUPTIBLE	0x0002
#define __TASK_STOPPED			0x0004
#define __TASK_TRACED			0x0008
/* Used in tsk->exit_state: */
#define EXIT_DEAD				0x0010
#define EXIT_ZOMBIE			
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值