Linux中的 进程概念、进程创建 和 GDB多进程调试 [Linux高并发服务器开发]

目录

一、进程的概念

1.进程的状态

2.进程控制块 PCB

3.查看进程

4.进程的信息中,STAT参数的意义:

5.top命令,实时显示进程动态:

6.杀死进程:

7.进程号获取:

二、创建进程

三、GDB 多进程调试

1.通过命令查看和更改默认调试进程:

2. 设置调试模式:

3.查看调试的进程:

4.切换当前调试的进程:

5.使进程脱离GDB调试:


一、进程的概念

在进程模型中,计算机上所有可运行的软件,通常包括操作系统,被组织成若干顺序进程(sequential  process),简称进程(process)。

进程是正在运行的程序的实例,是一个具有一定独立功能的程序关于某个数据结合的一次运行活动。 它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。 

进程 是由内核定义的抽象实体,并为该实体分配用以执行程序的各项系统资源。 从内核的角度看,进程由 用户内存空间 和一系列 内核数据结构 组成,其中用户内存空间包含了 程序代码及代码所使用的变量,而 内核数据结构则用于维护进程状态信息。(详细内容见 虚拟地址空间模型)   记录在内核数据中的信息 包括 进程的标识号(ID)虚拟内存表打开文件的描述符表信号传递及处理的有关信息进程资源使用及限制当前工作目录和大量的其他信息

进程 是 某种类型的一个活动,它有程序、输入、输出 以及 状态。 如果一个程序运行了两遍,则算作两个进程。  

单个处理器 可以被若干进程共享,它 使用某种调度算法  决定何时停止一个进程的工作,并转而为另一个进程提供服务。

多道程序设计技术是在计算机内存中同时存放几道相互独立的程序,使它们在管理程序控制下,相互穿插运行,两个或两个以上程序在计算机系统中同处于开始到结束之间的状态, 这些程序共享计算机系统资源。引入多道程序设计技术的根本目的是为了提高 CPU 的利用率。


时间片(timeslice)又称为“量子(quantum)”或“处理器片(processor slice)”是操作系统分配给每个正在运行的进程微观上的一段 CPU 时间事实上,虽然一台计算机通常可能有多个 CPU,但是同一个 CPU 永远不可能真正地同时运行多个任务。在只考虑一个 CPU 的情况下,这些进程“看起来像”同时运行的,实则是轮番穿插地运行,由于时间片通常很短(在 Linux 上为 5ms-800ms),用户不会感觉到。

时间片 由操作系统内核的 调度程序 分配给 每个进程。首先,内核会给每个进程分配相等的初始时间片,然后每个进程轮番地执行相应的时间,当所有进程都处于时间片耗尽的状态时,内核会重新为每个进程计算并分配时间片,如此往复。

1.进程的状态

进程有三种状态:  运行态、 就绪态、阻塞态

运行态: 进程占有处理器,正在运行

就绪态: 进程具备运行条件,等待系统分配处理器以便运行。 当进程已分配到除CPU以外的所有必要资源后,只要再获得CPU,便可立即执行。在一个系统中处于就绪状态的进程可能有多个,通常将它们排成一个队列,称为就绪队列。

阻塞态:又称为 等待(wait)态 或 睡眠(sleep)态,指进程不具备运行条件,正在等待某个事件的完成。
 

进程的三种状态之间 有四种转换关系:

转换1:进程因为等待输入而被阻塞。 在操作系统发现不能继续运行下去时,发生转换1。在某些系统中,进程可以执行pause的系统调用进入阻塞状态。Unix中,当一个进程从管道或设备文件(比如终端)读取数据时,如果没有有效的输入存在,则进程会被自动阻塞。

转换2:调度程序选择另一个进程 。 该转换由进程调度程序引起。系统认为一个运行进程占用处理器的时间已经过长,决定让其他进程使用CPU时间,会发生转换2。 

转换3:调度程序选择这个进程。由进程调度程序引起。在系统已经让所有其他进程享有了它们应有的公平待遇而重新轮到第一个进程再次占用CPU运行时,会发生转换3。

转换4:出现有效输入。 当进程等待的一个外部时间发生时,如一些输入到达,则发生转换4。

Linux中的 进程概念、进程创建 和 GDB多进程调试 [Linux高并发服务器开发]_第1张图片

操作系统的最底层是调度程序, 在它上面有许多进程。所有关于中断处理、启动进程 和 停止进程的具体细节都隐藏在调度程序中。

2.进程控制块 PCB

为了管理进程,内核为 每个进程分配一个 PCB(Processing Control Block)进程控制块,维护进程相关的信息,Linux 内核的进程控制块是 task_struct 结构体。

PCB表包含了进程状态的重要信息,包括:程序计数器、堆栈指针、内存分配状况、所打开文件的状态、账号和调度信息,以及其他在进程由运行态转换到就绪态或阻塞态时必须保存的信息,从而保证该进程随后能再次启动,就像从未被中断过一样

Linux系统文件,/usr/src/linux-headers-xxx/include/linux/sched.h 文件中可以查看 struct task_struct 结构体定义。主要有三个模块:

Linux中的 进程概念、进程创建 和 GDB多进程调试 [Linux高并发服务器开发]_第2张图片

 其内部成员有很多,我们只需要掌握以下部分即可。

⚫ 进程id: 系统中每个进程有唯一的 id,用 pid_t 类型表示,其实就是一个非负整数
⚫ 进程的状态: 有 就绪、运行、阻塞、停止等状态
⚫ 进程切换时需要保存和恢复的一些CPU寄存器
⚫ 描述虚拟地址空间的信息
⚫ 描述控制终端的信息
⚫ 当前工作目录(Current Working Directory)
⚫ umask 掩码
⚫ 文件描述符表, 包含很多指向 file 结构体的指针
⚫ 和 信号 相关的信息
⚫ 用户 id 和 组 id
⚫ 会话(Session)和 进程组
⚫ 进程可以使用的资源上限(Resource Limit)

struct task_struct {
#ifdef CONFIG_THREAD_INFO_IN_TASK
	/*
	 * For reasons of header soup (see current_thread_info()), this
	 * must be the first element of task_struct.
	 */
	struct thread_info		thread_info;
#endif
	/* -1 unrunnable, 0 runnable, >0 stopped: */
	volatile long			state;

	/*
	 * This begins the randomizable portion of task_struct. Only
	 * scheduling-critical items should be added above here.
	 */
	randomized_struct_fields_start

	void				*stack;
	refcount_t			usage;
	/* Per task flags (PF_*), defined further below: */
	unsigned int			flags;
	unsigned int			ptrace;

#ifdef CONFIG_SMP
	struct llist_node		wake_entry;
	int				on_cpu;
#ifdef CONFIG_THREAD_INFO_IN_TASK
	/* Current CPU: */
	unsigned int			cpu;
#endif
	unsigned int			wakee_flips;
	unsigned long			wakee_flip_decay_ts;
	struct task_struct		*last_wakee;

	/*
	 * recent_used_cpu is initially set as the last CPU used by a task
	 * that wakes affine another task. Waker/wakee relationships can
	 * push tasks around a CPU where each wakeup moves to the next one.
	 * Tracking a recently used CPU allows a quick search for a recently
	 * used CPU that may be idle.
	 */
	int				recent_used_cpu;
	int				wake_cpu;
#endif
	int				on_rq;

	int				prio;
	int				static_prio;
	int				normal_prio;
	unsigned int			rt_priority;

	const struct sched_class	*sched_class;
	struct sched_entity		se;
	struct sched_rt_entity		rt;
#ifdef CONFIG_CGROUP_SCHED
	struct task_group		*sched_task_group;
#endif
	struct sched_dl_entity		dl;

#ifdef CONFIG_UCLAMP_TASK
	/* Clamp values requested for a scheduling entity */
	struct uclamp_se		uclamp_req[UCLAMP_CNT];
	/* Effective clamp values used for a scheduling entity */
	struct uclamp_se		uclamp[UCLAMP_CNT];
#endif

#ifdef CONFIG_PREEMPT_NOTIFIERS
	/* List of struct preempt_notifier: */
	struct hlist_head		preempt_notifiers;
#endif

#ifdef CONFIG_BLK_DEV_IO_TRACE
	unsigned int			btrace_seq;
#endif

	unsigned int			policy;
	int				nr_cpus_allowed;
	const cpumask_t			*cpus_ptr;
	cpumask_t			cpus_mask;

#ifdef CONFIG_PREEMPT_RCU
	int				rcu_read_lock_nesting;
	union rcu_special		rcu_read_unlock_special;
	struct list_head		rcu_node_entry;
	struct rcu_node			*rcu_blocked_node;
#endif /* #ifdef CONFIG_PREEMPT_RCU */

#ifdef CONFIG_TASKS_RCU
	unsigned long			rcu_tasks_nvcsw;
	u8				rcu_tasks_holdout;
	u8				rcu_tasks_idx;
	int				rcu_tasks_idle_cpu;
	struct list_head		rcu_tasks_holdout_list;
#endif /* #ifdef CONFIG_TASKS_RCU */

	struct sched_info		sched_info;

	struct list_head		tasks;
#ifdef CONFIG_SMP
	struct plist_node		pushable_tasks;
	struct rb_node			pushable_dl_tasks;
#endif

	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
	int				exit_state;
	int				exit_code;
	int				exit_signal;
	/* The signal sent when the parent dies: */
	int				pdeath_signal;
	/* JOBCTL_*, siglock protected: */
	unsigned long			jobctl;

	/* Used for emulating ABI behavior of previous Linux versions: */
	unsigned int			personality;

	/* Scheduler bits, serialized by scheduler locks: */
	unsigned			sched_reset_on_fork:1;
	unsigned			sched_contributes_to_load:1;
	unsigned			sched_migrated:1;
	unsigned			sched_remote_wakeup:1;
#ifdef CONFIG_PSI
	unsigned			sched_psi_wake_requeue:1;
#endif

	/* Force alignment to the next boundary: */
	unsigned			:0;

	/* Unserialized, strictly 'current' */

	/* Bit to tell LSMs we're in execve(): */
	unsigned			in_execve:1;
	unsigned			in_iowait:1;
#ifndef TIF_RESTORE_SIGMASK
	unsigned			restore_sigmask:1;
#endif
#ifdef CONFIG_MEMCG
	unsigned			in_user_fault:1;
#endif
#ifdef CONFIG_COMPAT_BRK
	unsigned			brk_randomized:1;
#endif
#ifdef CONFIG_CGROUPS
	/* disallow userland-initiated cgroup migration */
	unsigned			no_cgroup_migration:1;
	/* task is frozen/stopped (used by the cgroup freezer) */
	unsigned			frozen:1;
#endif
#ifdef CONFIG_BLK_CGROUP
	/* to be used once the psi infrastructure lands upstream. */
	unsigned			use_memdelay:1;
#endif

	unsigned long			atomic_flags; /* Flags requiring atomic access. */

	struct restart_block		restart_block;

	pid_t				pid;
	pid_t				tgid;

#ifdef CONFIG_STACKPROTECTOR
	/* Canary value for the -fstack-protector GCC feature: */
	unsigned long			stack_canary;
#endif
	/*
	 * 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;

	/*
	 * 'ptraced' is the list of tasks this task is using ptrace() on.
	 *
	 * This includes both natural children and PTRACE_ATTACH targets.
	 * 'ptrace_entry' is this task's link on the p->parent->ptraced list.
	 */
	struct list_head		ptraced;
	struct list_head		ptrace_entry;

	/* PID/PID hash table linkage. */
	struct pid			*thread_pid;
	struct hlist_node		pid_links[PIDTYPE_MAX];
	struct list_head		thread_group;
	struct list_head		thread_node;

	struct completion		*vfork_done;

	/* CLONE_CHILD_SETTID: */
	int __user			*set_child_tid;

	/* CLONE_CHILD_CLEARTID: */
	int __user			*clear_child_tid;

	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;

	/* Empty if CONFIG_POSIX_CPUTIMERS=n */
	struct posix_cputimers		posix_cputimers;

	/* Process credentials: */

	/* Tracer's credentials at attach: */
	const struct cred __rcu		*ptracer_cred;

	/* Objective and real subjective task credentials (COW): */
	const struct cred __rcu		*real_cred;

	/* Effective (overridable) subjective task credentials (COW): */
	const struct cred __rcu		*cred;

#ifdef CONFIG_KEYS
	/* Cached requested key. */
	struct key			*cached_requested_key;
#endif

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

	struct nameidata		*nameidata;

#ifdef CONFIG_SYSVIPC
	struct sysv_sem			sysvsem;
	struct sysv_shm			sysvshm;
#endif
#ifdef CONFIG_DETECT_HUNG_TASK
	unsigned long			last_switch_count;
	unsigned long			last_switch_time;
#endif
	/* 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;

	struct callback_head		*task_works;

#ifdef CONFIG_AUDIT
#ifdef CONFIG_AUDITSYSCALL
	struct audit_context		*audit_context;
#endif
	kuid_t				loginuid;
	unsigned int			sessionid;
#endif
	struct seccomp			seccomp;

	/* Thread group tracking: */
	u64				parent_exec_id;
	u64				self_exec_id;

	/* Protection against (de-)allocation: mm, files, fs, tty, keyrings, mems_allowed, mempolicy: */
	spinlock_t			alloc_lock;

	/* Protection of the PI data structures: */
	raw_spinlock_t			pi_lock;

	struct wake_q_node		wake_q;

#ifdef CONFIG_RT_MUTEXES
	/* PI waiters blocked on a rt_mutex held by this task: */
	struct rb_root_cached		pi_waiters;
	/* Updated under owner's pi_lock and rq lock */
	struct task_struct		*pi_top_task;
	/* Deadlock detection and priority inheritance handling: */
	struct rt_mutex_waiter		*pi_blocked_on;
#endif

#ifdef CONFIG_DEBUG_MUTEXES
	/* Mutex deadlock detection: */
	struct mutex_waiter		*blocked_on;
#endif

#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
	int				non_block_count;
#endif

#ifdef CONFIG_TRACE_IRQFLAGS
	unsigned int			irq_events;
	unsigned long			hardirq_enable_ip;
	unsigned long			hardirq_disable_ip;
	unsigned int			hardirq_enable_event;
	unsigned int			hardirq_disable_event;
	int				hardirqs_enabled;
	int				hardirq_context;
	unsigned long			softirq_disable_ip;
	unsigned long			softirq_enable_ip;
	unsigned int			softirq_disable_event;
	unsigned int			softirq_enable_event;
	int				softirqs_enabled;
	int				softirq_context;
#endif

#ifdef CONFIG_LOCKDEP
# define MAX_LOCK_DEPTH			48UL
	u64				curr_chain_key;
	int				lockdep_depth;
	unsigned int			lockdep_recursion;
	struct held_lock		held_locks[MAX_LOCK_DEPTH];
#endif

#ifdef CONFIG_UBSAN
	unsigned int			in_ubsan;
#endif

	/* Journalling filesystem info: */
	void				*journal_info;

	/* Stacked block device info: */
	struct bio_list			*bio_list;

#ifdef CONFIG_BLOCK
	/* Stack plugging: */
	struct blk_plug			*plug;
#endif

	/* VM state: */
	struct reclaim_state		*reclaim_state;

	struct backing_dev_info		*backing_dev_info;

	struct io_context		*io_context;

#ifdef CONFIG_COMPACTION
	struct capture_control		*capture_control;
#endif
	/* Ptrace state: */
	unsigned long			ptrace_message;
	kernel_siginfo_t		*last_siginfo;

	struct task_io_accounting	ioac;
#ifdef CONFIG_PSI
	/* Pressure stall state */
	unsigned int			psi_flags;
#endif
#ifdef CONFIG_TASK_XACCT
	/* Accumulated RSS usage: */
	u64				acct_rss_mem1;
	/* Accumulated virtual memory usage: */
	u64				acct_vm_mem1;
	/* stime + utime since last update: */
	u64				acct_timexpd;
#endif
#ifdef CONFIG_CPUSETS
	/* Protected by ->alloc_lock: */
	nodemask_t			mems_allowed;
	/* Seqence number to catch updates: */
	seqcount_t			mems_allowed_seq;
	int				cpuset_mem_spread_rotor;
	int				cpuset_slab_spread_rotor;
#endif
#ifdef CONFIG_CGROUPS
	/* Control Group info protected by css_set_lock: */
	struct css_set __rcu		*cgroups;
	/* cg_list protected by css_set_lock and tsk->alloc_lock: */
	struct list_head		cg_list;
#endif
#ifdef CONFIG_X86_CPU_RESCTRL
	u32				closid;
	u32				rmid;
#endif
#ifdef CONFIG_FUTEX
	struct robust_list_head __user	*robust_list;
#ifdef CONFIG_COMPAT
	struct compat_robust_list_head __user *compat_robust_list;
#endif
	struct list_head		pi_state_list;
	struct futex_pi_state		*pi_state_cache;
	struct mutex			futex_exit_mutex;
	unsigned int			futex_state;
#endif
#ifdef CONFIG_PERF_EVENTS
	struct perf_event_context	*perf_event_ctxp[perf_nr_task_contexts];
	struct mutex			perf_event_mutex;
	struct list_head		perf_event_list;
#endif
#ifdef CONFIG_DEBUG_PREEMPT
	unsigned long			preempt_disable_ip;
#endif
#ifdef CONFIG_NUMA
	/* Protected by alloc_lock: */
	struct mempolicy		*mempolicy;
	short				il_prev;
	short				pref_node_fork;
#endif
#ifdef CONFIG_NUMA_BALANCING
	int				numa_scan_seq;
	unsigned int			numa_scan_period;
	unsigned int			numa_scan_period_max;
	int				numa_preferred_nid;
	unsigned long			numa_migrate_retry;
	/* Migration stamp: */
	u64				node_stamp;
	u64				last_task_numa_placement;
	u64				last_sum_exec_runtime;
	struct callback_head		numa_work;

	/*
	 * This pointer is only modified for current in syscall and
	 * pagefault context (and for tasks being destroyed), so it can be read
	 * from any of the following contexts:
	 *  - RCU read-side critical section
	 *  - current->numa_group from everywhere
	 *  - task's runqueue locked, task not running
	 */
	struct numa_group __rcu		*numa_group;

	/*
	 * numa_faults is an array split into four regions:
	 * faults_memory, faults_cpu, faults_memory_buffer, faults_cpu_buffer
	 * in this precise order.
	 *
	 * faults_memory: Exponential decaying average of faults on a per-node
	 * basis. Scheduling placement decisions are made based on these
	 * counts. The values remain static for the duration of a PTE scan.
	 * faults_cpu: Track the nodes the process was running on when a NUMA
	 * hinting fault was incurred.
	 * faults_memory_buffer and faults_cpu_buffer: Record faults per node
	 * during the current scan window. When the scan completes, the counts
	 * in faults_memory and faults_cpu decay and these values are copied.
	 */
	unsigned long			*numa_faults;
	unsigned long			total_numa_faults;

	/*
	 * numa_faults_locality tracks if faults recorded during the last
	 * scan window were remote/local or failed to migrate. The task scan
	 * period is adapted based on the locality of the faults with different
	 * weights depending on whether they were shared or private faults
	 */
	unsigned long			numa_faults_locality[3];

	unsigned long			numa_pages_migrated;
#endif /* CONFIG_NUMA_BALANCING */

#ifdef CONFIG_RSEQ
	struct rseq __user *rseq;
	u32 rseq_sig;
	/*
	 * RmW on rseq_event_mask must be performed atomically
	 * with respect to preemption.
	 */
	unsigned long rseq_event_mask;
#endif

	struct tlbflush_unmap_batch	tlb_ubc;

	union {
		refcount_t		rcu_users;
		struct rcu_head		rcu;
	};

	/* Cache last used pipe for splice(): */
	struct pipe_inode_info		*splice_pipe;

	struct page_frag		task_frag;

#ifdef CONFIG_TASK_DELAY_ACCT
	struct task_delay_info		*delays;
#endif

#ifdef CONFIG_FAULT_INJECTION
	int				make_it_fail;
	unsigned int			fail_nth;
#endif
	/*
	 * When (nr_dirtied >= nr_dirtied_pause), it's time to call
	 * balance_dirty_pages() for a dirty throttling pause:
	 */
	int				nr_dirtied;
	int				nr_dirtied_pause;
	/* Start of a write-and-pause period: */
	unsigned long			dirty_paused_when;

#ifdef CONFIG_LATENCYTOP
	int				latency_record_count;
	struct latency_record		latency_record[LT_SAVECOUNT];
#endif
	/*
	 * Time slack values; these are used to round up poll() and
	 * select() etc timeout values. These are in nanoseconds.
	 */
	u64				timer_slack_ns;
	u64				default_timer_slack_ns;

#ifdef CONFIG_KASAN
	unsigned int			kasan_depth;
#endif

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
	/* Index of current stored address in ret_stack: */
	int				curr_ret_stack;
	int				curr_ret_depth;

	/* Stack of return addresses for return function tracing: */
	struct ftrace_ret_stack		*ret_stack;

	/* Timestamp for last schedule: */
	unsigned long long		ftrace_timestamp;

	/*
	 * Number of functions that haven't been traced
	 * because of depth overrun:
	 */
	atomic_t			trace_overrun;

	/* Pause tracing: */
	atomic_t			tracing_graph_pause;
#endif

#ifdef CONFIG_TRACING
	/* State flags for use by tracers: */
	unsigned long			trace;

	/* Bitmask and counter of trace recursion: */
	unsigned long			trace_recursion;
#endif /* CONFIG_TRACING */

#ifdef CONFIG_KCOV
	/* Coverage collection mode enabled for this task (0 if disabled): */
	unsigned int			kcov_mode;

	/* Size of the kcov_area: */
	unsigned int			kcov_size;

	/* Buffer for coverage collection: */
	void				*kcov_area;

	/* KCOV descriptor wired with this task or NULL: */
	struct kcov			*kcov;
#endif

#ifdef CONFIG_MEMCG
	struct mem_cgroup		*memcg_in_oom;
	gfp_t				memcg_oom_gfp_mask;
	int				memcg_oom_order;

	/* Number of pages to reclaim on returning to userland: */
	unsigned int			memcg_nr_pages_over_high;

	/* Used by memcontrol for targeted memcg charge: */
	struct mem_cgroup		*active_memcg;
#endif

#ifdef CONFIG_BLK_CGROUP
	struct request_queue		*throttle_queue;
#endif

#ifdef CONFIG_UPROBES
	struct uprobe_task		*utask;
#endif
#if defined(CONFIG_BCACHE) || defined(CONFIG_BCACHE_MODULE)
	unsigned int			sequential_io;
	unsigned int			sequential_io_avg;
#endif
#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
	unsigned long			task_state_change;
#endif
	int				pagefault_disabled;
#ifdef CONFIG_MMU
	struct task_struct		*oom_reaper_list;
#endif
#ifdef CONFIG_VMAP_STACK
	struct vm_struct		*stack_vm_area;
#endif
#ifdef CONFIG_THREAD_INFO_IN_TASK
	/* A live task holds one reference: */
	refcount_t			stack_refcount;
#endif
#ifdef CONFIG_LIVEPATCH
	int patch_state;
#endif
#ifdef CONFIG_SECURITY
	/* Used by LSM modules for access restriction: */
	void				*security;
#endif

#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
	unsigned long			lowest_stack;
	unsigned long			prev_lowest_stack;
#endif

	/*
	 * New fields for task_struct should be added above here, so that
	 * they are included in the randomized portion of task_struct.
	 */
	randomized_struct_fields_end

	/* CPU-specific state of this task: */
	struct thread_struct		thread;

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

3.查看进程

ps  aux / ajx
a:显示终端上的所有进程,包括其他用户的进程
u:显示进程的详细信息
x:显示没有控制终端的进程
j: 列出与作业控制相关的信息

Linux中的 进程概念、进程创建 和 GDB多进程调试 [Linux高并发服务器开发]_第3张图片

 4.进程的信息中,STAT参数的意义:

可以使用  man  ps ,查看ps的帮助文档,来确定每一项显示的信息的含义。

PROCESS STATE CODES
       Here are the different values that the s, stat and state output specifiers (header "STAT" or "S") will display to
       describe the state of a process:

               D    uninterruptible sleep (usually IO)
               R    running or runnable (on run queue)
               S    interruptible sleep (waiting for an event to complete)
               T    stopped by job control signal
               t    stopped by debugger during the tracing
               W    paging (not valid since the 2.6.xx kernel)
               X    dead (should never be seen)
               Z    defunct ("zombie") process, terminated but not reaped by its parent

       For BSD formats and when the stat keyword is used, additional characters may be displayed:

               <    high-priority (not nice to other users)
               N    low-priority (nice to other users)
               L    has pages locked into memory (for real-time and custom IO)
               s    is a session leader
               l    is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
               +    is in the foreground process group

D

R
S(大写)
T

t

W

X

Z

不可中断 Uninterruptible(usually IO)

正在运行 或 就绪进程(在运行队列中)
处于休眠状态(等待一个事件去结束它)
停止,被调度停止

在跟踪期间被调试器停止

进入内存交换(从内核2.6开始无效)

死掉的进程

僵尸进程,已终止,但不能被父进程回收/释放资源

<
N

L
s

l
+

高优先级
低优先级

页面锁定到内存(实时的且与客户进行IO的)
包含子进程

l 多进程的(使用 CLONE_THREAD, 类似 NPTL pthreads)
位于前台的进程组

5.top命令,实时显示进程动态:

可以在使用 top 命令时加上 -d 来指定显示信息更新的时间间隔,在 top 命令
执行后,可以按以下按键对显示的结果进行排序
M   根据 内存使用量排序
P   根据  CPU 占有率排序
T   根据进程 运行时间长短排序
U   根据 用户名来筛选进程
 输入指定的 PID 杀死进程

6.杀死进程:

kill [-signal] pid
kill –l   ;列出所有信号
kill –SIGKILL [进程ID]
kill -9 [进程ID]
killall name ; 根据进程名杀死进程

7.进程号获取:

每个进程都由进程号来标识,其类型为 pid_t(整型),进程号的范围: 0~ 32767进程号总是唯一的,但可以重用。当一个进程终止后,其进程号就可以再次使用。

任何进程(除 init 进程)都是由另一个进程创建,该进程称为被创建进程的父进程,对应的进程号称为父进程号PPID)。
 

进程组 是一个或多个进程 的集合。 他们之间相互关联,进程组可以接收同一终端的各种信号,关联的进程有一个进程组号(PGID)。默认情况下,当前的进程号会当做当前的进程组号。

进程号和进程组相关函数:

pid_t    getpid (void);
pid_t    getppid (void);
pid_t    getpgid (pid_t pid);

二、创建进程

        Unix系统中只有一个系统调用可以用来 创建新进程fork。 这个系统调用会创建一个与调用进程相同的副本。 在调用了fork后,这两个 父进程 和 子进程 拥有相同的内存映像,相同的代码段,相同的堆栈等。   通常,子进程接着执行execve或一个类似的系统调用,以修改内存映像并运行一个新的程序。

        Unix系统允许一个进程创建新进程, 新进程 即为 子进程,子进程还可以创建新的子进程,形成进程树结构模型。

      pid_t fork(void);

函数的作用:

        用于创建子进程

返回值:

        fork()的返回值会返回两次。 一次是在父进程中,一次是在子进程中。

        在父进程中返回创建的子进程的ID,

        在子进程中返回0

        如何区分 父进程和子进程:通过 fork的返回值

        在父进程中返回-1,表示创建子进程失败,并且设置error no

        失败的两个主要原因:
        1. 当前系统的进程数已经达到了系统规定的上限,这时 errno 的值被设置为 EAGAIN
        2. 系统内存不足,这时 errno 的值被设置为 ENOMEM

父子进程之间的关系:

区别:

        1.fork()函数的返回值不同

            父进程中:>0 返回的子进程的ID

            子进程中:=0

        2.pcb中的数据:

            当前进程的id , pid 不同

            当前的进程的父进程的id  ppid

            信号集

 共同点:

        某些状态下:子进程刚被创建出来,还没有执行任何的写数据的操作

        - 用户区的数据

        - 文件描述符表

父子进程对变量是不是共享的?

     - 刚开始的时候,是共享的。 如果修改了数据,不共享了。

     - 读时共享(子进程被创建,两个进程没有做任何写的操作),写时拷贝

因此进程通信的时候,不能使用变量进行共享,来实现通信。

代码示例:

#include 
#include 
#include 

int main()
{
    
    //创建子进程
    pid_t pid = fork();

    //判断是父进程还是子进程
    if(pid>0)
    {
        printf("pid:%d\n",pid);
        //如果大于0 ,返回的是创建的子进程的进程号
        printf("I am parent process,pid:%d,ppid:%d\n",getpid(),getppid());
    }
    else if(pid == 0)
    {
        //当前是子进程
        printf("I am child process, pid:%d ppid:%d\n",getpid(),getppid());
    }

    //父子进程都会执行
    for(int i =0 ;i<3;++i)
    {
        printf("i:%d ,pid:%d\n",i,getpid());
        sleep(1);
    }

    return 0;
}

执行的结果是:

Linux中的 进程概念、进程创建 和 GDB多进程调试 [Linux高并发服务器开发]_第4张图片

 每次执行的结果不一样,是因为调度切换的问题。

使用fork函数,创建子进程的虚拟地址空间模型如下:

Linux中的 进程概念、进程创建 和 GDB多进程调试 [Linux高并发服务器开发]_第5张图片

在子进程没有对 进程中的变量进行写操作的时候,就是说只读变量的话,父子进程是共享的。 当改变变量值的时候,进行写时拷贝。

三、GDB 多进程调试

样例程序如下:

#include
#include

int main()
{
    printf("begin \n");

    if(fork()!=0)
    {
        printf("我是父进程:pid =%d, ppid=%d\n",getpid(),getppid());

        int i;
        for(i =0;i<10;++i)
        {
            printf("i = %d \n",i);
            sleep(1);
        }
    }
    else 
    {
        printf("我是子进程:pid =%d, ppid=%d\n",getpid(),getppid());

        int j;
        for(j =0;j<10;++j)
        {
            printf("j = %d \n",j);
            sleep(1);
        }
    }

    return 0;
}

对程序进行编译:

Linux中的 进程概念、进程创建 和 GDB多进程调试 [Linux高并发服务器开发]_第6张图片

 在第10行 和 第20行,打上断点:

Linux中的 进程概念、进程创建 和 GDB多进程调试 [Linux高并发服务器开发]_第7张图片

 执行进程,GDB默认 调试父进程

Linux中的 进程概念、进程创建 和 GDB多进程调试 [Linux高并发服务器开发]_第8张图片

 1.通过命令查看和更改默认调试进程:

show  follow-fork-mode  ;查看默认的调试进程

set  follow-fork-mode  child ;更改默认调试进程是 子进程

Linux中的 进程概念、进程创建 和 GDB多进程调试 [Linux高并发服务器开发]_第9张图片

2. 设置调试模式:

set  detach-on-fork  [on | off ]

默认为 on,表示调试当前进程的时候,其他的进程继续运行; 如果为 off,调试当前进程的时候,其他进程被 GDB 挂起。

比如,默认的detach-on-fork 为 on的时候,父子进程都执行。更改为 off之后,只执行父进程,子进程被挂起。

Linux中的 进程概念、进程创建 和 GDB多进程调试 [Linux高并发服务器开发]_第10张图片

3.查看调试的进程:

info  inferiors

4.切换当前调试的进程:

inferior  [id]

Linux中的 进程概念、进程创建 和 GDB多进程调试 [Linux高并发服务器开发]_第11张图片

 5.使进程脱离GDB调试:

detach  inferiors  [id]

继续坚持,加油,冲冲冲~

Linux中的 进程概念、进程创建 和 GDB多进程调试 [Linux高并发服务器开发]_第12张图片

你可能感兴趣的:(Linux高并发服务器开发,服务器,linux,后端)