進程描述符(PCB)
概述
CPU作為計算機的核心部件,我們當然希望它能一直工作,充分提高它的使用效率。對於上層軟件來說,我們不可能直接去操控CPU(我們沒這能力也沒必要),因為操作系統是夾在計算機硬件和上層軟件的中間層,所以操作系統就要充分擔當起這個中間人的角色,替計算機管理好CPU,保證上層軟件都能夠充分使用到CPU。
我們知道一個計算機上面運行了很多很多進程,這些進程其實就是使用CPU的最小單元,如果我們能夠管理好這些進程,那從側面來講我們也就管理好了CPU。
為什么需要對進程進行管理
首先我們先看一個例子:
int main(int argc, char* argv[])
{
int index = 0;
int to = atoi(argv[1]);
for (index = 1;index<=to; index++) {
sum += index;
fprintf(fp,"%d",sum);
}
}
當我們不存在fprintf語句時,我們執行10000000次循環,耗時0.015s左右,但是當我們加上fprintf時,我們執行1000次,耗時0.8952s,我們可以算一下2者的比例:
(0.015:10^7) : (0.859:10^3) = 5.7*10^5 : 1
從結果我們可以看出,加了打印語句和不加打印語句,代碼的執行時間差距非常大,所以這就提示我們不是每個進程執行時間都一樣,我們需要對進程進行合理的管理,才能充分利用CPU,這就涉及到進程的切換。
進程描述符(PCB)
上面我們說到,如果想充分使用CPU,必須對進程進行相應的管理,盡量使進程能夠無縫的使用CPU。既然涉及到進程的切換,那么就會面臨一個問題,進程現場的保護,當我們想切換到下一個進程的時候,上一個進程的現場我們必須管理好,即在切回來的時候現場必須是完整的。那么我們用什么來保存進程的信息呢,答案是進程描述符,每一個進程都有一個進程描述符(PCB),在進程創建的時候,生成PCB,在進程消亡的時候撤銷PCB,PCB記錄了操作系統所需的描述一個進程的所有信息,如打開的文件,掛起的信號量,進程狀態以及地址空間等。
在Linux系統中,每一個進程都是由task_struct數據結構來描述,task_struct就是我們平時所說的PCB,當我們fork()一個進程時,操作系統會為我們生成一個PCB,然后從父進程那里繼承一些數據,並同時把新進程插入到進程樹中,以待進行管理。
我們可以先理論推導一下task_struct都有哪些字段組成:
1、進程的狀態,記錄進程在等待,運行,或者死鎖
2、調度信息,由哪個函數調度,怎樣調度等
3、進程的通訊狀態
4、進程上下文和內核上下文
5、進程的父子兄弟指針,當然也是task_struct類型
6、內存信息
7、處理器上下文
下面是一個完整的PCB結構。
struct task_struct
{
/*
1. state: 進程執行時,它會根據具體情況改變狀態。進程狀態是進程調度和對換的依據。Linux中的進程主要有如下狀態:
1) TASK_RUNNING: 可運行
處於這種狀態的進程,只有兩種狀態:
1.1) 正在運行
正在運行的進程就是當前進程(由current所指向的進程)
1.2) 正准備運行
准備運行的進程只要得到CPU就可以立即投入運行,CPU是這些進程唯一等待的系統資源,系統中有一個運行隊列(run_queue),用來容納所有處於可運行狀態的進程,調度程序執行時,從中選擇一個進程投入運行
2) TASK_INTERRUPTIBLE: 可中斷的等待狀態,是針對等待某事件或其他資源的睡眠進程設置的,在內核發送信號給該進程表明事件已經發生時,進程狀態變為TASK_RUNNING,它只要調度器選中該進程即可恢復執行
3) TASK_UNINTERRUPTIBLE: 不可中斷的等待狀態
處於該狀態的進程正在等待某個事件(event)或某個資源,它肯定位於系統中的某個等待隊列(wait_queue)中,處於不可中斷等待態的進程是因為硬件環境不能滿足而等待,例如等待特定的系統資源,它任何情況下都不能被打斷,只能用特定的方式來喚醒它,例如喚醒函數wake_up()等
它們不能由外部信號喚醒,只能由內核親自喚醒
4) TASK_ZOMBIE: 僵死
進程雖然已經終止,但由於某種原因,父進程還沒有執行wait()系統調用,終止進程的信息也還沒有回收。顧名思義,處於該狀態的進程就是死進程,這種進程實際上是系統中的垃圾,必須進行相應處理以釋放其占用的資源。
5) TASK_STOPPED: 暫停
此時的進程暫時停止運行來接受某種特殊處理。通常當進程接收到SIGSTOP、SIGTSTP、SIGTTIN或 SIGTTOU信號后就處於這種狀態。例如,正接受調試的進程就處於這種狀態
6) TASK_TRACED
從本質上來說,這屬於TASK_STOPPED狀態,用於從停止的進程中,將當前被調試的進程與常規的進程區分開來
7) TASK_DEAD
父進程wait系統調用發出后,當子進程退出時,父進程負責回收子進程的全部資源,子進程進入TASK_DEAD狀態
8) TASK_SWAPPING: 換入/換出
*/
volatile long state;
/*
2. stack
進程內核棧,進程通過alloc_thread_info函數分配它的內核棧,通過free_thread_info函數釋放所分配的內核棧
*/
void *stack;
/*
3. usage
進程描述符使用計數,被置為2時,表示進程描述符正在被使用而且其相應的進程處於活動狀態
*/
atomic_t usage;
/*
4. flags
flags是進程當前的狀態標志(注意和運行狀態區分)
1) #define PF_ALIGNWARN 0x00000001: 顯示內存地址未對齊警告
2) #define PF_PTRACED 0x00000010: 標識是否是否調用了ptrace
3) #define PF_TRACESYS 0x00000020: 跟蹤系統調用
4) #define PF_FORKNOEXEC 0x00000040: 已經完成fork,但還沒有調用exec
5) #define PF_SUPERPRIV 0x00000100: 使用超級用戶(root)權限
6) #define PF_DUMPCORE 0x00000200: dumped core
7) #define PF_SIGNALED 0x00000400: 此進程由於其他進程發送相關信號而被殺死
8) #define PF_STARTING 0x00000002: 當前進程正在被創建
9) #define PF_EXITING 0x00000004: 當前進程正在關閉
10) #define PF_USEDFPU 0x00100000: Process used the FPU this quantum(SMP only)
#define PF_DTRACE 0x00200000: delayed trace (used on m68k)
*/
unsigned int flags;
/*
5. ptrace
ptrace系統調用,成員ptrace被設置為0時表示不需要被跟蹤,它的可能取值如下:
linux-2.6.38.8/include/linux/ptrace.h
1) #define PT_PTRACED 0x00000001
2) #define PT_DTRACE 0x00000002: delayed trace (used on m68k, i386)
3) #define PT_TRACESYSGOOD 0x00000004
4) #define PT_PTRACE_CAP 0x00000008: ptracer can follow suid-exec
5) #define PT_TRACE_FORK 0x00000010
6) #define PT_TRACE_VFORK 0x00000020
7) #define PT_TRACE_CLONE 0x00000040
8) #define PT_TRACE_EXEC 0x00000080
9) #define PT_TRACE_VFORK_DONE 0x00000100
10) #define PT_TRACE_EXIT 0x00000200
*/
unsigned int ptrace;
unsigned long ptrace_message;
siginfo_t *last_siginfo;
/*
6. lock_depth
用於表示獲取大內核鎖的次數,如果進程未獲得過鎖,則置為-1
*/
int lock_depth;
/*
7. oncpu
在SMP上幫助實現無加鎖的進程切換(unlocked context switches)
*/
#ifdef CONFIG_SMP
#ifdef __ARCH_WANT_UNLOCKED_CTXSW
int oncpu;
#endif
#endif
/*
8. 進程調度
1) prio: 調度器考慮的優先級保存在prio,由於在某些情況下內核需要暫時提高進程的優先級,因此需要第三個成員來表示(除了static_prio、normal_prio之外),由於這些改變不是持久的,因此靜態(static_prio)和普通(normal_prio)優先級不受影響
2) static_prio: 用於保存進程的"靜態優先級",靜態優先級是進程"啟動"時分配的優先級,它可以用nice、sched_setscheduler系統調用修改,否則在進程運行期間會一直保持恆定
3) normal_prio: 表示基於進程的"靜態優先級"和"調度策略"計算出的優先級,因此,即使普通進程和實時進程具有相同的靜態優先級(static_prio),其普通優先級(normal_prio)也是不同的。進程分支時(fork),新創建的子進程會集成普通優先級
*/
int prio, static_prio, normal_prio;
/*
4) rt_priority: 表示實時進程的優先級,需要明白的是,"實時進程優先級"和"普通進程優先級"有兩個獨立的范疇,實時進程即使是最低優先級也高於普通進程,最低的實時優先級為0,最高的優先級為99,值越大,表明優先級越高
*/
unsigned int rt_priority;
/*
5) sched_class: 該進程所屬的調度類,目前內核中有實現以下四種:
5.1) static const struct sched_class fair_sched_class;
5.2) static const struct sched_class rt_sched_class;
5.3) static const struct sched_class idle_sched_class;
5.4) static const struct sched_class stop_sched_class;
*/
const struct sched_class *sched_class;
/*
6) se: 用於普通進程的調用實體
調度器不限於調度進程,還可以處理更大的實體,這可以實現"組調度",可用的CPU時間可以首先在一般的進程組(例如所有進程可以按所有者分組)之間分配,接下來分配的時間在組內再次分配
這種一般性要求調度器不直接操作進程,而是處理"可調度實體",一個實體有sched_entity的一個實例標識
在最簡單的情況下,調度在各個進程上執行,由於調度器設計為處理可調度的實體,在調度器看來各個進程也必須也像這樣的實體,因此se在task_struct中內嵌了一個sched_entity實例,調度器可據此操作各個task_struct
*/
struct sched_entity se;
/*
7) rt: 用於實時進程的調用實體
*/
struct sched_rt_entity rt;
#ifdef CONFIG_PREEMPT_NOTIFIERS
/*
9. preempt_notifier
preempt_notifiers結構體鏈表
*/
struct hlist_head preempt_notifiers;
#endif
/*
10. fpu_counter
FPU使用計數
*/
unsigned char fpu_counter;
#ifdef CONFIG_BLK_DEV_IO_TRACE
/*
11. btrace_seq
blktrace是一個針對Linux內核中塊設備I/O層的跟蹤工具
*/
unsigned int btrace_seq;
#endif
/*
12. policy
policy表示進程的調度策略,目前主要有以下五種:
1) #define SCHED_NORMAL 0: 用於普通進程,它們通過完全公平調度器來處理
2) #define SCHED_FIFO 1: 先來先服務調度,由實時調度類處理
3) #define SCHED_RR 2: 時間片輪轉調度,由實時調度類處理
4) #define SCHED_BATCH 3: 用於非交互、CPU使用密集的批處理進程,通過完全公平調度器來處理,調度決策對此類進程給與"冷處理",它們絕不會搶占CFS調度器處理的另一個進程,因此不會干擾交互式進程,如果不打算用nice降低進程的靜態優先級,同時又不希望該進程影響系統的交互性,最適合用該調度策略
5) #define SCHED_IDLE 5: 可用於次要的進程,其相對權重總是最小的,也通過完全公平調度器來處理。要注意的是,SCHED_IDLE不負責調度空閑進程,空閑進程由內核提供單獨的機制來處理
只有root用戶能通過sched_setscheduler()系統調用來改變調度策略
*/
unsigned int policy;
/*
13. cpus_allowed
cpus_allowed是一個位域,在多處理器系統上使用,用於控制進程可以在哪里處理器上運行
*/
cpumask_t cpus_allowed;
/*
14. RCU同步原語
*/
#ifdef CONFIG_TREE_PREEMPT_RCU
int rcu_read_lock_nesting;
char rcu_read_unlock_special;
struct rcu_node *rcu_blocked_node;
struct list_head rcu_node_entry;
#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
/*
15. sched_info
用於調度器統計進程的運行信息
*/
struct sched_info sched_info;
#endif
/*
16. tasks
通過list_head將當前進程的task_struct串聯進內核的進程列表中,構建;linux進程鏈表
*/
struct list_head tasks;
/*
17. pushable_tasks
limit pushing to one attempt
*/
struct plist_node pushable_tasks;
/*
18. 進程地址空間
1) mm: 指向進程所擁有的內存描述符
2) active_mm: active_mm指向進程運行時所使用的內存描述符
對於普通進程而言,這兩個指針變量的值相同。但是,內核線程不擁有任何內存描述符,所以它們的mm成員總是為NULL。當內核線程得以運行時,它的active_mm成員被初始化為前一個運行進程的active_mm值
*/
struct mm_struct *mm, *active_mm;
/*
19. exit_state
進程退出狀態碼
*/
int exit_state;
/*
20. 判斷標志
1) exit_code
exit_code用於設置進程的終止代號,這個值要么是_exit()或exit_group()系統調用參數(正常終止),要么是由內核提供的一個錯誤代號(異常終止)
2) exit_signal
exit_signal被置為-1時表示是某個線程組中的一員。只有當線程組的最后一個成員終止時,才會產生一個信號,以通知線程組的領頭進程的父進程
*/
int exit_code, exit_signal;
/*
3) pdeath_signal
pdeath_signal用於判斷父進程終止時發送信號
*/
int pdeath_signal;
/*
4) personality用於處理不同的ABI,它的可能取值如下:
enum
{
PER_LINUX = 0x0000,
PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT,
PER_LINUX_FDPIC = 0x0000 | FDPIC_FUNCPTRS,
PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS |
WHOLE_SECONDS | SHORT_INODE,
PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS,
PER_BSD = 0x0006,
PER_SUNOS = 0x0006 | STICKY_TIMEOUTS,
PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
PER_LINUX32 = 0x0008,
PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB,
PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,
PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,
PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,
PER_RISCOS = 0x000c,
PER_SOLARIS = 0x000d | STICKY_TIMEOUTS,
PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
PER_OSF4 = 0x000f,
PER_HPUX = 0x0010,
PER_MASK = 0x00ff,
};
*/
unsigned int personality;
/*
5) did_exec
did_exec用於記錄進程代碼是否被execve()函數所執行
*/
unsigned did_exec:1;
/*
6) in_execve
in_execve用於通知LSM是否被do_execve()函數所調用
*/
unsigned in_execve:1;
/*
7) in_iowait
in_iowait用於判斷是否進行iowait計數
*/
unsigned in_iowait:1;
/*
8) sched_reset_on_fork
sched_reset_on_fork用於判斷是否恢復默認的優先級或調度策略
*/
unsigned sched_reset_on_fork:1;
/*
21. 進程標識符(PID)
在CONFIG_BASE_SMALL配置為0的情況下,PID的取值范圍是0到32767,即系統中的進程數最大為32768個
#define PID_MAX_DEFAULT (CONFIG_BASE_SMALL ? 0x1000 : 0x8000)
在Linux系統中,一個線程組中的所有線程使用和該線程組的領頭線程(該組中的第一個輕量級進程)相同的PID,並被存放在tgid成員中。只有線程組的領頭線程的pid成員才會被設置為與tgid相同的值。注意,getpid()系統調用
返回的是當前進程的tgid值而不是pid值。
*/
pid_t pid;
pid_t tgid;
#ifdef CONFIG_CC_STACKPROTECTOR
/*
22. stack_canary
防止內核堆棧溢出,在GCC編譯內核時,需要加上-fstack-protector選項
*/
unsigned long stack_canary;
#endif
/*
23. 表示進程親屬關系的成員
1) real_parent: 指向其父進程,如果創建它的父進程不再存在,則指向PID為1的init進程
2) parent: 指向其父進程,當它終止時,必須向它的父進程發送信號。它的值通常與real_parent相同
*/
struct task_struct *real_parent;
struct task_struct *parent;
/*
3) children: 表示鏈表的頭部,鏈表中的所有元素都是它的子進程(子進程鏈表)
4) sibling: 用於把當前進程插入到兄弟鏈表中(連接到父進程的子進程鏈表(兄弟鏈表))
5) group_leader: 指向其所在進程組的領頭進程
*/
struct list_head children;
struct list_head sibling;
struct task_struct *group_leader;
struct list_head ptraced;
struct list_head ptrace_entry;
struct bts_context *bts;
/*
24. pids
PID散列表和鏈表
*/
struct pid_link pids[PIDTYPE_MAX];
/*
25. thread_group
線程組中所有進程的鏈表
*/
struct list_head thread_group;
/*
26. do_fork函數
1) vfork_done
在執行do_fork()時,如果給定特別標志,則vfork_done會指向一個特殊地址
2) set_child_tid、clear_child_tid
如果copy_process函數的clone_flags參數的值被置為CLONE_CHILD_SETTID或CLONE_CHILD_CLEARTID,則會把child_tidptr參數的值分別復制到set_child_tid和clear_child_tid成員。這些標志說明必須改變子
進程用戶態地址空間的child_tidptr所指向的變量的值。
*/
struct completion *vfork_done;
int __user *set_child_tid;
int __user *clear_child_tid;
/*
27. 記錄進程的I/O計數(時間)
1) utime
用於記錄進程在"用戶態"下所經過的節拍數(定時器)
2) stime
用於記錄進程在"內核態"下所經過的節拍數(定時器)
3) utimescaled
用於記錄進程在"用戶態"的運行時間,但它們以處理器的頻率為刻度
4) stimescaled
用於記錄進程在"內核態"的運行時間,但它們以處理器的頻率為刻度
*/
cputime_t utime, stime, utimescaled, stimescaled;
/*
5) gtime
以節拍計數的虛擬機運行時間(guest time)
*/
cputime_t gtime;
/*
6) prev_utime、prev_stime是先前的運行時間
*/
cputime_t prev_utime, prev_stime;
/*
7) nvcsw
自願(voluntary)上下文切換計數
8) nivcsw
非自願(involuntary)上下文切換計數
*/
unsigned long nvcsw, nivcsw;
/*
9) start_time
進程創建時間
10) real_start_time
進程睡眠時間,還包含了進程睡眠時間,常用於/proc/pid/stat,
*/
struct timespec start_time;
struct timespec real_start_time;
/*
11) cputime_expires
用來統計進程或進程組被跟蹤的處理器時間,其中的三個成員對應着cpu_timers[3]的三個鏈表
*/
struct task_cputime cputime_expires;
struct list_head cpu_timers[3];
#ifdef CONFIG_DETECT_HUNG_TASK
/*
12) last_switch_count
nvcsw和nivcsw的總和
*/
unsigned long last_switch_count;
#endif
struct task_io_accounting ioac;
#if defined(CONFIG_TASK_XACCT)
u64 acct_rss_mem1;
u64 acct_vm_mem1;
cputime_t acct_timexpd;
#endif
/*
28. 缺頁統計
*/
unsigned long min_flt, maj_flt;
/*
29. 進程權能
*/
const struct cred *real_cred;
const struct cred *cred;
struct mutex cred_guard_mutex;
struct cred *replacement_session_keyring;
/*
30. comm[TASK_COMM_LEN]
相應的程序名
*/
char comm[TASK_COMM_LEN];
/*
31. 文件
1) fs
用來表示進程與文件系統的聯系,包括當前目錄和根目錄
2) files
表示進程當前打開的文件
*/
int link_count, total_link_count;
struct fs_struct *fs;
struct files_struct *files;
#ifdef CONFIG_SYSVIPC
/*
32. sysvsem
進程通信(SYSVIPC)
*/
struct sysv_sem sysvsem;
#endif
/*
33. 處理器特有數據
*/
struct thread_struct thread;
/*
34. nsproxy
命名空間
*/
struct nsproxy *nsproxy;
/*
35. 信號處理
1) signal: 指向進程的信號描述符
2) sighand: 指向進程的信號處理程序描述符
*/
struct signal_struct *signal;
struct sighand_struct *sighand;
/*
3) blocked: 表示被阻塞信號的掩碼
4) real_blocked: 表示臨時掩碼
*/
sigset_t blocked, real_blocked;
sigset_t saved_sigmask;
/*
5) pending: 存放私有掛起信號的數據結構
*/
struct sigpending pending;
/*
6) sas_ss_sp: 信號處理程序備用堆棧的地址
7) sas_ss_size: 表示堆棧的大小
*/
unsigned long sas_ss_sp;
size_t sas_ss_size;
/*
8) notifier
設備驅動程序常用notifier指向的函數來阻塞進程的某些信號
9) otifier_data
指的是notifier所指向的函數可能使用的數據。
10) otifier_mask
標識這些信號的位掩碼
*/
int (*notifier)(void *priv);
void *notifier_data;
sigset_t *notifier_mask;
/*
36. 進程審計
*/
struct audit_context *audit_context;
#ifdef CONFIG_AUDITSYSCALL
uid_t loginuid;
unsigned int sessionid;
#endif
/*
37. secure computing
*/
seccomp_t seccomp;
/*
38. 用於copy_process函數使用CLONE_PARENT標記時
*/
u32 parent_exec_id;
u32 self_exec_id;
/*
39. alloc_lock
用於保護資源分配或釋放的自旋鎖
*/
spinlock_t alloc_lock;
/*
40. 中斷
*/
#ifdef CONFIG_GENERIC_HARDIRQS
struct irqaction *irqaction;
#endif
#ifdef CONFIG_TRACE_IRQFLAGS
unsigned int irq_events;
int hardirqs_enabled;
unsigned long hardirq_enable_ip;
unsigned int hardirq_enable_event;
unsigned long hardirq_disable_ip;
unsigned int hardirq_disable_event;
int softirqs_enabled;
unsigned long softirq_disable_ip;
unsigned int softirq_disable_event;
unsigned long softirq_enable_ip;
unsigned int softirq_enable_event;
int hardirq_context;
int softirq_context;
#endif
/*
41. pi_lock
task_rq_lock函數所使用的鎖
*/
spinlock_t pi_lock;
#ifdef CONFIG_RT_MUTEXES
/*
42. 基於PI協議的等待互斥鎖,其中PI指的是priority inheritance/9優先級繼承)
*/
struct plist_head pi_waiters;
struct rt_mutex_waiter *pi_blocked_on;
#endif
#ifdef CONFIG_DEBUG_MUTEXES
/*
43. blocked_on
死鎖檢測
*/
struct mutex_waiter *blocked_on;
#endif
/*
44. lockdep,
*/
#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];
gfp_t lockdep_reclaim_gfp;
#endif
/*
45. journal_info
JFS文件系統
*/
void *journal_info;
/*
46. 塊設備鏈表
*/
struct bio *bio_list, **bio_tail;
/*
47. reclaim_state
內存回收
*/
struct reclaim_state *reclaim_state;
/*
48. backing_dev_info
存放塊設備I/O數據流量信息
*/
struct backing_dev_info *backing_dev_info;
/*
49. io_context
I/O調度器所使用的信息
*/
struct io_context *io_context;
/*
50. CPUSET功能
*/
#ifdef CONFIG_CPUSETS
nodemask_t mems_allowed;
int cpuset_mem_spread_rotor;
#endif
/*
51. Control Groups
*/
#ifdef CONFIG_CGROUPS
struct css_set *cgroups;
struct list_head cg_list;
#endif
/*
52. robust_list
futex同步機制
*/
#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;
#endif
#ifdef CONFIG_PERF_EVENTS
struct perf_event_context *perf_event_ctxp;
struct mutex perf_event_mutex;
struct list_head perf_event_list;
#endif
/*
53. 非一致內存訪問(NUMA Non-Uniform Memory Access)
*/
#ifdef CONFIG_NUMA
struct mempolicy *mempolicy; /* Protected by alloc_lock */
short il_next;
#endif
/*
54. fs_excl
文件系統互斥資源
*/
atomic_t fs_excl;
/*
55. rcu
RCU鏈表
*/
struct rcu_head rcu;
/*
56. splice_pipe
管道
*/
struct pipe_inode_info *splice_pipe;
/*
57. delays
延遲計數
*/
#ifdef CONFIG_TASK_DELAY_ACCT
struct task_delay_info *delays;
#endif
/*
58. make_it_fail
fault injection
*/
#ifdef CONFIG_FAULT_INJECTION
int make_it_fail;
#endif
/*
59. dirties
FLoating proportions
*/
struct prop_local_single dirties;
/*
60. Infrastructure for displayinglatency
*/
#ifdef CONFIG_LATENCYTOP
int latency_record_count;
struct latency_record latency_record[LT_SAVECOUNT];
#endif
/*
61. time slack values,常用於poll和select函數
*/
unsigned long timer_slack_ns;
unsigned long default_timer_slack_ns;
/*
62. scm_work_list
socket控制消息(control message)
*/
struct list_head *scm_work_list;
/*
63. ftrace跟蹤器
*/
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
int curr_ret_stack;
struct ftrace_ret_stack *ret_stack;
unsigned long long ftrace_timestamp;
atomic_t trace_overrun;
atomic_t tracing_graph_pause;
#endif
#ifdef CONFIG_TRACING
unsigned long trace;
unsigned long trace_recursion;
#endif
};