linux 上下文切换时对用户task和内核task区别对待——针对fpu

linux 5.10.8,本文以(上下文切换时,用户态task和内核task对fpu的load/store的区别)为主线

关于pthread和kthread的说明

  pthread时os对外提供的POSIX接口,并不是linux的概念。用户态程序可以调用pthread的接口创建、运行和销毁用户态线程。在下面的内容中,用pthread表示用户态线程,用kthread表示内核线程。在linux中,用户态线程和内核线程都是用struct task_struct表示的。

和kthread/pthread区别对待相关的数据结构

  linux中的TCB是task_struct,定义在文件./include/linux/sched.h中,和调度时和kthread和pthread区别对待相关的域如下:

struct task_struct {
   
    /* ... */
    struct thread_info  thread_info;
    /* ... */
    /* Per task flags (PF_*), defined further below: */
    unsigned int   flags;
    /* ... */
    struct mm_struct  *mm;
    struct mm_struct  *active_mm;
    /* ... */
}

/*
 * Per process flags
 */
#define PF_IDLE   0x00000002 /* I am an IDLE thread */
#define PF_EXITING  0x00000004 /* Getting shut down */
#define PF_VCPU   0x00000010 /* I'm a virtual CPU */
#define PF_WQ_WORKER  0x00000020 /* I'm a workqueue worker */
#define PF_FORKNOEXEC  0x00000040 /* Forked but didn't exec */
#define PF_MCE_PROCESS  0x00000080      /* Process policy on mce errors */
#define PF_SUPERPRIV  0x00000100 /* Used super-user privileges */
#define PF_DUMPCORE  0x00000200 /* Dumped core */
#define PF_SIGNALED  0x00000400 /* Killed by a signal */
#define PF_MEMALLOC  0x00000800 /* Allocating memory */
#define PF_NPROC_EXCEEDED 0x00001000 /* set_user() noticed that RLIMIT_NPROC was exceeded */
#define PF_USED_MATH  0x00002000 /* If unset the fpu must be initialized before use */
#define PF_USED_ASYNC  0x00004000 /* Used async_schedule*(), used by module init */
#define PF_NOFREEZE  0x00008000 /* This thread should not be frozen */
#define PF_FROZEN  0x00010000 /* Frozen for system suspend */
#define PF_KSWAPD  0x00020000 /* I am kswapd */
#define PF_MEMALLOC_NOFS 0x00040000 /* All allocation requests will inherit GFP_NOFS */
#define PF_MEMALLOC_NOIO 0x00080000 /* All allocation requests will inherit GFP_NOIO */
#define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */
#define PF_KTHREAD  0x00200000 /* I am a kernel thread */
#define PF_RANDOMIZE  0x00400000 /* Randomize virtual address space */
#define PF_SWAPWRITE  0x00800000 /* Allowed to write to swap */
#define PF_MEMSTALL  0x01000000 /* Stalled due to lack of memory */
#define PF_UMH   0x02000000 /* I'm an Usermodehelper process */
#define PF_NO_SETAFFINITY 0x04000000 /* Userland is not allowed to meddle with cpus_mask */
#define PF_MCE_EARLY  0x08000000      /* Early kill for mce process policy */
#define PF_MEMALLOC_NOCMA 0x10000000 /* All allocation request will have _GFP_MOVABLE cleared */
#define PF_IO_WORKER  0x20000000 /* Task is an IO worker */
#define PF_FREEZER_SKIP  0x40000000 /* Freezer should not count it as freezable */
#define PF_SUSPEND_TASK  0x80000000      /* This thread called freeze_processes() and should not be frozen */

  flag字段是task的标志位,标志位所有的信息如上所示。其中PF_KTHREAD标志位置1表示task是一个kthread。

  struct mm_struct是记录用户虚拟地址空间的数据结构。对于内核线程,mmNULL。由于内核线程之前可能是任何用户层进程在执行,故用户空间部分的内容本质上是随机的,内核线程决不能修改其内容,故将mm设置为NULL,同时如果切换出去的是用户进程,内核将原来进程的mm存放在新内核线程的active_mm中,因为某些时候内核必须知道用户空间当前包含了什么。在linux的代码实现中,这个字段和fpu的load/store没有关系,只是和kthread和pthread的区别对待有关系。

  thread_info 定义在./arch/x86/include/asm/thread_info.h的结构如下。它的flag字段设有32个标志位,如下所示。其中TIF_NEED_FPU_LOAD标志位置1,当task被调度到,在返回用户态之前,或者kernel需要用到fpu时,fpu会被加载到cpu上。

struct thread_info {
   
 unsigned long  flags;  /* low level flags */
 u32   status;  /* thread synchronous flags */
};

/*
 * thread information flags
 * - these are process sta
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值