acl在内核里的位置_Linux 进程在内核眼中是什么样子的?
本篇算是進(jìn)程管理的的揭幕篇,簡單介紹一個進(jìn)程在內(nèi)核眼里的來龍去脈,為接下來的進(jìn)程創(chuàng)建,進(jìn)程調(diào)度,進(jìn)程管理等篇章做好學(xué)習(xí)準(zhǔn)備。
從程序到進(jìn)程再到內(nèi)核
啥是程序,啥是進(jìn)程,一張圖可以給我們解釋:
程序轉(zhuǎn)換為進(jìn)程的過程不是本文重點,這里不做詳解,詳情請看 《 Linux 程序編譯過程的來龍去脈 》。接下來我們轉(zhuǎn)換鏡頭,站在內(nèi)核OS的視角看什么是程序,什么是進(jìn)程。
ELF可執(zhí)行文件送給內(nèi)核后,OS是如何看待它的呢?換句話講,內(nèi)核OS眼里只有進(jìn)程:
通過 top 命令我們可以看到 linux 的各種進(jìn)程(即上右圖)。
內(nèi)核通過 task_struct 描述進(jìn)程
用命令 pstree 可以讓內(nèi)核以樹形的結(jié)構(gòu)把進(jìn)程之間的關(guān)系列出來,如下圖:
這是進(jìn)程在內(nèi)核中的結(jié)構(gòu)形式,那么內(nèi)核是如何來以樹形結(jié)構(gòu)管理描述這些進(jìn)程的呢?用來描述進(jìn)程的數(shù)據(jù)結(jié)構(gòu),可以理解為進(jìn)程的屬性。比如進(jìn)程的狀態(tài)、進(jìn)程的標(biāo)識(PID)等,都被封裝在了進(jìn)程描述符這個數(shù)據(jù)結(jié)構(gòu)中,一起來看下今天的主角—— task_struct 結(jié)構(gòu)體。
struct task_struct {volatile long state; //說明了該進(jìn)程是否可以執(zhí)行,還是可中斷等信息 -1 unrunnable, 0 runnable, >0 stoppedunsigned long flags; //Flage 是進(jìn)程號,在調(diào)用fork()時給出int sigpending; //進(jìn)程上是否有待處理的信號mm_segment_t addr_limit; //進(jìn)程地址空間,區(qū)分內(nèi)核進(jìn)程與普通進(jìn)程在內(nèi)存存放的位置不同 //0-0xBFFFFFFF for user-thead //0-0xFFFFFFFF for kernel-thread//調(diào)度標(biāo)志,表示該進(jìn)程是否需要重新調(diào)度,若非0,則當(dāng)從內(nèi)核態(tài)返回到用戶態(tài),會發(fā)生調(diào)度volatile long need_resched;int lock_depth; //鎖深度long nice; //進(jìn)程的基本時間片//進(jìn)程的調(diào)度策略,有三種,實時進(jìn)程:SCHED_FIFO,SCHED_RR, 分時進(jìn)程:SCHED_OTHERunsigned long policy;struct mm_struct *mm; //進(jìn)程內(nèi)存管理信息int processor;//若進(jìn)程不在任何CPU上運行, cpus_runnable 的值是0,否則是1 這個值在運行隊列被鎖時更新unsigned long cpus_runnable, cpus_allowed;struct list_head run_list; //指向運行隊列的指針unsigned long sleep_time; //進(jìn)程的睡眠時間//用于將系統(tǒng)中所有的進(jìn)程連成一個雙向循環(huán)鏈表, 其根是init_taskstruct task_struct *next_task, *prev_task;struct mm_struct *active_mm;struct list_head local_pages; //指向本地頁面 unsigned int allocation_order, nr_local_pages;struct linux_binfmt *binfmt; //進(jìn)程所運行的可執(zhí)行文件的格式int exit_code, exit_signal;int pdeath_signal; //父進(jìn)程終止時向子進(jìn)程發(fā)送的信號unsigned long personality;//Linux可以運行由其他UNIX操作系統(tǒng)生成的符合iBCS2標(biāo)準(zhǔn)的程序int did_exec:1; pid_t pid; //進(jìn)程標(biāo)識符,用來代表一個進(jìn)程pid_t pgrp; //進(jìn)程組標(biāo)識,表示進(jìn)程所屬的進(jìn)程組pid_t tty_old_pgrp; //進(jìn)程控制終端所在的組標(biāo)識pid_t session; //進(jìn)程的會話標(biāo)識pid_t tgid;int leader; //表示進(jìn)程是否為會話主管struct task_struct *p_opptr,*p_pptr,*p_cptr,*p_ysptr,*p_osptr;struct list_head thread_group; //線程鏈表struct task_struct *pidhash_next; //用于將進(jìn)程鏈入HASH表struct task_struct **pidhash_pprev;wait_queue_head_t wait_chldexit; //供wait4()使用struct completion *vfork_done; //供vfork() 使用unsigned long rt_priority; //實時優(yōu)先級,用它計算實時進(jìn)程調(diào)度時的weight值struct timer_list real_timer; //指向?qū)崟r定時器的指針struct tms times; //記錄進(jìn)程消耗的時間unsigned long start_time; //進(jìn)程創(chuàng)建的時間//記錄進(jìn)程在每個CPU上所消耗的用戶態(tài)時間和核心態(tài)時間long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS]; int swappable:1; //表示進(jìn)程的虛擬地址空間是否允許換出int ngroups; //記錄進(jìn)程在多少個用戶組中g(shù)id_t groups[NGROUPS]; //記錄進(jìn)程所在的組//進(jìn)程的權(quán)能,分別是有效位集合,繼承位集合,允許位集合kernel_cap_t cap_effective, cap_inheritable, cap_permitted;int keep_capabilities:1;struct user_struct *user;struct rlimit rlim[RLIM_NLIMITS]; //與進(jìn)程相關(guān)的資源限制信息unsigned short used_math; //是否使用FPUchar comm[16]; //進(jìn)程正在運行的可執(zhí)行文件名 //文件系統(tǒng)信息int link_count, total_link_count;//NULL if no tty 進(jìn)程所在的控制終端,如果不需要控制終端,則該指針為空struct tty_struct *tty;unsigned int locks;//進(jìn)程間通信信息struct sem_undo *semundo; //進(jìn)程在信號燈上的所有undo操作struct sem_queue *semsleeping; //當(dāng)進(jìn)程因為信號燈操作而掛起時,他在該隊列中記錄等待的操作//進(jìn)程的CPU狀態(tài),切換時,要保存到停止進(jìn)程的task_struct中struct thread_struct thread; //文件系統(tǒng)信息struct fs_struct *fs; //打開文件信息struct files_struct *files; //信號處理函數(shù)spinlock_t sigmask_lock;struct signal_struct *sig; //信號處理函數(shù)sigset_t blocked; //進(jìn)程當(dāng)前要阻塞的信號,每個信號對應(yīng)一位struct sigpending pending; //進(jìn)程上是否有待處理的信號......};內(nèi)核就是通過list_head鏈表把各個進(jìn)程關(guān)系以樹形結(jié)構(gòu)管理起來的。
task_struct 結(jié)構(gòu)體內(nèi)容太多,這里只列出部分成員變量,感興趣的讀者可以去源碼 include/linux/sched.h頭文件查看。
task_struct 中的主要信息分類:
1. 標(biāo)示符:描述本進(jìn)程的唯一標(biāo)識符,用來區(qū)別其他進(jìn)程。2. 狀態(tài):任務(wù)狀態(tài),退出代碼,退出信號等?3. 優(yōu)先級:相對于其他進(jìn)程的優(yōu)先級?4. 程序計數(shù)器:程序中即將被執(zhí)行的下一條指令的地址?5. 內(nèi)存指針:包括程序代碼和進(jìn)程相關(guān)數(shù)據(jù)的指針,還有和其他進(jìn)程共享的內(nèi)存塊的指針?6. 上下文數(shù)據(jù):進(jìn)程執(zhí)行時處理器的寄存器中的數(shù)據(jù)?7. I/O狀態(tài)信息:包括顯示的I/O請求,分配的進(jìn)程I/O設(shè)備和進(jìn)程使用的文件列表?8. 記賬信息:可能包括處理器時間總和,使用的時鐘總和,時間限制,記帳號等這些信息每類都可以單獨開個章節(jié)去講解,這里先簡單描述下任務(wù)狀態(tài)的轉(zhuǎn)換,以后篇章再深入介紹各個分類。
任務(wù)狀態(tài)轉(zhuǎn)換
上面可以看到變量定義后面的注釋,它說明變量內(nèi)容<0是不運行的,=0是運行狀態(tài),>0是停止?fàn)顟B(tài)。
下面我們介紹幾個常用的取值:
任務(wù)狀態(tài)在不同情況下的狀態(tài)轉(zhuǎn)換如下:
圖來源于https://www.lagou.com/lgeduarticle/96239.html
內(nèi)核如何存放 task_struct
我們知道一個進(jìn)程所占的棧空間有用戶棧和內(nèi)核棧,用戶棧的分布方式見之前的文章《 C語言在ARM中函數(shù)調(diào)用時,棧是如何變化的? 》。那么內(nèi)核棧是如何存放進(jìn)程描述符的呢?
內(nèi)核棧對于應(yīng)用程序是不可見的,因為它位于內(nèi)核空間中。在應(yīng)用程序執(zhí)行過程中,如果發(fā)生異常、中斷或系統(tǒng)調(diào)用的話,應(yīng)用程序會被暫停,系統(tǒng)進(jìn)入內(nèi)核態(tài),轉(zhuǎn)去執(zhí)行異常響應(yīng)等代碼,這個時候所使用的棧就是內(nèi)核棧。
為了節(jié)省空間,linux把內(nèi)核棧和緊挨著task_struct的thread_info放在一起,如上所示,thread_info中存放了進(jìn)程/線程(內(nèi)核不大區(qū)分進(jìn)程與線程)的一些數(shù)據(jù),其中包括指向task_struct結(jié)構(gòu)的指針。數(shù)組stack即內(nèi)核棧,stack占據(jù)8K/4K(依配置不同)空間。
union thread_union {#ifndef CONFIG_THREAD_INFO_IN_TASK struct thread_info thread_info;#endif unsigned long stack[THREAD_SIZE/sizeof(long)];};最后
到這里應(yīng)該已經(jīng)了解了一個程序如何轉(zhuǎn)換為進(jìn)程,內(nèi)核如何描述進(jìn)程,又如何存儲進(jìn)程,當(dāng)然還有很多關(guān)于進(jìn)程的描述沒有介紹,比如進(jìn)程的調(diào)度,優(yōu)先級,內(nèi)存管理等等,這些會在以后的文章里單獨分開詳細(xì)介紹。但這些所有的信息都存儲在今天的主角里——task_struct。
總結(jié)
以上是生活随笔為你收集整理的acl在内核里的位置_Linux 进程在内核眼中是什么样子的?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VBA-PPT
- 下一篇: android 获取网卡mac_Java