linux current

本文详细解析了Linux内核中的task_struct数据结构,它是进程控制块(PCB),用于描述和管理进程状态、调度信息、进程间通信、上下文切换、内存管理等关键信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

尽管内核模块不象应用程序一样顺序执行, 内核做的大部分动作是代表一个特定进程的. 内核代码可以引用当前进程, 通过存取全局项 current, 它在 <asm/current.h> 中定义, 它产生一个指针指向结构 task_struct, 在 <linux/sched.h> 定义. current 指针指向当前在运行的进程. 在一个系统调用执行期间, 例如 open 或者 read, 当前进程是发出调用的进程. 内核代码可以通过使用 current 来使用进程特定的信息, 如果它需要这样.

实际上, current 不真正地是一个全局变量. 支持 SMP 系统的需要强迫内核开发者去开发一种机制, 在相关的 CPU 上来找到当前进程. 这种机制也必须快速, 因为对 current 的引用非常频繁地发生. 结果就是一个依赖体系的机制, 常常, 隐藏了一个指向 task_struct 的指针在内核堆栈内. 实现的细节对别的内核子系统保持隐藏, 一个设备驱动可以只包含 <linux/sched.h> 并且引用当前进程. 例如, 下面的语句打印了当前进程的进程 ID 和命令名称, 通过存取结构 task_struct 中的某些字段.
printk(KERN_INFO "The process is \"%s\" (pid %i)\n", current->comm, current->pid);
存于 current->comm
的命令名称是由当前进程执行的程序文件的基本名称( 截短到 15 个字符, 如果需要 ).

 

  在linux   中每一个进程都由task_struct   数据结构来定义.   task_struct就是我们通常所说的PCB.她是对进程控制的唯一手段也是最有效的手段.   当我们调用fork()   时,   系统会为我们产生一个task_struct结构.然后从父进程,那里继承一些数据,   并把新的进程插入到进程树中,   以待进行进程管理.因此了解task_struct的结构对于我们理解任务调度(在linux   中任务和进程是同一概念)的关键.在进行剖析task_struct的定义之前.   我们先按照我们的理论推一下它的结构.   1,   进程状态   ,将纪录进程在等待,运行,或死锁   2,   调度信息,   由哪个调度函数调度,怎样调度等   3,   进程的通讯状况   4,因为要插入进程树,必须有联系父子兄弟的指针,   当然是task_struct型   5,时间信息,   比如计算好执行的时间,   以便cpu   分配   6,标号   ,决定改进程归属   7,可以读写打开的一些文件信息   8,   进程上下文和内核上下文   9,处理器上下文   10,内存信息   因为每一个PCB都是这样的,   只有这些结构,   才能满足一个进程的所有要求.打开/include/linux/sched.h   找到task_struct   的定义   
   

  1.  struct   task_struct   {   /*   these   are   hardcoded   -   don't   touch   */   这里是一些硬件设置对程序原来说是透明的.   其中state   说明了该进程是否可以执行,还是可中断等信息.   Flage   是进程号,   在调用   fork()   时给出,addr_limit   是区分内核进程与普通进程在内存存放的位置不同    
  2. volatile   long   state; /*   -1   unrunnable,   0   runnable,  >0  stopped   */     
  3. unsigned   long   flags;   /*   per   process   flags,   defined   below   */   int   sigpending;     
  4. mm_segment_t   addr_limit;   /*   thread   address   space:   0-0xBFFFFFFF   for   user-thead   0-0xFFFFFFFF   for   kernel-thread   */     
  5. struct   exec_domain   *exec_domain;     
  6. long   need_resched;       
  7.   /*   various   fields   */   count   是   计数器   priorrity   是优先级     
  8. long   counter;     
  9. long   priority;     
  10. cycles_t   avg_slice;     
  11. /*   SMP   and   runqueue   state   */   为多处理机定义的变量.    
  12. int   has_cpu;     
  13. int   processor;     
  14. int   last_processor;     
  15. int   lock_depth;   /*   Lock   depth.   We   can   context   switch   in   and   out   of   holding   a   syscall   kernel   lock...   */    
  16. 为了在进程树中排序,   定义的父子,兄弟指针    
  17. struct   task_struct   *next_task,   *prev_task;     
  18. struct   task_struct   *next_run,   *prev_run;       
  19.   /*   task   state   */   定义可   task   运行的状态,   以及信号     
  20. struct   linux_binfmt   *binfmt;     
  21. int   exit_code,   exit_signal;     
  22. int   pdeath_signal;   /*   The   signal   sent   when   the   parent   dies   */   /*   定义可进程的用户号,用户组以及进程组*/     
  23. unsigned   long   personality;     
  24. int   dumpable:1;     
  25. int   did_exec:1;     
  26. pid_t   pid;     
  27. pid_t   pgrp;     
  28. pid_t   tty_old_pgrp;     
  29. pid_t   session;     
  30. /*   boolean   value   for   session   group   leader   */    
  31. 是不是进程组的头文件     
  32. int   leader;     
  33. /*    
  34. *   pointers   to   (original)   parent   process,   youngest   child,   younger   sibling,    
  35. *   older   sibling,   respectively.   (p->father   can   be   replaced   with   *   p->p_pptr->pid)   
  36. */     
  37. 父子进程的一些指针     
  38. struct   task_struct   *p_opptr,   *p_pptr,   *p_cptr,   *p_ysptr,   *p_osptr;       
  39.   /*   PID   hash   table   linkage.   */   在调度中用的一些hash   表     
  40. struct   task_struct   *pidhash_next;     
  41. struct   task_struct   **pidhash_pprev;       
  42.   /*   Pointer   to   task[]   array   linkage.   */     
  43. struct   task_struct   **tarray_ptr;       
  44. struct   wait_queue   *wait_chldexit;   /*   for   wait4()   等待队列   */   struct   semaphore   *vfork_sem;   /*   for   vfork()   */     
  45. unsigned   long   policy,   rt_priority;     
  46. unsigned   long   it_real_value,   it_prof_value,   it_virt_value;     
  47. 进程的性质因为实时进程与普通进程的调度算法不一样所以应有变量区分     
  48. 下面是进程的一些时间信息     
  49. unsigned   long   it_real_incr,   it_prof_incr,   it_virt_incr;     
  50. struct   timer_list   real_timer;     
  51. struct   tms   times;    
  52. unsigned   long   start_time;     
  53. long   per_cpu_utime[NR_CPUS],   per_cpu_stime[NR_CPUS];定义了时间片的大小     
  54. /*   mm   fault   and   swap   info:   this   can   arguably   be   seen   as   either   mm-specific   or   thread-specific   */     
  55. 内存信息     
  56. unsigned   long   min_flt,   maj_flt,   nswap,   cmin_flt,   cmaj_flt,   cnswap;   int   swappable:1;     
  57. /*   process   credentials   */     
  58. uid_t   uid,euid,suid,fsuid;     
  59. gid_t   gid,egid,sgid,fsgid;     
  60. int   ngroups;     
  61. gid_t   groups[NGROUPS];     
  62. kernel_cap_t   cap_effective,   cap_inheritable,   cap_permitted;     
  63. struct   user_struct   *user;     
  64. 以下英文注释很清楚     
  65. /*   limits   */     
  66. struct   rlimit   rlim[RLIM_NLIMITS];     
  67. unsigned   short   used_math;     
  68. char   comm[16];   /*   file   system   info   */     
  69. int   link_count;     
  70. struct   tty_struct   *tty;   /*   NULL   if   no   tty   */     
  71. /*   ipc   stuff   */       
  72. struct   sem_undo   *semundo;     
  73. struct   sem_queue   *semsleeping;     
  74. /*   tss   for   this   task   */     
  75. struct   thread_struct   tss;    
  76. /*   filesystem   information   */     
  77. struct   fs_struct   *fs;     
  78. /*   open   file   information   */     
  79. struct   files_struct   *files;    
  80. /*   memory   management   info   */     
  81. struct   mm_struct   *mm;       
  82.   /*   signal   handlers   */     
  83. spinlock_t   sigmask_lock;    
  84. /*   Protects   signal   and   blocked   */     
  85. struct   signal_struct   *sig;   sigset_t   signal,   blocked;     
  86. struct   signal_queue   *sigqueue,   **sigqueue_tail;     
  87. unsigned   long   sas_ss_sp;     
  88. size_t   sas_ss_size;     
  89. };     
 struct   task_struct   {   /*   these   are   hardcoded   -   don't   touch   */   这里是一些硬件设置对程序原来说是透明的.   其中state   说明了该进程是否可以执行,还是可中断等信息.   Flage   是进程号,   在调用   fork()   时给出,addr_limit   是区分内核进程与普通进程在内存存放的位置不同  
volatile   long   state; /*   -1   unrunnable,   0   runnable,  >0  stopped   */   
unsigned   long   flags;   /*   per   process   flags,   defined   below   */   int   sigpending;   
mm_segment_t   addr_limit;   /*   thread   address   space:   0-0xBFFFFFFF   for   user-thead   0-0xFFFFFFFF   for   kernel-thread   */   
struct   exec_domain   *exec_domain;   
long   need_resched;     
  /*   various   fields   */   count   是   计数器   priorrity   是优先级   
long   counter;   
long   priority;   
cycles_t   avg_slice;   
/*   SMP   and   runqueue   state   */   为多处理机定义的变量.  
int   has_cpu;   
int   processor;   
int   last_processor;   
int   lock_depth;   /*   Lock   depth.   We   can   context   switch   in   and   out   of   holding   a   syscall   kernel   lock...   */  
为了在进程树中排序,   定义的父子,兄弟指针  
struct   task_struct   *next_task,   *prev_task;   
struct   task_struct   *next_run,   *prev_run;     
  /*   task   state   */   定义可   task   运行的状态,   以及信号   
struct   linux_binfmt   *binfmt;   
int   exit_code,   exit_signal;   
int   pdeath_signal;   /*   The   signal   sent   when   the   parent   dies   */   /*   定义可进程的用户号,用户组以及进程组*/   
unsigned   long   personality;   
int   dumpable:1;   
int   did_exec:1;   
pid_t   pid;   
pid_t   pgrp;   
pid_t   tty_old_pgrp;   
pid_t   session;   
/*   boolean   value   for   session   group   leader   */  
是不是进程组的头文件   
int   leader;   
/*   
*   pointers   to   (original)   parent   process,   youngest   child,   younger   sibling,   
*   older   sibling,   respectively.   (p->father   can   be   replaced   with   *   p->p_pptr->pid)  
*/   
父子进程的一些指针   
struct   task_struct   *p_opptr,   *p_pptr,   *p_cptr,   *p_ysptr,   *p_osptr;     
  /*   PID   hash   table   linkage.   */   在调度中用的一些hash   表   
struct   task_struct   *pidhash_next;   
struct   task_struct   **pidhash_pprev;     
  /*   Pointer   to   task[]   array   linkage.   */   
struct   task_struct   **tarray_ptr;     
struct   wait_queue   *wait_chldexit;   /*   for   wait4()   等待队列   */   struct   semaphore   *vfork_sem;   /*   for   vfork()   */   
unsigned   long   policy,   rt_priority;   
unsigned   long   it_real_value,   it_prof_value,   it_virt_value;   
进程的性质因为实时进程与普通进程的调度算法不一样所以应有变量区分   
下面是进程的一些时间信息   
unsigned   long   it_real_incr,   it_prof_incr,   it_virt_incr;   
struct   timer_list   real_timer;   
struct   tms   times;  
unsigned   long   start_time;   
long   per_cpu_utime[NR_CPUS],   per_cpu_stime[NR_CPUS];定义了时间片的大小   
/*   mm   fault   and   swap   info:   this   can   arguably   be   seen   as   either   mm-specific   or   thread-specific   */   
内存信息   
unsigned   long   min_flt,   maj_flt,   nswap,   cmin_flt,   cmaj_flt,   cnswap;   int   swappable:1;   
/*   process   credentials   */   
uid_t   uid,euid,suid,fsuid;   
gid_t   gid,egid,sgid,fsgid;   
int   ngroups;   
gid_t   groups[NGROUPS];   
kernel_cap_t   cap_effective,   cap_inheritable,   cap_permitted;   
struct   user_struct   *user;   
以下英文注释很清楚   
/*   limits   */   
struct   rlimit   rlim[RLIM_NLIMITS];   
unsigned   short   used_math;   
char   comm[16];   /*   file   system   info   */   
int   link_count;   
struct   tty_struct   *tty;   /*   NULL   if   no   tty   */   
/*   ipc   stuff   */     
struct   sem_undo   *semundo;   
struct   sem_queue   *semsleeping;   
/*   tss   for   this   task   */   
struct   thread_struct   tss;  
/*   filesystem   information   */   
struct   fs_struct   *fs;   
/*   open   file   information   */   
struct   files_struct   *files;  
/*   memory   management   info   */   
struct   mm_struct   *mm;     
  /*   signal   handlers   */   
spinlock_t   sigmask_lock;  
/*   Protects   signal   and   blocked   */   
struct   signal_struct   *sig;   sigset_t   signal,   blocked;   
struct   signal_queue   *sigqueue,   **sigqueue_tail;   
unsigned   long   sas_ss_sp;   
size_t   sas_ss_size;   
};   


在分析完   这个结构之后,   还有很多问题要想,   也许不能读   但框架要搞好.需要向的问题有以下几个   1,在task_struct   中用的常量在那里定义呢,   如最大进程个数,   最多支持的cpu   个数,等等   2,在调用fork()   时,   系统是分配一块内存   会是这样么   malloc(1,sizeof(struct   task_struck))   拷贝一些变量,还是和父进程共用一部分内存.malloc   函数怎么实现(在内存管理那一部分,但此处我认为不能不想)   3,.对于线程来说,   又如何实现呢?   4,   调度策略函数schedule()有几种形势,   时间片轮转,   抢占式,优先级抢占式,   多级反馈制.除了时间片轮转外都要对进程树进行遍历,(对于实时进程的fifo机制不用)linux   是怎样保证了高效呢?如果把最大线成数修改,   效率会不会降低   5,   进程通讯用到的管道,信号结构如何
### Linux Kernel `get_current` Usage and Explanation In the context of the Linux kernel, obtaining information about the currently executing process is a common requirement. The macro or function used for this purpose is often referred to as `get_current`. This functionality allows developers to access details related to the current task or thread within the kernel space. The implementation of `get_current` leverages per-CPU variables which are designed specifically for scenarios where each processor has its own copy of certain data structures[^1]. By using these Per-CPU variables, accessing the current task structure becomes efficient because it avoids contention between CPUs in an SMP (Symmetric MultiProcessing) environment. Here’s how one might use `get_current`: ```c #include <linux/sched.h> struct task_struct *current_task; // Obtain pointer to the current running task. current_task = get_current(); ``` This code snippet demonstrates retrieving a pointer (`current_task`) pointing to the `task_struct`, representing the currently executing process on that particular CPU core at runtime. When dealing with preemption-aware kernels, ensuring correct behavior under all circumstances requires careful handling when referencing global state like the current task. Therefore, mechanisms such as RCU (Read-Copy Update), mentioned briefly earlier, play crucial roles alongside Per-CPU storage solutions provided by the operating system itself. Understanding what happens during a kernel oops can also provide insight into why proper management of tasks through constructs like `get_current` matters significantly for stability reasons. For instance, if there were issues while trying to manipulate pointers associated with the active task without adequate safeguards, encountering errors similar to those described could occur[^2]: An example output from a kernel panic includes various pieces of diagnostic information including but not limited to: - **Oops**: Indicates type of fault encountered; - **Page Error Code**: Describes nature of memory violation detected; - **Dead Counters & Affected CPU ID** : Tracks frequency and location specifics regarding failures across multiple cores; - **Process Identifier along with Command Name**: Identifies offending application causing instability; - **Instruction Pointer Address**: Points exactly where things went wrong inside executable instructions sequence being processed. --related questions-- 1. How does the scheduler manage processes efficiently? 2. What role do spinlocks play in managing concurrent operations safely? 3. Can you explain more about high-resolution timers' impact on real-time performance? 4. In what ways can improper usage of `get_current` lead to kernel panics?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值