目錄
一、行程的概念
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,

作業系統的最底層是調度程式, 在它上面有許多行程,所有關于中斷處理、啟動行程 和 停止行程的具體細節都隱藏在調度程式中,
2.行程控制塊 PCB
為了管理行程,內核為 每個行程分配一個 PCB(Processing Control Block)行程控制塊,維護行程相關的資訊,Linux 內核的行程控制塊是 task_struct 結構體,
PCB表中 包含了行程狀態的重要資訊,包括:程式計數器、堆疊指標、記憶體分配狀況、所打開檔案的狀態、賬號和調度資訊,以及其他在行程由運行態轉換到就緒態或阻塞態時必須保存的資訊,從而保證該行程隨后能再次啟動,就像從未被中斷過一樣,
Linux系統檔案,/usr/src/linux-headers-xxx/include/linux/sched.h 檔案中可以查看 struct task_struct 結構體定義,主要有三個模塊:

其內部成員有很多,我們只需要掌握以下部分即可,
? 行程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: 列出與作業控制相關的資訊

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 parentFor 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 t W X Z | 不可中斷 Uninterruptible(usually IO) 正在運行 或 就緒行程(在運行佇列中) 在跟蹤期間被除錯器停止 進入記憶體交換(從內核2.6開始無效) 死掉的行程 僵尸行程,已終止,但不能被父行程回收/釋放資源 |
| < L l | 高優先級 頁面鎖定到記憶體(實時的且與客戶進行IO的) l 多行程的(使用 CLONE_THREAD, 類似 NPTL pthreads) |
5.top命令,實時顯示行程動態:
可以在使用 top 命令時加上 -d 來指定顯示資訊更新的時間間隔,在 top 命令
執行后,可以按以下按鍵對顯示的結果進行排序:
? M 根據 記憶體使用量排序
? P 根據 CPU 占有率排序
? T 根據行程 運行時間長短排序
? U 根據 用戶名來篩選行程
? K 輸入指定的 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 <sys/types.h>
#include <unistd.h>
#include <stdio.h>
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;
}
執行的結果是:

每次執行的結果不一樣,是因為調度切換的問題,
使用fork函式,創建子行程的虛擬地址空間模型如下:

在子行程沒有對 行程中的變數進行寫操作的時候,就是說只讀變數的話,父子行程是共享的, 當改變變數值的時候,進行寫時拷貝,
三、GDB 多行程除錯
樣例程式如下:
#include<stdio.h>
#include<unistd.h>
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;
}
對程式進行編譯:

在第10行 和 第20行,打上斷點:

執行行程,GDB默認 除錯父行程:

1.通過命令查看和更改默認除錯行程:
show follow-fork-mode ;查看默認的除錯行程
set follow-fork-mode child ;更改默認除錯行程是 子行程

2. 設定除錯模式:
set detach-on-fork [on | off ]
默認為 on,表示除錯當前行程的時候,其他的行程繼續運行; 如果為 off,除錯當前行程的時候,其他行程被 GDB 掛起,
比如,默認的detach-on-fork 為 on的時候,父子行程都執行,更改為 off之后,只執行父行程,子行程被掛起,

3.查看除錯的行程:
info inferiors
4.切換當前除錯的行程:
inferior [id]

5.使行程脫離GDB除錯:
detach inferiors [id]
繼續堅持,加油,沖沖沖~

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/395321.html
標籤:其他
上一篇:R語言tidyquant包的tq_transmute函式計算持有某只股票的天、月、周收益率、ggplot2使用條形圖(bar plot)可視化股票月收益率資料條形圖
