基於Linux的源代碼
摘要:
本文為基於Linux 2.6.11源代碼進行的有關進程部分的簡單解析。
一、Linux下的進程
1.進程的定義
在進程模型中,計算機上所有可運行的軟件,通常也包括操作系統,被組織成若幹順序進程(sequential process),簡稱進程(process)。操作系統中最核心的概念是進程, 進程也是並發程序設計中的一個最重要、 最基本的概念。進程是一個動態的過程, 即進程有生命周期, 它擁有資源, 是程序的執行過程, 其狀態是變化的。
2.為什麽要引入進程
1.理論角度看,是對正在運行的程序過程的抽象; 2..實現角度看,是一種數據結構,目的在於清晰地刻畫動態系統的內在規律,有效管理和調度進入計算機系統主存儲器運行的程序。
一個計算機系統進程包括(或者說“擁有”)下列數據: 那個程序的可運行機器碼的一個在存儲器的映像。 分配到的存儲器(通常包括虛擬內存的一個區域)。存儲器的內容包括可運行代碼、特定於進程的數據(輸入、輸出)、調用堆棧、堆棧(用於保存運行時運數中途產生的數據)。 分配給該進程的資源的操作系統描述符,諸如文件描述符(Unix術語)或文件句柄(Windows)、數據源和數據終端。 安全特性,諸如進程擁有者和進程的權限集(可以容許的操作)。 處理器狀態(內文),諸如寄存器內容、物理存儲器尋址等。當進程正在運行時,狀態通常儲存在寄存器,其他情況在存儲器。
二、組織進程 1.
struct task_struct { volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ struct thread_info *thread_info; atomic_t usage; unsigned long flags; /* per process flags, defined below */ unsigned long ptrace; int lock_depth; /* Lock depth*/ int prio, static_prio; struct list_head run_list; prio_array_t *array; unsigned long sleep_avg; unsigned long long timestamp, last_ran; int activated; unsigned long policy; cpumask_t cpus_allowed; unsigned int time_slice, first_time_slice; #ifdef CONFIG_SCHEDSTATS struct sched_info sched_info; #endif struct list_head tasks; /* * ptrace_list/ptrace_children forms the list of my children * that were stolen by a ptracer. */ struct list_head ptrace_children; struct list_head ptrace_list; struct mm_struct *mm, *active_mm; /* task state */ struct linux_binfmt *binfmt; long exit_state; int exit_code, exit_signal; int pdeath_signal; /* The signal sent when the parent dies */ /* ??? */ unsigned long personality; unsigned did_exec:1; pid_t pid; pid_t tgid; /* * pointers to (original) parent process, youngest child, younger sibling, * older sibling, respectively. (p->father can be replaced with * p->parent->pid) */ struct task_struct *real_parent; /* real parent process (when being debugged) */ struct task_struct *parent; /* parent process */ /* * children/sibling forms the list of my children plus the * tasks I‘m ptracing. */ struct list_head children; /* list of my children */ struct list_head sibling; /* linkage in my parent‘s children list */ struct task_struct *group_leader; /* threadgroup leader */ /* PID/PID hash table linkage. */ struct pid pids[PIDTYPE_MAX]; struct completion *vfork_done; /* for vfork() */ int __user *set_child_tid; /* CLONE_CHILD_SETTID */ int __user *clear_child_tid; /* CLONE_CHILD_CLEARTID */ unsigned long rt_priority; unsigned long it_real_value, it_real_incr; cputime_t it_virt_value, it_virt_incr; cputime_t it_prof_value, it_prof_incr; struct timer_list real_timer; cputime_t utime, stime; unsigned long nvcsw, nivcsw; /* context switch counts */ struct timespec start_time; /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */ unsigned long min_flt, maj_flt; /* process credentials */ uid_t uid,euid,suid,fsuid; gid_t gid,egid,sgid,fsgid; struct group_info *group_info; kernel_cap_t cap_effective, cap_inheritable, cap_permitted; unsigned keep_capabilities:1; struct user_struct *user; #ifdef CONFIG_KEYS struct key *session_keyring; /* keyring inherited over fork */ struct key *process_keyring; /* keyring private to this process (CLONE_THREAD) */ struct key *thread_keyring; /* keyring private to this thread */ #endif int oomkilladj; /* OOM kill score adjustment (bit shift). */ char comm[TASK_COMM_LEN]; /* file system info */ int link_count, total_link_count; /* ipc stuff */ struct sysv_sem sysvsem; /* CPU-specific state of this task */ struct thread_struct thread; /* filesystem information */ struct fs_struct *fs; /* open file information */ struct files_struct *files; /* namespace */ struct namespace *namespace; /* signal handlers */ struct signal_struct *signal; struct sighand_struct *sighand; sigset_t blocked, real_blocked; struct sigpending pending; unsigned long sas_ss_sp; size_t sas_ss_size; int (*notifier)(void *priv); void *notifier_data; sigset_t *notifier_mask; void *security; struct audit_context *audit_context; /* Thread group tracking */ u32 parent_exec_id; u32 self_exec_id; /* Protection of (de-)allocation: mm, files, fs, tty, keyrings */ spinlock_t alloc_lock; /* Protection of proc_dentry: nesting proc_lock, dcache_lock, write_lock_irq(&tasklist_lock); */ spinlock_t proc_lock; /* context-switch lock */ spinlock_t switch_lock; /* journalling filesystem info */ void *journal_info; /* VM state */ struct reclaim_state *reclaim_state; struct dentry *proc_dentry; struct backing_dev_info *backing_dev_info; struct io_context *io_context; unsigned long ptrace_message; siginfo_t *last_siginfo; /* For ptrace use. */ /* * current io wait handle: wait queue entry to use for io waits * If this thread is processing aio, this points at the waitqueue * inside the currently handled kiocb. It may be NULL (i.e. default * to a stack based synchronous wait) if its doing sync IO. */ wait_queue_t *io_wait; /* i/o counters(bytes read/written, #syscalls */ u64 rchar, wchar, syscr, syscw; #if defined(CONFIG_BSD_PROCESS_ACCT) u64 acct_rss_mem1; /* accumulated rss usage */ u64 acct_vm_mem1; /* accumulated virtual memory usage */ clock_t acct_stimexpd; /* clock_t-converted stime since last update */ #endif #ifdef CONFIG_NUMA struct mempolicy *mempolicy; short il_next; #endif };
其中
- 1)unsigned short pid 為用戶標識
(2)int pid 為進程標識
(3)int processor標識用戶正在使用的CPU,以支持對稱多處理機方式;
(4)volatile long state 標識進程的狀態,可為下列六種狀態之一:
可運行狀態(TASK-RUNING);
可中斷阻塞狀態(TASK-UBERRUPTIBLE)
不可中斷阻塞狀態(TASK-UNINTERRUPTIBLE)
僵死狀態(TASK-ZOMBLE)
暫停態(TASK_STOPPED)
交換態(TASK_SWAPPING)
(5)long prority表示進程的優先級
(6)unsigned long rt_prority 表示實時進程的優先級,對於普通進程無效
(7)long counter 為進程動態優先級計數器,用於進程輪轉調度算法
(8)unsigned long policy 表示進程調度策略,其值為下列三種情況之一:
SCHED_OTHER(值為0)對應普通進程優先級輪轉法(round robin)
SCHED_FIFO(值為1)對應實時進程先來先服務算法;
SCHED_RR(值為2)對應實時進程優先級輪轉法
(9)struct task_struct *next_task,*prev_task為進程PCB雙向鏈表的前後項指針
(10)struct task_struct *next_run,*prev_run為就緒隊列雙向鏈表的前後項指針(11)struct task_struct *p_opptr,*p_pptr,*p_cptr,*p_ysptr,*p_ptr指明進程家族間的關系,分別為指向祖父進程、父進程、子進程以及新老進程的指針。
- 1)unsigned short pid 為用戶標識
2.進程的狀態轉換(網圖侵刪)
3.進程調度
__wait_event_interruptible_timeout(wq, condition, ret) do { DEFINE_WAIT(__wait); for (;;) { prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE); if (condition) break; if (!signal_pending(current)) { ret = schedule_timeout(ret); if (!ret) break; continue; } ret = -ERESTARTSYS; break; } finish_wait(&wq, &__wait); } while (0)
1、進程調度的時機
進程狀態轉換:
當前進程時間片用完
設備驅動程序運行時
從內核態返回到用戶態
從中斷或系統調用中返回;
進程重新允許搶占;
調用該函數為主動進入休眠。
調度程序運行時,要在所有處於可運行狀態的進程中選擇最值得運行的進程投入運行。
1.進程的調度策略(policy)
SCHED_NORMAL(SCHED_OTHER):普通的分時進程
SCHED_FIFO :先入先進的實時進程
SCHED_RR: 時間片輪轉的實時進程
SCHED_BATCH:批處理進程,與普通進程不被搶占的情況類似
SCHED_IDLE:CPU空閑時,即SCHED_IDLE等級以外處於可執行狀態的進程消失時,將被賦予執行權。也就是它將成為優先級最低的進程。
linux對調度策略定義如下:
#define SCHED_NORMAL 0 #define SCHED_FIFO 1
#define SCHED_RR 2
#define SCHED_BATCH 3 #define SCHED_IDLE 5
進程的調度算法:
1.先來先服務FCFS:該算法即可用於作業調度,也可用於進程調度
2.短作業優先/短進程優先 :SJF/ SPF :選擇剩余時間最短的
3.優先權優先 FPF
4.時間片輪詢法
4.對Linux進程模型的看法
一個優秀的系統無法脫離優秀的結構而存。作為一個開源的操作系統,Linux建立在許許多多誌同道合的開發者的緊密合作之上。通過閱讀代碼,我們可以發現其書寫的規範性和命名極強的可讀性。也許這提醒了我們,在當前的環境下,多人協作並構築出一個可行的標準是極其重要的。
參考材料:
https://elixir.bootlin.com/linux/v2.6.11/ident/sched_class
https://www.ibm.com/developerworks/cn/linux/l-task-killable/
https://www.cnblogs.com/ck1020/p/6089970.html
https://blog.csdn.net/shuizhilan/article/details/6642040
https://blog.csdn.net/kevin_hcy/article/details/6064518
基於Linux的源代碼