成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Linux 對進程的描述

系統 Linux
進程是操作系統種調度的實體,對進程擁有資源的描述稱為進程控制塊(PCB, Process Contrl Block)。

[[406262]]

進程是操作系統種調度的實體,對進程擁有資源的描述稱為進程控制塊(PCB, Process Contrl Block)。

通過 task_struct 描述進程

內核里,通過 task_struct 結構體來描述一個進程,稱為進程描述符 (process descriptor),它保存著支撐一個進程正常運行的所有信息。task_struct 結構體內容太多,這里只列出部分成員變量,感興趣的讀者可以去源碼 include/linux/sched.h頭文件查看。

  1. struct task_struct { 
  2.  
  3. #ifdef CONFIG_THREAD_INFO_IN_TASK 
  4.   /* 
  5.    * For reasons of header soup (see current_thread_info()), this 
  6.    * must be the first element of task_struct. 
  7.    */ 
  8.   struct thread_info        thread_info; 
  9. #endif 
  10.   volatile long state; 
  11.   void *stack; 
  12.   ...... 
  13.   struct mm_struct *mm; 
  14.   ...... 
  15.   pid_t pid; 
  16.   ...... 
  17.   struct task_struct *parent; 
  18.   ...... 
  19.   char comm[TASK_COMM_LEN]; 
  20.   ...... 
  21.   struct files_struct *files; 
  22.   ...... 
  23.   struct signal_struct *signal; 

task_struct 中的主要信息分類:

1.標示符:描述本進程的唯一標識符 pid,用來區別其他進程。

2.狀態:任務狀態,退出代碼,退出信號等

3.優先級:相對于其他進程的優先級

4.程序計數器:程序中即將被執行的下一條指令的地址

5.內存指針:包括程序代碼和進程相關數據的指針,還有和其他進程共享的內存塊的指針

6.上下文數據:進程執行時處理器的寄存器中的數據

7.I/O狀態信息:包括顯示的I/O請求,分配的進程I/O設備和進程使用的文件列表

8.記賬信息:可能包括處理器時間總和,使用的時鐘總和,時間限制,記帳號等

  • struct thread_info thread_info: 進程被調度執行的信息
  • volatile long state:-1是不運行的,=0是運行狀態,>0是停止狀態。下面是幾個比較重要的進程狀態以及它們之間的轉換流程。

  1. void *stack:指向內核棧的指針,內核通過 dup_task_struct 為每個進程都分配內核棧空間,并記錄在此。
  2. struct mm_struct *mm: 與進程地址空間相關的信息。

  • pid_t pid: 進程標識符
  • char comm[TASK_COMM_LEN]: 進程的名稱
  • struct files_struct *files: 打開的文件表
  • struct signal_struct *signal: 信號處理相關

task_struct, thread_info 和內核棧 sp 的關系

接著看下 thread_info 結構:

  1. struct thread_info { 
  2.         unsigned long           flags;          /* low level flags */ 
  3.         mm_segment_t            addr_limit;     /* address limit */ 
  4. #ifdef CONFIG_ARM64_SW_TTBR0_PAN 
  5.         u64                     ttbr0;          /* saved TTBR0_EL1 */ 
  6. #endif 
  7.         union { 
  8.                 u64             preempt_count;  /* 0 => preemptible, <0 => bug */ 
  9.                 struct { 
  10. #ifdef CONFIG_CPU_BIG_ENDIAN 
  11.                         u32     need_resched; 
  12.                         u32     count
  13. #else 
  14.                         u32     count
  15.                         u32     need_resched; 
  16. #endif 
  17.                 } preempt; 
  18.         }; 
  19. #ifdef CONFIG_SHADOW_CALL_STACK 
  20.         void                    *scs_base; 
  21.         void                    *scs_sp; 
  22. #endif 
  23. }; 

接著再來看下內核棧的定義:

  1. union thread_union { 
  2. #ifndef CONFIG_ARCH_TASK_STRUCT_ON_STACK 
  3.         struct task_struct task; 
  4. #endif 
  5. #ifndef CONFIG_THREAD_INFO_IN_TASK 
  6.         struct thread_info thread_info; 
  7. #endif 
  8.         unsigned long stack[THREAD_SIZE/sizeof(long)]; 
  9. }; 

當 CONFIG_THREAD_INFO_IN_TASK 這個配置打開的時候,則 thread_union 結構中只存在 stask 成員了。

內核在啟動的時候會在 head.S 里通過 __primary_switched 來做內核棧的初始化:

  1. SYM_FUNC_START_LOCAL(__primary_switched) 
  2.         adrp    x4, init_thread_union 
  3.         add     sp, x4, #THREAD_SIZE 
  4.         adr_l   x5, init_task 
  5.         msr     sp_el0, x5                      // Save thread_info 

將 init_thread_union 的地址保存到 x4,然后偏移 THREAD_SIZE 棧大小,用于初始化 sp。將 init_task 進程描述符地址賦值給 x5,并保存到 sp_el0。

下面再看下 init_thread_union 和 init_task 的定義:

  1. #include/linux/sched/task.h 
  2. extern union thread_union init_thread_union; 
  3.  
  4. #init/init_task.c 
  5. struct task_struct init_task 
  6.         __aligned(L1_CACHE_BYTES) 
  7. = { 
  8. #ifdef CONFIG_THREAD_INFO_IN_TASK 
  9.         .thread_info    = INIT_THREAD_INFO(init_task), 
  10.         .stack_refcount = REFCOUNT_INIT(1), 
  11. #endif 
  12. ..... 
  13.  }; 

故這三者的關系可以通過下圖描述:

如何獲取當前進程

內核中經常通過 current 宏來獲得當前進程對應的 struct task_sturct 結構,我們借助 current,結合上面介紹的內容,看下具體的實現。

  1. static __always_inline struct task_struct *get_current(void) 
  2.     unsigned long sp_el0; 
  3.   
  4.     asm ("mrs %0, sp_el0" : "=r" (sp_el0)); 
  5.   
  6.     return (struct task_struct *)sp_el0; 
  7.   
  8. #define current get_current() 

代碼比較簡單,可以看出通過讀取用戶空間棧指針寄存器 sp_el0 的值,然后將此值強轉成 task_struct 結構就可以獲得當前進程。(sp_el0 里存放的是 init_task,即 thread_info 地址,thread_info 又是在 task_sturct 的開始處,從而找到當前進程。)

 

責任編輯:武曉燕 來源: 人人都是極客
相關推薦

2009-12-17 14:43:47

紅旗Linux

2023-04-06 15:22:15

Linux進程系統

2020-02-07 18:16:01

進程線程底層原理

2010-05-26 15:03:51

2010-09-15 09:58:20

2010-07-19 18:04:23

SQL Server鎖

2009-11-13 09:28:35

2009-08-06 15:52:11

C#調用外部進程

2010-05-26 13:50:15

MySQL備份

2010-07-19 16:17:41

SQL Server聚

2010-04-27 16:18:26

Oracle數據字典

2010-05-28 11:14:39

MySQL全文索引限制

2010-09-08 13:31:24

2010-09-30 16:17:13

2010-09-08 15:10:48

2010-09-29 12:52:14

2011-03-30 11:28:31

SQL Server聚集索引

2010-08-06 14:52:13

DB2 9.7武器

2010-05-12 16:47:54

MySQL 中文亂碼

2010-03-29 13:55:26

Oracle Mult
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 曰韩一二三区 | 精品国产一区二区三区性色 | 久久久久久国产 | 日日干夜夜操天天操 | 国产中文字幕在线 | 四虎海外| 超碰91在线 | 成人免费观看男女羞羞视频 | 久久久精品一区二区三区 | 亚洲精品黄 | 一级特黄色毛片 | 久久亚洲高清 | 日日操视频 | 久久国产欧美日韩精品 | 亚洲黄色一区二区三区 | 岛国精品| caoporn国产 | 性高湖久久久久久久久aaaaa | 国产亚洲欧美日韩精品一区二区三区 | 国产精品视频一二三 | 国产一区二区三区四区 | 精品国产乱码久久久久久影片 | 五十女人一级毛片 | 亚洲精品日韩综合观看成人91 | 日韩欧美黄色 | 精品成人一区二区 | 亚洲 欧美 日韩在线 | 欧美日韩电影一区 | 亚洲精品成人网 | 天天澡天天狠天天天做 | 久久国产精品视频 | 久久久久久久久久毛片 | 97国产爽爽爽久久久 | 午夜午夜精品一区二区三区文 | 在线国产一区二区三区 | 欧美成人免费电影 | 久久午夜国产精品www忘忧草 | 欧洲av一区 | 99re热精品视频国产免费 | 一区二区三区av | 凹凸日日摸日日碰夜夜 |