小明哥学linux内核之进程(一)

这篇博客详细介绍了Linux中的进程概念,包括进程描述符(thread_info、进程名、运行状态、标识符、亲属关系及内存空间)、进程的建立(_do_fork工作流程、0号进程的建立)、进程切换的原理以及进程调试技巧。内容涵盖从用户空间到内核空间的进程理解,解析了task_struct结构、进程间的父子关系以及内核线程的内存管理。
摘要由CSDN通过智能技术生成

目录

进程

1. 进程描述符

thread_info

进程名

进程运行状态

进程标识符

进程亲属关系

进程的内存空间

2. 进程的建立

_do_fork工作流程

0号进程的建立

3. 进程切换

4. 进程调试技巧

参考文献


进程

进程在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];	
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值