首先明确一个概念,Linux系统中甚至没有真正的线程。不过,可以认为Linux是系统的线程是内核线程,所有调度是基于线程的。

1、线程分类

一个进程由于其运行空间的不同, 从而有内核线程用户进程的区分,进程和线程都被维护为一个task_struct结构,线程和进程被同等对待来进行调度

  • 内核线程运行在内核空间, 之所以称之为线程是因为它没有虚拟地址空间, 只能访问内核的代码和数据, 而用户进程则运行在用户空间, 但是可以通过中断, 系统调用等方式从用户态陷入内核态
  • 用户进程运行在用户空间上, 而一些通过共享资源实现的一组进程我们称之为线程组, Linux下内核其实本质上没有线程的概念, Linux下线程其实上是与其他进程共享某些资源的进程而已。但是我们习惯上还是称他们为线程或者轻量级进程

Linux将线程区分为3类:

(1)实时先入先出。

(2)实时轮转。

(3)分时。

实时先入先出有最高的优先级,不会被其他线程抢占,除非是另外一个刚刚准备好的且优先级更高的实时先入先出线程。

实时轮转线程与实时先入先出类似,不过有一个轮转体系,即分配一个时间片,时间到了就可以被抢占。时间片消耗完就进入实时轮转线程列表的末尾。其实,这两种都不是真的实时,因为执行的最后期限无法确定,只是比分时线程有更高的优先级。

实时线程的优先级从0-99,0是实时线程的最高优先级,99是实时线程的最低优先级。

传统的非实时线程,优先级从100-139。Linux系统根据非实时线程的优先级分配时间量。

2、调度队列和多CPU负载均衡

每个CPU有自己的调度队列,包括两个数组:活动的和过期失效的。每个数组包括了140个链表头,对应140个优先级的链表。

调度器从正在活动数组中选择一个优先级最高的任务,如果时间片耗尽失效,就加入到过期失效数组中。如果进程在时间片内被阻塞,那么在时间片失效之前,等待的事件发生就可以继续运行,放回到正在活动的数组中。如果活动数组没有任务了,调度器交换指针,使得活动数组和失效数组调换。

不同的优先级被赋予不同的时间片长度,优先级越高的进程,时间片越长。

如果每个CPU调度队列的大小很不均衡,就会触发内核的load_balance函数。这个函数会把某个CPU处理器上过多的进程移到runqueue元素相对少的CPU处理器上。

3、线程优先级

Linux采用静态优先级动态优先级结合的方式。Linux采用了奖惩机制,目的在于奖励互动进程以及惩罚占用CPU的进程。一个进程初始被赋予了一个优先级,耗尽和阻塞会改变nice值,活动与过期进程转换时,动态改变进程优先级。

另外,对于多核处理器,运行队列数据结构与某一个处理器相对应,调度器尽量进行亲和调度,即将之前在某个处理器上运行过的任务再次调入该处理器。

调度器只考虑可以运行的任务,不可运行的任务和正在等待各种I/O操作的或内核事件的任务被放入等待队列中。每一种等待某种事件的任务组成一个等待队列。等待队列的头部包含一个指向任务链表的指针及一个自旋锁。

4、CPU时间片

内核在微观上,把CPU的运行时间分成许多分,然后安排给各个进程轮流运行,造成宏观上所有的进程仿佛同时在执行。双核CPU,实际上最多只能有两个进程在同时运行,大家在top、vmstat命令里看到的正在运行的进程,并不是真的在占有着CPU哈。

所以,一些设计良好的高性能进程,比如nginx,都是实际上有几颗CPU,就配几个工作进程,道理就在这。比如你的服务器有8颗CPU,那么nginx worker应当只有8个,当你多于8个时,内核可能会放超过多个nginx worker进程到1个runqueue里,会发生什么呢?就是在这颗CPU上,会比较均匀的把时间分配给这几个nginx worker,每个worker进程运行完一个时间片后,内核需要做进程切换,把正在运行的进程上下文保存下来。假设内核分配的时间片是100ms,做进程切换的时间是5ms,那么进程性能下降还是很明显的,跟你配置的worker有关,越多下降得越厉害。

当然,这是跟nginx的设计有关的。nginx是事件驱动的全异步进程,本身设计上就几乎不存在阻塞和中断,nginx的设计者就希望每一个nginx worker可以独占CPU的几乎全部时间片,这点就是nginx worker数量配置的依据所在。

当然,实际的运行进程里,大部分并不是nginx这种希望独占CPU全部时间片的进程,许多进程,比如vi,它在很多时间是在等待用户输入,这时vi在等待IO中断,是不占用时间片的,内核面对多样化的进程,就需要技巧性的分配CPU时间片了。

 
 参考:
https://www.cnblogs.com/lustar/p/7716165.html

【Linux内核】CPU和线程的更多相关文章

  1. LINUX内核CPU负载均衡机制【转】

    转自:http://oenhan.com/cpu-load-balance 还是神奇的进程调度问题引发的,参看Linux进程组调度机制分析,组调度机制是看清楚了,发现在重启过程中,很多内核调用栈阻塞在 ...

  2. linux内核中创建线程方法

    1.头文件 #include <linux/sched.h> //wake_up_process() #include <linux/kthread.h> //kthread_ ...

  3. linux内核--进程与线程

    http://blog.csdn.net/yusiguyuan/article/details/12154823 在<linux内核设计与实现>中第三章讲解了进程管理,在关于进程和线程的概 ...

  4. linux内核中创建线程方法【转】

    本文转载自:https://www.cnblogs.com/Ph-one/p/6077787.html 1.头文件 #include <linux/sched.h> //wake_up_p ...

  5. Linux内核:kthread_create(线程)、SLEEP_MILLI_SEC

    转自:http://blog.csdn.net/guowenyan001/article/details/39230181 一.代码 #include <linux/module.h> # ...

  6. Linux内核剖析 之 进程简单介绍

    1.概念 1.1  什么是进程?     进程是程序运行的一个实例.能够看作充分描写叙述程序已经运行到何种程度的数据结构的汇集.     从内核观点看.进程的目的就是担当分配系统资源(CPU时间,内存 ...

  7. Linux内核设计基础(十)之内核开发与总结

    (1)Linux层次结构: (2)Linux内核组成: 主要由进程调度(SCHED).内存管理(MM).虚拟文件系统(VFS).网络接口(NET)和进程间通信(IPC)等5个子系统组成. (3)与Un ...

  8. 《Linux内核设计与实现》第一二章笔记

    第一章 linux内核简介 每个处理器在任何时间点上的活动必然概括为下列三者: 运行于用户空间,执行用户进程 运行于内核空间,处于进程上下文,代表某个特定的进程执行 运行于内核空间,处于中断上下文,与 ...

  9. Linux内核分析 一二章读书笔记

    第一章 Linux内核简介 1.Unix (1)Unix系统很简洁 (2)在Unix中,所以东西都被当作文件对待,通过一套相同的系统调用接口来进行:open(),read(),write(),lsee ...

  10. 《LINUX内核设计与实现》第一、二章学习总结

    第一章 Linux内核简介 (一)Unix是一个强大.健壮和稳定的操作系统,特点是: Unix很简洁,仅仅提供几个几百个系统调用并且有一个非常明确的设计目的 在Unix中,所有的东西都被当作文件对待, ...

随机推荐

  1. 多线程 interrupt()方法

    java interrupt()方法只是设置线程的中断标记,当对处于阻塞状态的线程调用interrupt方法时(处于阻塞状态的线程是调用sleep, wait, join 的线程),会抛出Interr ...

  2. skywalking6.3.0安装(centos7.6)

    先安装好jdk8(略),经测试高于jdk8不支持. http://skywalking.apache.org/downloads/wget --no-check-certificate --no-co ...

  3. _nl_intern_locale_data: Assertion `cnt < (sizeof (_nl_value_type_LC_TIME) / sizeof (_nl_value_type_LC_TIME[0]))' failed

    在Ubuntu18上使用交叉编译工具,报这个错.研究之下发现,工具的绝对路径过长,ubuntu18对其优化,修改路径,导致报错. 使用命令:export LC_ALL=C

  4. Spark2.x(五十七):User capacity has reached its maximum limit(用户容量已达到最大限制)

    背景: 目前服务器资源是43个节点,每个节点配置信息如下:24VCores 64G yarn配置情况: yarn.scheduler.minimum-allocation-mb  单个容器可申请的最小 ...

  5. git远程版本回退

    本文为博主原创,未经允许不得转载: 之前在git提交版本时,发现将新开发的代码提交到了另一个分支上,为了不影响提交分支代码的 功能,需要回退到之前的版本. 在使用命令回退的时候,一直没有回退成功,有个 ...

  6. Microsoft Office Excel不能访问文件*.xls的解决方案

    Microsoft Office Excel不能访问文件‘xxxx.xls“可能的原因有:·文件名称或路径不存在,文件正被其他程序使用:您正要保存的工作簿与当前打开的工作簿同名. 解决方案 1.首先检 ...

  7. aligin-items与aligin-content的区别

    align-items 属性使用于所有的flex容器,它是用来设置每个flex元素在侧轴上的默认对齐方式 aligin-items 与align-content有相同的功能,不过不同点是它是用来让每一 ...

  8. 树莓派插入U盘自动拷贝系统日志到U盘或通过U盘升级程序

    注意,U盘用Fat32格式,NTFS格式的话,需要在Linux另外安装相应驱动. 可通过udev实现如题的功能. 在/etc/udev/rules.d/目录下新建规则文件98-logcopy.rule ...

  9. PHP命令行参数

    原文地址:http://php.swoole.com/wiki/PHP%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0   PHP命令行参数 目录 [隐藏]  ...

  10. jinja 模板渲染路径坑

    路径中不能用上一级目录../