The Process of Mingo linux Kernel

Keywords: Linux less Ubuntu

process

Processes are also called tasks in linux.

For user space, a process is an instance of program execution.A process can be compared to a human individual: there is only one parent process and there can be multiple child processes; there are more or less valid lives; it takes on certain functions or tasks; it has different states, and there is only one state at any time; and it will eventually die out.

For the kernel space, the purpose of the process is to reasonably allocate the entities of the system resources.Each process will use the kernel to get its own CPU, memory, and other system resources to perform tasks.

1. Process Descriptor

Since a process is an instance of a program execution, in addition to program instructions, it contains a large number of resources and has a separate virtual address space.In order to better manage processes, the kernel must have a clear understanding of each process's current state and what it does.Thus, there is the concept of a process descriptor.In Linux, a process is described using the task_struct structure.

Process descriptors are task_struct type structures that contain all process-related information.

ubuntu system code location (Linux version 4.15): /usr/src/linux-headers-4.15.0-72/include/linux/sched.h

linux online code location: https://elixir.bootlin.com/linux/v5.5.2/source/include/linux/sched.h

Since the task_struct structure is very large and complex, the main structures are listed here:

struct task_struct {
        //Process Running State
	/* -1 unrunnable, 0 runnable, >0 stopped: */
	volatile long			state;
        //end

        //Kernel State Stack
	void				*stack;
        //end

        //Process Status Information
	/* Per task flags (PF_*), defined further below: */
	unsigned int			flags;
        //end

        //Process priority information
	int				prio;//Dynamic Priority
	int				static_prio;//Static priority, can be modified directly with nice
	int				normal_prio;//Static Priority and Scheduling Policy
	unsigned int			rt_priority;//Real-time priority
        //end

        //Process memory information
	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

        //Process Exit Status
	int				exit_state;
	int				exit_code;
	int				exit_signal;
	/* The signal sent when the parent dies: */
	int				pdeath_signal;
        //end

        //Atomic Access Marker
	unsigned long			atomic_flags; /* Flags requiring atomic access. */
        //end

        //Process Identifier
	pid_t				pid;
	pid_t				tgid;
        //end

        //The relatives of a process
	/*
	 * 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; //Real parent process
	/* Recipient of SIGCHLD, wait4() reports: */
	struct task_struct __rcu	*parent; //Formally, the parent process is usually real_parent.

	/*
	 * Children/sibling form the list of natural children:
	 */
	struct list_head		children;
	struct list_head		sibling;
	struct task_struct		*group_leader;
        //end

        //Time Statistics
	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

        //Process name, up to 15 characters
	/*
	 * 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!
	 */
};

Process name

/* Task command name length: */
#define TASK_COMM_LEN			16

/*
 * 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];

comm is the process name and is no longer than 15 characters in length.

Process Running State

/* -1 unrunnable, 0 runnable, >0 stopped: */
volatile long state;
/*
 * Task state bitmask. NOTE! These bits are also
 * encoded in fs/proc/array.c: get_task_state().
 *
 * We have two separate sets of flags: task->state
 * is about runnability, while task->exit_state are
 * about the task exiting. Confusing, but this way
 * modifying one set can't modify the other one by
 * mistake.
 */
#define TASK_RUNNING 0x0000 //Runnable state, either running or ready to run
#define TASK_INTERRUPTIBLE 0x0001 //Interruptible wait state
#define TASK_UNINTERRUPTIBLE 0x0002 //Uninterruptible wait state
#Define u TASK_STOPPED 0x0004 //pause state
#Define u TASK_TRACED 0x0008 //Tracking status
/* in tsk->exit_state */
#define EXIT_DEAD 0x0010 //Process Death Status
#define EXIT_ZOMBIE 0x0020//Process Dead State
#define EXIT_TRACE		(EXIT_ZOMBIE | EXIT_DEAD)
/* in tsk->state again */
#define TASK_DEAD 0x0040 // Abnormal death during process death -->EXIT_ZOMBIE; Normal death -->EXIT_DEAD
#define TASK_WAKEKILL 0x0080 //Process to wake up and kill
#define TASK_WAKING 0x0100 //Wake-up process
#define TASK_PARKED		0x0200 //
#define TASK_NOLOAD		0x0400
#define TASK_NEW		0x0800
#define TASK_STATE_MAX		0x1000

Process Identifier

//Process Identifier
pid_t				pid;
pid_t				tgid;

Is the easy-to-understand pid and tgid.

PID is the process id, fork creates a unique pid.

TGID is the thread group id, and all processes in the same thread group have the same TGID; the TGID of the thread group leader is the same as its PID; and if a process does not use a thread, its TGID and PID are the same.

Process Kinship

/*
 * 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;

/*
 * Children/sibling form the list of natural children:
 */
struct list_head		children;
struct list_head		sibling;
struct task_struct		*group_leader;

Where real_parent is a pointer to the parent process and is the fork's own process; parent is the formal parent process and is the trace's own process.Typically, parent is real_parent.Upon exit, report wait4() to parent.

 

Seven original articles published. Praise 5. Visits 2761
Private letter follow

Posted by parthatel on Mon, 10 Feb 2020 21:10:26 -0800