目录
进程
进程在linux 里也叫任务。
对于user space来讲,进程是程序执行时的一个实例。可以把进程比作一个人类个体:只有一个父进程,可以有多个子进程;有或多或少的有效生命;承担一定的功能或任务;拥有不同的状态,且任一时刻有且只有一种状态;最终都会消亡。
对于kernel space来讲,进程的目的就是合理的分配系统资源的实体。每个进程都会通过内核获取自己的CPU、内存等系统资源,从而执行任务。
1. 进程描述符
由于进程是程序执行时的一个实例,故除了程序指令之外,还包含了大量的资源,拥有独立的虚拟地址空间。为了更好的管理进程,内核必须清楚的了解每个进程当前的状态以及所做的事情。从而,就有了进程描述符这个概念。Linux中,使用task_struct结构来描述一个进程。
进程描述符都是task_struct类型结构,包含所有与进程相关的信息。
ubuntu系统代码位置(Linux version 4.15):/usr/src/linux-headers-4.15.0-72/include/linux/sched.h
linux在线代码位置:https://elixir.bootlin.com/linux/v5.5.2/source/include/linux/sched.h
由于task_struct结构体非常庞大复杂,这里主要列举主要结构:
struct task_struct {
//thread_info信息
/*
* For reasons of header soup (see current_thread_info()), this
* must be the first element of task_struct.
*/
struct thread_info thread_info;
//end
//进程运行状态
/* -1 unrunnable, 0 runnable, >0 stopped: */
volatile long state;
//end
//内核态堆栈
void *stack;
//end
//进程状态信息
/* Per task flags (PF_*), defined further below: */
unsigned int flags;
//end
//进程优先级信息
int prio;//动态优先级
int static_prio;//静态优先级,可用nice直接修改
int normal_prio;//静态优先级和调度策略
unsigned int rt_priority;//实时优先级
//end
//进程内存信息
struct mm_struct *mm;
struct mm_struct *active_mm;
/* Per-thread vma caching: */
struct vmacache vmacache;
#ifdef SPLIT_RSS_COUNTING
struct task_rss_stat rss_stat;
#endif
//end
//进程退出状态
int exit_state;
int exit_code;
int exit_signal;
/* The signal sent when the parent dies: */
int pdeath_signal;
//end
//原子访问标志
unsigned long atomic_flags; /* Flags requiring atomic access. */
//end
//进程标识符
pid_t pid;
pid_t tgid;
//end
//进程的亲属关系
/*
* Pointers to the (original) parent process, youngest child, younger sibling,
* older sibling, respectively. (p->father can be replaced with
* p->real_parent->pid)
*/
/* Real parent process: */
struct task_struct __rcu *real_parent; //真实的父进程
/* Recipient of SIGCHLD, wait4() reports: */
struct task_struct __rcu *parent; //形式上的父进程,一般都是real_parent。
/*
* Children/sibling form the list of natural children:
*/
struct list_head children;
struct list_head sibling;
struct task_struct *group_leader;
//end
//时间统计信息
u64 utime;
u64 stime;
#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME
u64 utimescaled;
u64 stimescaled;
#endif
u64 gtime;
struct prev_cputime prev_cputime;
#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
struct vtime vtime;
#endif
#ifdef CONFIG_NO_HZ_FULL
atomic_t tick_dep_mask;
#endif
/* Context switch counts: */
unsigned long nvcsw;
unsigned long nivcsw;
/* Monotonic time in nsecs: */
u64 start_time;
/* Boot based time in nsecs: */
u64 real_start_time;
/* MM fault and swap info: this can arguably be seen as either mm-specific or thread-specific: */
unsigned long min_flt;
unsigned long maj_flt;
#ifdef CONFIG_POSIX_TIMERS
struct task_cputime cputime_expires;
struct list_head cpu_timers[3];
#endif
//end
//进程名,最长15个字符
/*
* executable name, excluding path.
*
* - normally initialized setup_new_exec()
* - access it with [gs]et_task_comm()
* - lock it with task_lock()
*/
char comm[TASK_COMM_LEN];
//end
/* Filesystem information: */
struct fs_struct *fs;
/* Open file information: */
struct files_struct *files;
/* Namespaces: */
struct nsproxy *nsproxy;
/* Signal handlers: */
struct signal_struct *signal;
struct sighand_struct *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;
/* Protection against (de-)allocation: mm, files, fs, tty, keyrings, mems_allowed, mempolicy: */
spinlock_t alloc_lock;
/*
* WARNING: on x86, 'thread_struct' contains a variable-sized
* structure. It *MUST* be at the end of 'task_struct'.
*
* Do not put anything below here!
*/
};
thread_info
thread_info的定义在arch目录下,不同的架构有不同的thread_info。
以arm架构为例:arch/arm/include/asm/thread_info.h。其中的task属性就是指向task_struct。
thread_info保存了汇编代码段需要访问的那部分进程的数据,arm架构在thread_info中嵌入指向task_struct的指针, 则我们可以很方便的通过thread_info来查找task_struct。不同的体系架构拥有不同的thread_info。
/*
* low level task data that entry.S needs immediate access to.
* __switch_to() assumes cpu_context follows immediately after cpu_domain.
*/
struct thread_info {
unsigned long flags; /* low level flags */
int preempt_count; /* 0 => preemptable, <0 => bug */
mm_segment_t addr_limit; /* address limit */
struct task_struct *task; /* main task structure */
__u32 cpu; /* cpu */
__u32 cpu_domain; /* cpu domain */
#ifdef CONFIG_STACKPROTECTOR_PER_TASK
unsigned long stack_canary;
#endif
struct cpu_context_save cpu_context; /* cpu context */
__u32 syscall; /* syscall number */
__u8 used_cp[16];