linux内核源码分析进程的管理与调度

2023-11-10


一、进程管理

进程描写叙述符及任务结构

进程存放在叫做任务队列(tasklist)的双向循环链表中。链表中的每一项包括一个详细进程的全部信息,类型为task_struct,称为进程描写叙述符(process descriptor),该结构定义在<linux/sched.h>文件里。
task_struct数据结构主要成员内核源码分析在这里插入图片描述
Linux通过slab分配器分配task_struct结构,这样能达到对象复用和缓存着色(cache coloring)的目的。还有一方面,为了避免使用额外的寄存器存储专门记录,让像x86这样寄存器较少的硬件体系结构仅仅要通过栈指针就能计算出task_struct的位置,该结构为thread_info,在文件<asm/thread_info.h>中定义。
Linux中能够用ps命令查看全部进程的信息。

进程状态

task_struct中的state描写叙述进程的当前状态。进程的状态一共同拥有5种(其中,睡眠状态又可细分为轻度睡眠,中度睡眠,深度睡眠),而进程必定处于当中一种状态:
(1)TASK_RUNNING(运行)——进程是可运行的,它或者正在运行,或者在运行队列中等待运行。这是进程在用户空间中运行唯一可能的状态;也能够应用到内核空间中正在运行的进程。
(2)TASK_INTERRUPTIBLE(可中断)——进程正在睡眠(也就是说它被堵塞)等待某些条件的达成。一旦这些条件达成,内核就会把进程状态设置为执行,处于此状态的进程也会由于接收到信号而提前被唤醒并投入执行。
(3)TASK_UNINTERRUPTIBLE(不可中断)——除了不会由于接收到信号而被唤醒从而投入执行外,这个状态与可打断状态同样。这个状态通常在进程必须在等待时不受干扰或等待事件非常快就会发生时出现。由于处于此状态的任务对信号不作响应,所以较之可中断状态,使用得较少。
(4)TASK_ZOMBIE(僵死)——该进程已经结束了,可是其父进程还没有调用wait4()系统调用。为了父进程可以获知它的消息,子进程的进程描写叙述符仍然被保留着。一旦父进程调用了wait4(),进程描写叙述符就会被释放。
(5)TASK_STOPPED(停止)——进程停止执行,进程没有投入执行也不能投入执行。通常这样的状态发生在接收到SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU等信号的时候。此外,在调试期间接收到不论什么信号,都会使进程进入这样的状态。
须要调整进程的状态,最好使用set_task_state(task, state)函数,在必要的时候,它会设置内存屏障来强制其它处理器作又一次排序(SMP)。

进程的各个状态之间的转化图如下所示:
在这里插入图片描述

进程创建

在Linux系统中,全部的进程都是PID为1的init进程的后代(在Linux内核中,新进程是从一个已经存在的进程复制出来的,内核使用静态数据结构造出0号内核线程, 0号内核线程分叉生成1号内核线程和2号内核线程(kthreadd 线程)。1号内核线程完成初始化以后装载用户程序,变成1号进程,其他进程都是1号进程或者它的子孙进程分叉生成的;)。内核在系统启动的最后阶段启动init进程。该进程读取系统的初始化脚本(initscript)并运行其它的相关程序,终于完毕系统启动的整个进程。

Linux提供两个函数去处理进程的创建和运行:fork()和exec()。首先,fork()通过拷贝当前进程创建一个子进程。子进程与父进程的差别只在于PID(每一个进程唯一),PPID(父进程的PID)和某些资源和统计量(比如挂起的信号)。exec()函数负责读取可运行文件并将其加载地址空间開始运行。
fork()使用写时拷贝(copy-on-write)页实现。内核在fork进程时不复制整个进程地址空间,让父进程和子进程共享同一个拷贝,当须要写入时,数据才会被复制,使各进程拥有自己的拷贝。在页根本不会被写入的情况下(fork()后马上exec()),fork的实际开销仅仅有复制父进程的页表以及给子进程创建唯一的task_struct。

创建进程的fork()函数实际上终于是调用clone()函数(clone (克隆):可以精确地控制子进程和父进程共享哪些资源。这个系统调用的主要用处是可供pthread库用来创建线程。股clone是功能最齐全的函数,参数多使用复杂,fork是clone的简化函数)。 创建线程和进程的步骤一样,仅仅是终于传给clone()函数的參数不同。比方,通过一个普通的fork来创建进程,相当于:clone(SIGCHLD, 0);创建一个和父进程共享地址空间,文件系统资源,文件描写叙述符和信号处理程序的进程,即一个线程:clone(CLONE_VM | CLONE_FS | CLONE_FILES |CLONE_SIGHAND, 0)。

在内核中创建的内核线程与普通的进程之间还有个主要差别在于:内核线程没有独立的地址空间,它们仅仅能在内核空间执行。

fork和vfork的差别

fork()与vfock()都是创建一个进程,那他们有什么差别呢?总结有下面三点差别:
1.fork ():子进程拷贝父进程的数据段,代码段
vfork ( ):子进程与父进程共享数据段
2.fork ()父子进程的运行次序不确定
vfork 保证子进程先执行,在调用exec 或exit 之前与父进程数据是共享的,在它调用exec
或exit 之后父进程才可能被调度执行。
3. vfork ()保证子进程先执行,在她调用exec 或exit 之后父进程才可能被调度执行。假设在
调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。
注意: vfork用于创建子进程,之后子进程立即调用execve以装载新程序的情况,为了避免复制物理页,父进程会睡眠等待子进程装载新程序。现在fork采用了写时复制技术,vfork 失去了速度优势,已经被废弃。

进程终止

进程在执行结束,或接受到它既不能处理也不能忽略的信号,或异常时,都会被终结。此时,依靠do_exit()(在kernel/exit.c文件里)把与进程相关联的全部资源都被释放掉(如果进程是这些资源的唯一使用者)。至此,与进程相关的全部资源都被释放掉了。进程不可执行(实际上也没有地址空间让它执行)并处于TASK_ZOMBIE状态。它占用的全部资源就是内核栈、thread_info和task_struct。此时进程存在的唯一目的就是想它的父进程提供信息。在父进程获得已终结的子进程的信息后,或者通知内核它并不关注那些信息后,子进程持有的task_struct等剩余内存才被释放。

二、进程调度

什么是调度

如今的操作系统都是多任务的,为了能让很多其它的任务能同一时候在系统上更好的执行,须要一个管理程序来管理计算机上同一时候执行的各个任务(也就是进程)。

这个管理程序就是调度程序,它的功能说起来非常easy:

1.决定哪些进程执行,哪些进程等待

2.决定每一个进程执行多长时间

此外,为了获得更好的用户体验,执行中的进程还可以马上被其它更紧急的进程打断。总之,调度是一个平衡的过程。一方面,它要保证各个执行的进程可以最大限度的使用CPU(即尽量少的切换进程,进程切换过多,CPU的时间会浪费在切换上);还有一方面,保证各个进程能公平的使用CPU(即防止一个进程长时间独占CPU的情况)。

三、策略

I/O消耗型和处理器消耗型的进程

I/O消耗型进程:大部分时间用来提交I/O请求或是等待I/O请求,常常处于可执行状态,但执行时间短,等待请求过程时处于堵塞状态。如交互式程序。
处理器消耗型进程:时间大都用在执行代码上,除非被抢占否则一直不停的执行。
调度策略要在:进程响应迅速(响应时间短)和最大系统利用率(高吞吐量)之间寻找平衡。

Linux为了保证交互式应用,所以对进程的对应做了优化,更倾向于优先调度I/O消耗型进程。

进程优先级

调度算法中最主要的一类就是基于优先级的调度。这是一种依据进程的价值和其对处理器时间的需求来对进程分级的想法。优先级高的进程先执行,低的后执行,同样优先级的进程按轮转方式进行调度。
Linux依据以上思想实现了一种基于动态优先级的调度方法。一開始,该方法先设置主要的优先级,然而它同意调度程度依据须要来加、减优先级。比如,假设一个进程在I/O等待上耗费的时间多于其执行时间,那么该进程明显属于I/O消耗型,它的优先级会被动态提高。相反,处理器消耗型进程的优先级会被动态减少。
Linux内核提供两组独立的优先级范围。第一种是nice值,范围从-20到+19,默认值是0。nice值越大优先级越低。另外一种是实时优先级,其值可配置,范围从0到99,不论什么实时进程的优先级都高于普通的进程。

时间片

时间片是一个数值,它表明进程在被抢占前所能持续执行的时间,I/O消耗型不须要长的时间片,而处理器消耗型的进程则希望越长越好。时间片的大小设置并不简单,设大了,系统响应变慢(调度周期长);设小了,进程频繁切换带来的处理器消耗。
Linux调度程序提高交互程序的优先级,让它们运行得更频繁。于是,调度程序提供了比較长的默认时间片给交互程序。此外,Linux调度程序还能依据进程的优先级动态调整分配给它的时间片。从而保证优先级高的进程,假定也是重要性高的进程,运行的频率高,运行时间长。通过实现这样一种动态调整优先级和时间片长度的机制,Linux调度性性能不但非常稳定并且也非常强健。

注意,进程并非一定非要一次就用完它全部的时间片,比如一个拥有100毫秒时间片的进程,能够通过反复调度,分5次每次20毫秒用完这些时间片。

当一个进程的时间耗尽时,就觉得到期了。没有时间片的进程不会再投入执行,除非等到其它全部的进程都耗尽了他们的时间片。那个时候,全部进程的时间片会被又一次计算。

进程抢占

Linux是抢占式的。当一个进程进入TASK_RUNNING状态,内核会检查它的优先级是否高于当前正在执行的进程。假设是这样,调度程序会被唤醒,抢占当前正在执行的进程并执行新的可执行进程。此外,当一个进程的时间片变为0时,它会被抢占,调度程序被唤醒以选择一个新的进程。

调度算法

可运行队列

调度程序中最主要的数据结构式运行队列(runqueue)。可运行队列是给定处理器上的可运行进程的链表,每一个处理器一个。每一个可投入运行的进程都唯一的归属于一个可运行队列。此外,可运行队列中还包括每一个处理器的调度信息。所以,可运行队列也是每一个处理器最重要的数据结构。
为了避免死锁,要锁住多个执行队列的代码必须总是依照相同的顺序获取这些锁:依照可执行队列地址从低向高的顺序。

优先级数组

每一个执行队列都有两个优先级数组,一个活跃的和一个过期的。优先级数组是一种可以提供O(1)级算法复杂度的数据结构。优先级数组使可执行处理器的每一种优先级都包括一个相应的队列,而这些队列包括相应优先级上的可执行进程链表。优先级数组还拥有一个优先级位图,当须要查找当前系统内拥有最高优先级的可执行进程时,它可以帮助提高效率。

又一次计算时间片

很多操作系统在全部进程的时间片都用完时,都採用一种显示的方法来计算时间片。典型的实现是循环訪问每一个进程,这样可能会耗费相当长的时间,最坏情况为O(N);重算时必须考锁的形式来保护任务队列和每一个进程描写叙述符,这样做会加剧对锁的争用;又一次计算时间的实际不确定。

活跃数组内的可运行队列上的进程都还有时间片剩余,而过期数组内的都耗尽了时间片。当一个进程的时间片耗尽时,它会被移至过期数组,但在此之前,时间片已经给它又一次计算好。又一次计算时间片变得很easy,仅仅要在活跃和过期数组之间来回切换,这是O(1)级调度程序的核心。

schedule()

选定下一个进程并切换到它去运行是通过schedule()函数实现的。当内核代码想要休眠时,会直接调用该函数,另外,假设有哪个进程将被抢占,那么该函数也会被唤起运行。schedule()函数独立于每一个处理器运行。

首先要在活动优先级数组中找到第一个被设置的位,该位对于这优先级最高的可运行进程。然后,调度程序选择这个级别链表里的有一个进程。这就是系统中优先级最高的可运行程序。假设被选中的进程不是当前进程,就进行上下文切换。

计算优先级和时间片

nice值之所以起名为静态优先级,是由于它从一開始由用户指定后,就不能改变。动态优先级通过一个关于静态优先级和进程交互性的函数关系计算而来。effective_prio()函数能够返回一个进程的动态优先级。这个函数以nice值为基数,再加上-5到+5之间的进程交互性的奖励或罚分。

怎么通过一些判断来获取准确反映进程究竟是I/O消耗型的还是处理器消耗型的。最明显的标准莫过于进程休眠的时间长短了。假设一个进程的大部分时间都在休眠,那么它就是I/O消耗型的。假设一个进程运行的时间比休眠的时间长,那它就是处理器消耗型的。

还有一方面,又一次计算时间片相对简单了。它仅仅要以静态优先级为基础就能够了。在一个进程创建的时候,新建的子进程和父进程均分父进程剩余的进程时间片。这种分配非常公平而且防止用户通过不断创建新进程来不停地获取时间片。task_timeslice()函数为给定任务返回一个新的时间片。时间片的计算仅仅须要把优先级按比例缩放,使其符合时间片的数值范围要求就能够了。进程的静态优先级越高,它每次运行得到的时间片就越长。

调度程序还提供了第二种机制以支持交互进程:假设一个进程的交互性很强,那么当它时间片用完后,它会被放置到活动数组而不是过期数组中。

睡眠与唤醒

休眠(被堵塞)的进程处于一个特殊的不可运行状态。进程把它自己标记成休眠状态,把自己从可运行队列移出,放入等待队列,然后调用schedule()选择和运行一个其它进程。唤醒的过程刚好相反:进程被设置为可运行状态,然后再从等待队列中移到可运行队列。

休眠有两种相关的进程状态:TASK_INTERRUPTIBLE和TASK_UNINTERRUPTIBLE。休眠通过等待队列进行处理。等待队列是由等待某些事件发生的进程组成的简单链表。内核用wake_queue_head_t来代表等待队列。等待队列能够通过DECLARE_WAITQUEUE()静态创建,也能够由init_waitqueue_head()动态创建。唤醒操作通过函数wake_up()进行,它会唤醒指定的等待队列上的全部进程。

负载平衡

Linux的调度程序为堆成多处理系统的每一个处理器准备了单独的可运行队列和锁。为了使各个可运行队列上的负载平衡,提供了负载平衡程序。假设它发现了不平衡,就会把相抵繁忙的队列中的进程抽到当前的可自行队列中来。

负载平衡程序有kernel/sched.c中的函数load_balance()来实现。它有两种调用方法。在schedule()运行的时候,仅仅要当前的可运行队列为空,它就会被调用。此外,它还会被定时器调用:系统空暇时每隔1毫秒调用一次或者在其它情况下每隔200毫秒调用一次。负载平衡程序调用时须要锁住当前处理器的可运行队列而且屏蔽中断,以避免可运行队列被并发地訪问。

抢占和上下文切换

上下文切换,也就是从一个可运行进程切换到还有一个可运行进程。进程切换schedule函数调用context_switch()函数完毕下面工作:

1.调用定义在<asm/mmu_context.h>中的switch_mm(),该函数负责把虚拟内存从上一个进程映射切换到新进程中。

2.调用定义在<asm/system.h>中的switch_to(),该函数负责从上一个进程的处理器状态切换到新进程的处理器状态。这包含保存、恢复栈信息和寄存器信息。

前面看到schedule函数调用有非常多种情况,全然依靠用户来调用不能达到非常好的效果。内核须要推断什么时候调用schedule,内核提供了一个need_resched标志来表明是否须要又一次运行一次调度:

1当某个进程耗尽它的时间片时,scheduler_tick()就会设置这个标志;

2当一个优先级高的进程进入可运行状态的时候,try_to_wake_up()也会设置这个标志。

每一个进程都包括一个need_resched标志,这是由于訪问进程描写叙述符内的数值要比訪问一个全局变量快

用户抢占

内核即将返回用户空间时候,假设need_resched标志被设置,会导致schedule函数被调用,此时发生用户抢占。

用户抢占在下面情况时产生:

1.从系统调返回用户空间。

2.从中断处理程序返回用户空间。

内核抢占

仅仅要又一次调度是安全的,那么内核就能够在不论什么时间抢占正在运行的任务。

什么时候又一次调度才是安全的呢?仅仅要没有持有锁,内核就能够进行抢占。

锁是非抢占区域的标志。因为内核是支持SMP的,所以,假设没有持有锁,那么正在运行的代码就是可又一次导入的,也就是能够抢占的。

内核抢占会发生在:
1.当从中断处理程序正在运行,且返回内核空间之前。

2.当内核代码再一次具有可抢占性的时候。

3.假设内核中的任务显式的调用schedule()。

4.假设内核中的任务堵塞(这相同也会导致调用schedule())。

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,
分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:服务器课程

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux内核源码分析进程的管理与调度 的相关文章

  • 从 Java 读取 /dev/input/js0

    我正在尝试阅读 dev input js0来自Java 但我不断得到 java io IOException Invalid argument at java io FileInputStream read0 Native Method a
  • 不同GIT版本的GIT合并结果不同

    在不同的 GIT 版本上运行 merge 命令我们得到不同的结果 命令是 git merge no ff origin master codeline Results 版本2 1 4 gt 合并成功 版本1 7 1 gt 同一提交上的同一合
  • 页面错误陷阱的成本

    我有一个应用程序 它定期 每 1 或 2 秒后 通过分叉自身来获取检查点 因此 检查点是原始进程的一个分支 它一直保持空闲状态 直到原始进程发生某些错误时被要求启动 现在我的问题是fork的写时复制机制的成本有多大 每当原始进程写入内存页面
  • 如何修改s_client的代码?

    我正在玩apps s client c in the openssl源代码 我想进行一些更改并运行它 但是在保存文件并执行操作后 我的更改没有得到反映make all or a make 例如 我改变了sc usage函数为此 BIO pr
  • 如何查找或计算Linux进程的页表大小和其他内核占用?

    我怎样才能知道 Linux 进程页表有多大 以及任何其他可变大小的进程统计 如果您真的对页表感兴趣 请执行以下操作 cat proc meminfo grep PageTables PageTables 24496 kB
  • 当我通过 shell 脚本创建 .txt 文件时,为什么文件名末尾出现问号? [复制]

    这个问题在这里已经有答案了 我正在编写一个 shell 脚本 我应该在其中创建 1 个文本文件 当我这样做时 文件名末尾出现一个问号 是什么原因 我正在 bash 脚本中尝试以下方法 1 grep ERROR a1 gt text txt
  • 如何真正释放 Linux 中的大页面以供新进程使用?

    真的找不到太多关于此的信息 希望有人可以提供帮助 我正在假脱机使用 100GB java 堆作为大数据缓存 为了避免与文件系统缓存等内容发生冲突 并且因为它通常性能更好 我将其分配在大页面中 我保留了 51 200 x 2MB 大页面 一切
  • 在键盘热插拔上加载模块

    我正在尝试学习如何为 Linux 系统编写模块和驱动程序 类似于this https unix stackexchange com questions 120839 usb kernel module does not load on de
  • 跟踪 pthread 调度

    我想做的是创建某种图表 详细说明 Linux 中 两个 线程的执行情况 我不需要查看线程的作用 只需查看它们何时被安排以及持续多长时间 基本上是一条时间线 在过去的几个小时里 我一直在互联网上搜索跟踪 pthread 调度的方法 不幸的是
  • 使用 C++ 输出字符串覆盖 Linux 终端上的最后一个字符串

    假设我有一个命令行程序 有没有办法让我说的时候 std cout lt lt stuff 如果我不做std cout lt lt n 在另一个之间std cout lt lt stuff 东西的另一个输出将覆盖同一行上的最后一个东西 清理行
  • 对 sf:: 的未定义引用

    我想用 C 制作 GUI 应用程序 发现 SFML 是一个不错的选择 幸运的是 我使用的是 Linux 所以 SFML 2 4 已经安装在我的系统上 所以我开始搜索一些教程并找到了一个制作简单窗口的教程 但是当我运行代码时 出现错误 提示未
  • xdotool 类型需要很长时间并导致整个桌面冻结

    我一直在使用xdotool type过去只能在快捷方式上输入耸肩xdotool type 这可行 但总是需要相当长的时间 并导致整个桌面冻结 完全冻结 而不仅仅是输入 几秒钟 不过并没有太打扰我 现在我需要一种方法来从文件中读取内容 对其进
  • 使用 sed 将 old-link-url 替换为 new-link-url

    我正在 bash 中编写一个脚本 将 old link url 替换为 new link url 我的问题是 sed 由于斜杠而无法替换 url 如果我只输入一些文字就可以了 my code sed e s old link new lin
  • Linux TCP服务器:在接受连接之前读取客户端的IP地址

    Related C Winsock API如何在接受连接之前获取连接客户端IP https stackoverflow com questions 716209 c winsock api how to get connecting cli
  • gnome-terminal 新选项卡,使用别名作为要执行的命令

    我已经创建了一个别名 bashrc文件如下 alias myproject cd Desktop myproject 当我重新启动终端时保存文件后 输入myproject带我到项目目录 但是当我尝试使用别名作为新的命令参数时gnome te
  • 是否有可能通过 mmap 匿名内存“打孔”?

    考虑一个使用大量大致页面大小的内存区域 例如 64 kB 左右 的程序 每个内存区域的寿命都相当短暂 在我的特定情况下 这些是绿色线程的替代堆栈 如何最好地分配这些区域 以便一旦该区域不再使用 它 们的页面可以返回到内核 天真的解决方案显然
  • 如何阅读shell命令的源代码?

    我想阅读编写linux命令的实际源代码 我已经获得了一些使用它们的经验 现在我认为是时候与我的机器进行更深层次的交互了 我在这里找到了一些命令http directory fsf org wiki GNU http directory fs
  • 如何从“git log”中查看 Git 中的特定版本?

    My git log显示为 enter code here git trial git log commit 4c5bc66ae50780cf8dcaf032da98422aea6e2cf7 Author king lt email pro
  • 如何在 Linux 中使用单行命令获取 Java 版本

    我想通过单个命令获取 Linux 中的 Java 版本 我是 awk 的新手 所以我正在尝试类似的事情 java version awk print 3 但这不会返回版本 我将如何获取1 6 0 21从下面的Java版本输出 java ve
  • 编写多个mysql脚本

    是否可以在复合脚本中包含其他 mysql 脚本 理想情况下 我不想为包含的脚本创建存储过程 对于较大的项目 我想分层维护几个较小的脚本 然后根据需要组合它们 但现在 我很乐意学习如何包含其他脚本 source是一个内置命令 您可以在 MyS

随机推荐

  • 使用HTMLTestRunner没有生成测试报告

    原因 没有执行 main函数中的程序 只执行了测试用例 在main函数上方右键运行的是整个py文件 在main函数下方右键运行的是py文件中的测试用例 如果在上方点击出现的和下方点击的一样需要在右上角设置并添加文件路径
  • element 限制文件上传类型

  • Golang依赖注入提升开发效率!

    导语 依赖注入并不是java独有的 也不是web框架独有的 本文用通俗易懂的语言讲解什么是依赖注入 为什么需要依赖注入 以及go语言如何使用依赖注入来提升开发效率 一 什么依赖注入 依赖注入 Dependency Injection 也叫D
  • C++拷贝构造、赋值构造详解

    一 前言 写一个用到指针的程序时 被拷贝 赋值 析构函数坑了一波 网上查相关博客 发现关于拷贝 赋值构造函数调用时机大多都有错误 因此决定自己总结撸一发博客 A A a 拷贝构造函数 A const A a 拷贝构造函数 A operato
  • 谈谈区块链入门技能(三):Layer 2区块链浏览器如何使用?Tokenview

    继介绍了比特币以及EVM系列区块链浏览器使用指南 今天我们再来 介绍一下Layer 2系列浏览器如何使用 Layer 1 是基础区块链 以太坊和比特币都是Layer1区块链因为它们是各种Layer2网络构建的底层基础 Layer2项目包括以
  • 第二个作业:贝叶斯估计

    第二个作业 贝叶斯估计实战 第一小题 试使用西瓜数据集3 0作为训练集 通过AIC准则构建一个贝叶斯网 我先看看scikit learn官网上关于贝叶斯估计 特别是贝叶斯网的构建方面的包和函数 然后再看看这个AIC准则具体是怎么样的 如何构
  • 操作系统5-处理机调度——lab6调度器

    大纲 处理机调度概念 处理机调度 调度时机 调度准则 调度算法 实时调度 多处理器调度 优先级反转 CPU调度的背景 什么是CPU调度 为什么会有这个概念 要研究它的什么 CPU调度的背景是进程切换 当我们说进程切换 其概念是保存当前进程在
  • stm32 CRC-16校验代码,单片机ModBUS-CRC16校验

    stm32系列内部均带有硬件CRC 不过为了方便移植 建议使用纯计算的方式 进行CRC 16计算 可用于ModBUS通信 提供两种实现方法的代码 1 实时计算 CRC 16 耗时多 这种方式耗时会比较多 优点是占用Flash RAM小 CR
  • umi3.5新特性之提速方案mfsu

    前几天 umi 插件化的企业级前端应用框架 正式发布了3 5版本 此次更新带来了一个全新的功能 mfsu 一 mfsu是什么 mfsu是一种基于webpack5新特性Module Federation 模块联邦 的打包提速方案 开启mfsu
  • 域环境的搭建

    域环境 内网渗透测试 很大的程度上就是域渗透测试 搭建域环境 这里使用Windows Server 2012 R2搭建windwos域环境 Windows Server 2012 R2 Windows Server 2008 R2 wind
  • SonarQube 9.x集成阿里p3c代码规范检测java代码;

    文章目录 前言 一 下载p3c pmd插件 二 sonarqube配置使用p3c规则检测 1 新建质量配置 2 将创建好的p3c检测规则设置为默认质量配置 注1 注2 前言 因为我们公司后端主用的是java语言 在进行sonar代码检测的时
  • LED驱动GPIO相关头文件简要分析

    常识 应用程序 gt 系统内核 gt 设备驱动 gt 硬件设备 设备驱动既是系统内核的下属 又是硬件设备的老大 在inux系统中用一个文件来代表一个设备 这个文件就叫设备文件 设备驱动的责任是将应用程序对设备文件 的打开 读 写 定位等操作
  • 当今世界依然屏蔽谷歌服务的五个国家

    附件里有一份数据表 转载于 https blog 51cto com mirage1993 1541008
  • 解决mysql不是内部或外部命令 环境变量

    1 当安装好MySQL后 安装MySQL时用户名和密码都设置的简单一点 比如我的用户名和密码都是root 针对学生练习而言 不要增加自己的练习难度 按键盘win r 输入cmd打开命令行模式 输入命令 gt gt gt mysql u ro
  • 添加域账号到客户机本地管理员组

    关键词 域账号 本地管理员组 域策略 需求描述 在域中 我们通常不会给普通域用户本地管理员身份 只会将特定域用户组加入客户机本地管理员组中 这里就涉及到了如何添加问题 既然在域中 我们多采用域策略实现以上需求 方法有二 方法1 1 在bat
  • Java面试复习体系总结

    https blog csdn net weixin 43314519 article details 112603595 utm medium distribute pc feed none task blog personrec tag
  • Java21天打卡day16-类1

    public class Person String Name int Age String Sex public void setName String name Name name public void setAge int age
  • 构建第一个fabric网络

    本例中使用的官方提供的fabric sample案例 在该网络中 cli客户端能够直接调用chaincode 在实际开发环境中 cli不允许直接调用chaincode 只有peer结点才能运行chaincode 该环境适用于调试开发环节 在
  • Delphi入门教程

    一 第一章Delphi6介绍 1 1概述 Delphi是基于Pascal语言的RAD快速应用程序开发工具 Rapid Application Development 为Windows系统下的可视化集成开发工具 它提供强大的VCL Visua
  • linux内核源码分析进程的管理与调度

    文章目录 一 进程管理 进程描写叙述符及任务结构 进程状态 进程创建 fork和vfork的差别 进程终止 二 进程调度 什么是调度 三 策略 I O消耗型和处理器消耗型的进程 进程优先级 时间片 进程抢占 调度算法 可运行队列 优先级数组