Nachos操作系统课设 浅谈优先级调度

Nachos实验实现线程id、限制线程数和更改调度算法(按优先级调度) 阅读详情

题目


Task1.5 实现优先级调度

  Implement priority scheduling in Nachos by completing the PriorityScheduler class. Priority scheduling is a key building block in real-time systems. Note that in order to use your priority scheduler, you will need to change a line in nachos.confthat specifies the scheduler class to use. The ThreadedKernel.scheduler key is initially equal to nachos.threads.RoundRobinScheduler. You need to change this to nachos.threads.PriorityScheduler when you're ready to run Nachos with priority scheduling.

  Note that all scheduler classes extend the abstract class nachos.threads.Scheduler. You must implement the methods getPriority(),getEffectivePriority(), and setPriority(). You may optionally also implement increasePriority() and decreasePriority() (these are not required). In choosing which thread to dequeue, the scheduler should always choose a thread of the highest effective priority. If multiple threads with the same highest priority are waiting, the scheduler should choose the one that has been waiting in the queue the longest.

  An issue with priority scheduling is priority inversion. If a high priority thread needs to wait for a low priority thread (for instance, for a lock held by a low priority thread), and another high priority thread is on the ready list, then the high priority thread will never get the CPU because the low priority thread will not get any CPU time. A partial fix for this problem is to have the waiting thread donate its priority to the low priority thread while it is holding the lock.

  Implement the priority scheduler so that it donates priority, where possible. Be sure to implement Scheduler.getEffectivePriority(), which returns the priority of a thread after taking into account all the donations it is receiving.

  Note that while solving the priority donation problem, you will find a point where you can easily calculate the effective priority for a thread, but this calculation takes a long time. To receive full credit for the design aspect of this project, you need to speed this up by caching the effective priority and only recalculating a thread's effective priority when it is possible for it to change.

  It is important that you do not break the abstraction barriers while doing this part -- the Lock class does not need to be modified. Priority donation should be accomplished by creating a subclass of ThreadQueue that will accomplish priority donation when used with the existing Lock class, and still work correctly when used with the existing Semaphore and Condition classes. Priority should also be donated through thread joins.

  Priority Donation Implementation Details:

  1) A thread's effective priority is calculated by taking the max of the donor's and the recipient's priority. If thread A with priority 4 donates to thread B with priority 2, then thread B's effective priority is now 4. Note that thread A's priority is also still 4. A thread that donates priority to another thread does not lose any of its own priority. For these reasons, the term "priority inheritance" is in many ways a more appropriate name than the term "priority donation".

  2) Priority donation is transitive. If thread A donates to thread B and then thread B donates to thread C, thread B will be donating its new effective priority (which it received from thread A) to thread C.


浅说  

        题目要求了要用较低的复杂度实现带有优先级传递的优先级调度,这要求我们在更新一个线程的优先级后要递归地将优先级向上传递。但是优先级的传递并不是一条链状的,因为一个线程可以通过Lock类或者join()方法持有多个等待队列。那么我们再来考虑一个问题,优先级的传递是否会构成环或者复杂的有向图呢?不会,因为在Nachos系统中,一个线程acquire()一个锁或者join()另一个线程后,就会立刻进入等待状态,而不继续执行其他操作,这就意味着一个线程不会处于多个等待队列中,所以优先级的传递关系实际上是一个有向森林,是树形的。这里我对一个线程用一个链表holdQueues来存储了它所持有的全部等待队列,用waitQueue来代表它所处的等待队列,并在队列的实现中设置了lockholder,来表示该队列锁的持有者,递归的实现在getEffectivePriority()中,每次进程修改优先级就会去调用该方法,waitQueue的lockholder来向上更新全部的优先级关系。

        另外一个问题就是如何在保证逻辑完备的情况下将调度高效地实现,这里大多数的同学都没有做对,他们犯了一个严重的错误,使用了java自带的PirorityQueue或者TreeSet,但是在setPirority时没有将线程从队列中移出再放回,而是直接修改了优先级,PirorityQueue是一个二叉堆,TreeSet是利用红黑树实现的,它们的形状在节点插入或者移出时改变,只修改权值并不会引起结构的改变,修改其实是无效的。采用PirorityQueue的方法无疑是最糟糕的,因为这意味着你每次修改优先级都需要使用Iterator遍历整个队列找到你要修改的线程。

        使用TreeSet可以在log(n)的复杂度内移出一个特定线程,已经比较好了,但还是会出现小问题,因为TreeSet是一个集合,里面不能有重复的元素,而TreeSet是采用权重来区分线程的,这样如果只将优先级作为权重,相同优先级的线程就会被覆盖,所以我们要设法使每个线程权重均不相同。注意到要求中有这样一句话,要求相同优先级的进程先进入队列的先出队列,所以我们就可以将权重设置为一个双关键字的值,先比较优先级,再比较时间。如果你将进入队列时系统的时钟滴答作为时间,这样看起来充分利用了系统特性,好像是个不错的主意,但是你又搞错了,因为nachos的时钟滴答一般是在一个线程yield()时才会增加10个,这样如果你一次性将多个线程放入就绪队列的话,他们进入队列的时钟滴答实际是一样的,Treeset同样无法识别这些线程。好的做法是在队列中设置一个计数器,每次线程调用waitForAccess()都会使该队列的计数器加一,通过这个计数器来代表线程进入队列的时间。

        能够完整地将上面的做法实现已经很不错了,但是算法还可以进一步优化。意识到优先级只有0~7这8个等级,我们可以在队列中设置一个大小为8的TreeSet数组,每个线程根据优先级放入相应的TreeSet中。这样的做法有一个好处,就是在更新一个线程的有效优先级时,我们要查询它所持有的全部等待队列中线程优先级的最大值,如果我们直接用一个TreeSet复杂度将是O(logn),当TreeSet中线程数量超过256个时,操作次数是大于8的,但是用刚才提到的做法我们只需要查队列中的8个TreeSet的size()是否大于0即可,size()方法的复杂度是O(1)的,这样不管有多少进程,对每个队列的查询操作次数都不会超过8,复杂度达到了常数级。

        在代码的实现中还有诸多细节,这里不再一一赘述。


实现代码

package nachos.threads;

import nachos.machine.*;
import java.util.*;

public class PriorityScheduler extends Scheduler {
    public PriorityScheduler() {
    }
    
    public ThreadQueue newThreadQueue(boolean transferPriority) {
        return new PriorityQueue(transferPriority);
    }

    public int getPriority(KThread thread) {
        Lib.assertTrue(Machine.interrupt().disabled());
                   
        return getThreadState(thread).getPriority();
    }

    public int getEffectivePriority(KThread thread) {
        Lib.assertTrue(Machine.interrupt().disabled());
                   
        return getThreadState(thread).getEffectivePriority();
    }

    public void setPriority(KThread thread, int priority) {
        Lib.assertTrue(Machine.interrupt().disabled());
                   
        Lib.assertTrue(priority >= priorityMinimum &&
               priority <= priorityMaximum);
        
        getThreadState(thread).setPriority(priority);
    }

    public boolean increasePriority() {
        boolean intStatus = Machine.interrupt().disable();
                   
        KThread thread = KThread.currentThread();
    
        int priority = getPriority(thread);
        if (priority == priorityMaximum)
            return false;
    
        setPriority(thread, priority+1);
    
        Machine.interrupt().restore(intStatus);
        return true;
    }

    public boolean decreasePriority() {
        boolean intStatus = Machine.interrupt().disable();
                   
        KThread thread = KThread.currentThread();
    
        int priority = getPriority(thread);
        if (priority == priorityMinimum)
            return false;
    
        setPriority(thread, priority-1);
    
        Machine.interrupt().restore(intStatus);
        return true;
    }

    public static int priorityDefault = 1;
    public static int priorityMinimum = 0;
    public static int priorityMaximum = 7;    

    protected ThreadState getThreadState(KThread thread) {
        if (thread.schedulingState == null)
            thread.schedulingState = new ThreadState(thread);
    
        return (ThreadState) thread.schedulingState;
    }
    
    protected class PriorityQueue extends ThreadQueue {
        PriorityQueue(boolean transferPriority) {
            this.transferPriority = transferPriority;
            init();
        }
        public void init() {
            cnt=0;
            wait=new TreeSet[priorityMaximum+1];
            for(int i=0;i<=priorityMaximum;i++)
                wait[i]=new TreeSet<ThreadState>();
        }
    
        public void waitForAccess(KThread thread) {
            Lib.assertTrue(Machine.interrupt().disabled());
            getThreadState(thread).waitForAccess(this);
        }
    
        public void acquire(KThread thread) {
            Lib.assertTrue(Machine.interrupt().disabled());
            getThreadState(thread).acquire(this);
            if(transferPriority)
                lockholder=getThreadState(thread);
        }
    
        public KThread nextThread() {
            Lib.assertTrue(Machine.interrupt().disabled());
            ThreadState res=pickNextThread();
            
            return res==null?null:res.thread;
        }
    
        protected ThreadState pickNextThread() {
            ThreadState res=NextThread();
            
            if(lockholder!=null)
            {
                lockholder.holdQueues.remove(this);
                lockholder.getEffectivePriority();
                lockholder=res;
            }
            if(res!=null) res.waitQueue=null;
            return res;
        }
        
        protected ThreadState NextThread() {
            ThreadState res=null;

            for(int i=priorityMaximum;i>=priorityMinimum;i--)
               if((res=wait[i].pollFirst())!=null) break;
            
            return res;
        }
        
        public void print() {
            Lib.assertTrue(Machine.interrupt().disabled());
        }
        
        public void add(ThreadState state) {
            wait[state.effectivepriority].add(state);
        }
        
        public boolean isEmpty() {
            for(int i=0;i<=priorityMaximum;i++)
                 if(!wait[i].isEmpty()) return false;
            return true;
        }
    
        protected long cnt;
        public boolean transferPriority;
        protected TreeSet<ThreadState>[] wait;
        protected ThreadState lockholder=null;
    }

    protected class ThreadState implements Comparable<ThreadState>{
        public ThreadState(KThread thread) {
            this.thread = thread;
            holdQueues=new LinkedList<PriorityQueue>();
            
            setPriority(priorityDefault);
            getEffectivePriority();
        }

        public int getPriority() {
            return priority;
        }

        public int getEffectivePriority() {
            int res=priority;
            if(!holdQueues.isEmpty()) {
                Iterator it=holdQueues.iterator();
                while(it.hasNext())
                {
                    PriorityQueue holdQueue=(PriorityQueue)it.next();
                    for(int i=priorityMaximum;i>res;i--)
                        if(!holdQueue.wait[i].isEmpty()) { res=i;break;}
                }
            }
            if(waitQueue!=null&&res!=effectivepriority)
            {
                ((PriorityQueue)waitQueue).wait[effectivepriority].remove(this);
                ((PriorityQueue)waitQueue).wait[res].add(this);
            }
            effectivepriority=res;
            if(lockholder!=null)
                lockholder.getEffectivePriority();
            return res;
        }
    
        public void setPriority(int priority) {
            if (this.priority == priority)
                return;
            
            this.priority = priority;
            
            getEffectivePriority();
        }
    
        public void waitForAccess(PriorityQueue waitQueue) {
            Lib.assertTrue(Machine.interrupt().disabled());
            
            time=++waitQueue.cnt;
            
            this.waitQueue=waitQueue;
            waitQueue.add(this);
            lockholder=waitQueue.lockholder;
            getEffectivePriority();
        }
    
        public void acquire(PriorityQueue waitQueue) {
            Lib.assertTrue(Machine.interrupt().disabled());
             
            if(waitQueue.transferPriority) holdQueues.add(waitQueue);
            Lib.assertTrue(waitQueue.isEmpty());
        }   
       
        protected KThread thread;
        protected int priority,effectivepriority;
        protected long time;
        protected ThreadQueue waitQueue=null;
        protected LinkedList holdQueues;
        protected ThreadState lockholder=null;

        public int compareTo(ThreadState ts) {
            if(time==ts.time) return 0;
            return time>ts.time?1:-1;
        }
    }
}



测试


测试代码:

    private static class PingTest implements Runnable
    {
        Lock a=null,b=null;
        int name;
        PingTest(Lock A,Lock B,int x)
        {
            a=A;b=B;name=x;
        }
        public void run() {
            System.out.println("Thread "+name+" starts.");
            if(b!=null)
            {
                System.out.println("Thread "+name+" waits for Lock b.");
                b.acquire();
                System.out.println("Thread "+name+" gets Lock b.");
            }
            if(a!=null)
            {
                System.out.println("Thread "+name+" waits for Lock a.");
                a.acquire();
                System.out.println("Thread "+name+" gets Lock a.");
            }
            KThread.yield();
            boolean intStatus = Machine.interrupt().disable();
            System.out.println("Thread "+name+" has priority "+ThreadedKernel.scheduler.getEffectivePriority()+".");
            Machine.interrupt().restore(intStatus);
            KThread.yield();
            if(b!=null) b.release();
            if(a!=null) a.release();
            System.out.println("Thread "+name+" finishs.");
            
        }
    }
    
    public static void selfTest()
    {
        Lock a=new Lock();
        Lock b=new Lock();
        
        Queue<KThread> qq=new LinkedList<KThread>();
        for(int i=1;i<=5;i++)
        {
            KThread kk=new KThread(new PingTest(null,null,i));
            qq.add(kk);
            kk.setName("Thread-"+i).fork();
        }
        for(int i=6;i<=10;i++)
        {
            KThread kk=new KThread(new PingTest(a,null,i));
            qq.add(kk);
            kk.setName("Thread-"+i).fork();
        }
        for(int i=11;i<=15;i++)
        {
            KThread kk=new KThread(new PingTest(a,b,i));
            qq.add(kk);
            kk.setName("Thread-"+i).fork();
        }
        KThread.yield();
        Iterator it=qq.iterator();
        int pp=0;
        while(it.hasNext())
        {
            boolean intStatus = Machine.interrupt().disable();
            ThreadedKernel.scheduler.setPriority((KThread)it.next(),pp+1);
            Machine.interrupt().restore(intStatus);
            pp=(pp+1)%6+1;
        }
    }



结果:

        线程1~5不要任何锁,线程6~10需要锁a,线程11~15需要锁a和锁b,并将15个线程的优先级设置如下:1 2 3 4 5 6 1 2 3 4 5 6 1 2 3,这样根据优先级传递的原则,运行结果如下:

Thread 1 starts.

Thread 2 starts.

Thread 3 starts.

Thread 4 starts.

Thread 5 starts.

Thread 6 starts.

Thread 6 waits for Lock a.

Thread 6 gets Lock a.

Thread 7 starts.

Thread 7 waits for Lock a.

Thread 8 starts.

Thread 8 waits for Lock a.

Thread 9 starts.

Thread 9 waits for Lock a.

Thread 10 starts.

Thread 10 waits for Lock a.

Thread 11 starts.

Thread 11 waits for Lock b.

Thread 11 gets Lock b.

Thread 11 waits for Lock a.

Thread 12 starts.

Thread 12 waits for Lock b.

Thread 13 starts.

Thread 13 waits for Lock b.

Thread 14 starts.

Thread 14 waits for Lock b.

Thread 15 starts.

Thread 15 waits for Lock b.

Thread 6 has priority 7.

Thread 6 finishs.

Thread 7 gets Lock a.

Thread 7 has priority 7.

Thread 7 finishs.

Thread 11 gets Lock a.

Thread 11 has priority 7.

Thread 11 finishs.

Thread 13 gets Lock b.

Thread 13 waits for Lock a.

Thread 5 has priority 5.

Thread 5 finishs.

Thread 4 has priority 4.

Thread 10 gets Lock a.

Thread 4 finishs.

Thread 10 has priority 4.

Thread 10 finishs.

Thread 13 gets Lock a.

Thread 13 has priority 7.

Thread 13 finishs.

Thread 12 gets Lock b.

Thread 12 waits for Lock a.

Thread 3 has priority 3.

Thread 9 gets Lock a.

Thread 3 finishs.

Thread 9 has priority 3.

Thread 9 finishs.

Thread 12 gets Lock a.

Thread 12 has priority 6.

Thread 12 finishs.

Thread 15 gets Lock b.

Thread 15 waits for Lock a.

Thread 2 has priority 2.

Thread 8 gets Lock a.

Thread 2 finishs.

Thread 8 has priority 2.

Thread 8 finishs.

Thread 15 gets Lock a.

Thread 15 has priority 3.

Thread 15 finishs.

Thread 14 gets Lock b.

Thread 14 waits for Lock a.

Thread 14 gets Lock a.

Thread 14 has priority 2.

Thread 14 finishs.

Thread 1 has priority 1.

Thread 1 finishs.
【Nachos】山东大学操作系统实验二 具有优先级的线程调度 完整源码见本人博客下载资源 文章目录一、Nachos线程调度相关分析二、实现的线程调度一览三、基本优先级调度(抢占与非抢占)1、非抢占优先级调度1)基本思路2)实现过程描述3)测试结果展示2、抢占优先级调度1)基本思路2)实现过程描述3)测试结果展示四、动态优先级时间片轮转调度(DP_RR)1、Nachos定时器(Timer),时钟中断,时间计算相关分析2、DP_RR算法描述以及优势分析*1)优势... 阅读详情

相关推荐

操作系统课设--具有优先级的线程调度

山东大学操作系统课设实验二 具有优先级的线程调度(lab2)实验目的熟悉Nachos原有的线程调度策略设计并实现具有优先级的线程调度策略修改Thread.h,修改Thread.cc修改scheduler.cc修改Test 实验二 具有优先级的线程调度(lab2) 实验目的 熟悉Nachos原有的线程调度策略 概念欠缺: .cc是方法实现,.h是头文件 步骤: 将threads里的内容copy...

qq_41545715的博客 1710

Implement priority queue (实现优先队列)

优先队列:顾名思义,首先它是一个队列,但是它强调了“优先”二字,所以,已经不能算是一般意义上的队列了,它的“优先”意指取队首元素时,有一定的选择性,即根据元素的属性选择某一项值最优的出队~   优先级队列 是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素   优先队列是0个或多个元素的集合,每个元素都有一个优先权或值,对优先队列执行的操作有1) 查找;2) 插

chen 1263

nachos操作系统-基于优先级的线程调度

基于优先级的线程调度  1.实验目的     熟悉nachos操作系统,掌握线程优先级的调度,深入理解操作系统内核,了解用户程序的加载过程以及多用户进程的内存分配机制。 2.实验内容       Nachos的线程管理模块升级源代码及实现线程的优先级调度 3.实验方法(实验步骤) Thread.h 文件 (1)、指定线程的最大值; (2)、

qq_38472663的博客 3374

Nachos进程数量限制128、ID号分配以及基于优先级的调度算法详解

文章目录 写在前面 运行环境配置 最大线程限制 实现可回收的线程ID机制 基于优先级的先来先服务调度算法 一.写在前面 写这篇博客初衷主要是因为最近在进行操作系统的实验,在网上找了很多教程,但都有些问题,要么就是根本实现不了,要么讲述的不够详细,对于没有面向对象编程基础的小白很不友好。于是就萌发出了写这篇博客的想法,在这篇博客中我会尽可能详细的讲述每一个实现步骤。即使是没有面向对象编程基础的小白,只要认真的跟着步骤来也能成功。 由于是面向小白的,所以在讲述的过程难免有些冗杂,还望谅解,已经有面向对象编程

gw_fy的博客 5225

NACHOS调度算法的实现

基于当时刚刚接触NACHOS时无从下手的窘迫,现在贴出一份自己的实验报告,跟大家交流下操作系统实验3 关于调度算法的实现我们实现的是Shortest Job First ,Shortest Remaining Next & Priority,Round-Robin 和Multiple Queues这5个调度的算法。 经过我一个多星期对文档的阅读和与同学的讨论,初步弄明白了Nachos的线程调度的基

Mars的专栏 8163

高级操作系统——Nachos进程调度

因为这篇文章引用博主 superli90有点多了(主要是他写的很清楚,我也不知道在哪找。所以就直接引用过来了Hhh)于是首先附上链接 版权声明:本文为优快云博主「superli90」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.youkuaiyun.com/superli90/article/details/29373593 ...

weixin_45680007的博客 770

nachos

nachos实验记录实验一分析threads文件夹内容threadscheduler初始化函数Initialize()的工作main()函数的工作gdb基本使用实验三分析synch文件实验内容 实验一 分析threads文件夹内容 思路:通过thread类中的方法,来调用schedule类中的调度函数,实现线程的创建,就绪,运行,阻塞和结束五种状态的转换。 thread 创建线程:fork()。首先为线程分配栈资源(StackAllocate()),然后将线程状态设为就绪态(setStatus()),并放

weixin_43679657的博客 2324

Nachos操作系统实习-lab2

Nachos操作系统实习-lab2内容一:总体概述内容二:任务完成情况内容三:遇到的困难以及解决方法内容四:收获及感想内容五:对课程的意见和建议内容六:参考文献 内容一:总体概述 本次lab的主要内容是充分理解Linux中存在的进程/线程调度算法,并在理解Nachos线程调度机制的基础上动手实现两个调度算法——基于优先级的抢占式调度算法和时间片轮转调度算法。 本次lab的重点在于理解Nachos的...

weixin_42214778的博客 974

NachOS根据优先级的线程调度实验--创建完之后再调度

注1:由于老师的要求实在太高,边创建边调度的模式实现得不是很好(老师要求不能改原构造函数,不能修改内核线程,不能去抑制它们),所以最后做出了许多版本,但都不符合他的要求,所以最后就直接创建完之后再调度 注2:由于前两篇博客是分开写的,所以就有点绕了,同时存在一些bug,所以今天将对前两篇文章进行整合,同时也将一些不对的地方修改了。同时就不再使用原构造函数,改为使用新构造函数 一、NachOS线程ID的实现、最大线程数的实现和优先级的添加 1、修改thread.h文件,定义我们需要的一些变量和参数(threa

qq_51846636的博客 3680

操作系统课程设计 nachos 线程调度

本程序实现了Nachos中的线程调度算法,实现的算法有 动态优先数, 轮询法, 静态优先数, FCFS, 彩票调度算法。此为操作系统课程设计中要求对Nachos进行改进的实验。

Silvaco 学习笔记——物理模型:载流子产生复合模型

对载流子的复合机制进行总结

reactortiger的博客 1万+

山东大学操作系统课设实验一:Nachos开发环境的安装测试

此处运行命令报错,经过搜索资料发现,这是由于不同版本的Kali Linux,它的源软件包名字会发生一些局部的变化,这都是很正常的。我的ubuntu版本为20.04版本,版本过高。由于我的ubuntu版本过高,最新版本的 Ubuntu 中,默认情况下可能没有提供 gcc-4.8 和 g++-4.8 这样的旧版本软件包。我的ubuntu版本为20.4,都是图片,懒得写代码啦,不同版本下载总会遇到不同问题,可以参考。Filesys 目录 Nachos 文件系统管理部分源代码,包括文件读写、目录管理等。

m0_63155449的博客 861

TP4054芯片实战:手把手教你设计USB锂电充电电路(附PCB散热优化技巧)

本文以TP4054芯片为核心,手把手教你设计稳定可靠的USB锂电池充电电路。文章详细解析了芯片的恒流恒压工作模式、关键外围元件选型计算,并重点分享了PCB布局与散热优化的实战技巧,帮助工程师从“能工作”提升到“工作得好”,确保充电效率与系统稳定性。

1a2s3d4f5g的博客 468

NachOS根据优先级的线程调度实验

注:由于老师一直没发实验报告模板,所以直到今天才开始写,本次实验是延续上一次实验所做,并会对上一次实验中的某些过程进行修改(不理解的同学可以看一下上一篇博客)!!! 实验目的 (1)通过阅读相关源码,掌握NachOS调度的数据结构和实现过程; (2)对NachOS线程描述进行完善,增加关于调度的内容; (3)掌握NachOS线程调度的算法。 实验内容 (1)在NachOS线程描述中增加调度优先级的数据成员,并完善就绪队列管理的成员方法; (2)实现基于优先级的FCFS调度。 实验过程 这次试验也是看了许

qq_51846636的博客 4791

告别配置烦恼!保姆级教程:在Windows 10/11上为QT5.14.2配置MSVC2017编译器(附VS2022组件避坑指南)

本文提供了一份详细的保姆级教程,指导如何在Windows 10/11上为QT5.14.2配置MSVC2017编译器,包括VS2022组件避坑指南。从环境准备到关键配置,再到调试工具验证和Qt Creator中的编译器设置,一步步解决常见问题,帮助开发者快速搭建稳定可靠的开发环境。

weixin_30615767的博客 503

linux上使用tun/tap设备模拟一个虚拟网卡,并将该虚拟网卡连接到新创建的网桥上

tun/tap设备是操作系统内核中的虚拟网络设备,是用软件模拟的网络设备,提供与硬件网络设备完全相同的功能。主要用于用户空间和内核空间传递报文。tun/tap对于硬件网络设备而言,一端连接的是物理网络,一端连接的是网络协议栈。对于tun/tap设备而言,一端连接的是应用程序(通过 字符设备文件),一端连接的是网络协议栈。

糖果墙的博客 6413

操作系统NACHOS实验(二)具有优先级的线程调度

山东大学操作系统NACHOS实验(二)实验思路关键源代码注释及说明调试记录: 可能会有一些小错误,但是基本思路应该还是没问题的。 实验思路 首先找到控制线程调度的代码 scheduler.h 和 scheduler.cc ,阅读代码后可知,其包含的主要方法由ReadyToRun (Thread *thread);FindNextToRun ();Run (Thread *nextThread);三...

weixin_37900570的博客 3535

【人工智能】大模型可以分为L0层:基础大模型/通用大模型、L1层:行业大模型、L2层:细分场景模型三个层级

大模型确实可以分为L0、L1、L2三个层级,这种分层架构不仅有助于提升模型的泛化能力和适应性,还能更好地满足不同行业和场景的需求。华为盘古大模型的分层架构(L0、L1、L2)在多个证据中得到了详细描述和验证。例如,华为云盘古大模型3.0明确分为L0基础大模型、L1行业大模型和L2场景模型三层架构。此外,其他来源也一致支持这一分层架构,如用友网络的企业服务大模型、智谱AI的GLM-4系列等。

奶爸的编程之路,也就一周冷个三天 3984

Nachos操作系统实验二:具有优先级的线程调度

Nachos操作系统实验二:具有优先级的线程调度注意实验目的实验思路实验过程 注意 所有单独修改部分均在其后方注释add here 整体修改部分均在其上下注释add here 本文均为直接在原代码上进行修改,如果移动位置到其他文件夹,请自行修改makefile文件,本文只提供思路。 实验目的 1.熟悉Nachos原有的线程调度策略; 2.设计并实现具有静态优先级的非抢占式线程调度策略。 实验思路 实验要求实现具有静态优先级的非抢占式线程调度策略,首先找到线程调度的相关位置,为code/threads/sch

m0_46422419的博客 2104

五.EtherCAT开发之STM32F407ZGt6+ LAN9253 外置EEPROM配置数据含义

EtherCAT从站简称ESC,ESC在上电过程中,会自动加载EEPROM中前7个字(1word = 2 byte)到ESC寄存器。ESC寄存器总是可以被EtherCAT主站通过EtherCAT总线访问,无论PDI接口寄存器配置什么值。EEPROM存储器中的前7个字,将决定ESC的工作模式。

AIoT深度探索者 | 嵌入式系统架构师 深耕物联网(IoT)与人工智能(AI)融合技术,聚焦​​边缘计算、图像开发、低功耗通信协议​​,致力于智能硬件,关注我获取最新技术文章信息与海量资源~ 3471

Apache Jena SPARQL 查询完全指南:入门与实战案例

本文介绍了使用Apache Jena执行SPARQL查询的完整指南。SPARQL是用于RDF数据的标准查询语言,在知识图谱领域地位相当于SQL。教程从基础开始,涵盖创建模型、加载数据以及执行各种查询类型。特别强调了WHERE子句中的图模式匹配机制,通过Mermaid图直观展示数据图与查询图的匹配过程。文章还对比了变量命名规范(?和$前缀),解释了SPARQL引擎如何通过变量绑定实现数据检索。通过Hello World示例演示了完整查询流程,为开发者提供了SPARQL的实用入门指导。

Lincoln 的专栏 1375

山东大学软件学院操作系统课设nachos---具有优先级的线程调度

实验2 具有优先级的线程调度(Lab2)实现的具体方法提示:List类中已有的方法可加以利用。参阅:codelab2/n2codecode/demo0/

2401_83166453的博客 1216

【YOLO系列】YOLOv4详解:模型结构、损失函数、训练方法及代码实现

摘要:YOLOv4在目标检测领域实现了精度与速度的平衡,通过CSPDarknet53骨干网络、SPP+PANet特征融合及CIoU损失函数等创新,在MS COCO数据集达到65.7% AP50,V100显卡实现62FPS实时检测。核心优化包括Mosaic数据增强、自对抗训练和解耦头结构,显著提升小目标检测和遮挡场景鲁棒性。代码实现采用CSP模块和SPP多尺度池化,兼顾计算效率与检测性能,为工业落地提供高效解决方案。(149字)

一碗白开水一 1358

NachOS线程ID的实现、最大线程数的实现和优先级的添加

NachOS线程的描述和优先级 1.实验目的 (1)通过阅读相关源码,掌握NachOS运行原理和编译方法; (2)完善NachOS下线程描述的内容。 2.实验内容 (1)为NachOS线程添加线程ID,并设置系统最大线程数; (2)为NachOS线程调度添加优先级,为实现基于优先级的调度做准备。 3.实验方法(实验步骤) (1)理解NachOS线程的运行与调度原理,找到需要修改的代码(注:以下所有修改代码的部分,均是由vim修改完成); (2)对thread.h进行修改:在头文件处定义线程最大数MAX_SI

qq_51846636的博客 5570

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

线程调度实验报告_Nachos Lab2

内容一:总体概述          本次Lab针对的内容了解线程的调度机制,每个时刻每个CPU上只能有一个线程运行,为了提高系统的吞吐量和工作效率,必须合理的安排每个线程上CPU的顺序和时间。在实用中,多数为几种调度策略结合使用的。包括是否抢占、动态优先级还是静态优先级、是否分时等等。          调度策略的实施通常需要在PCB中增加相应的修改,需要在其中增加相应的数据结构记录执行的状态

superli90的专栏 8822

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

对Nachos线程调度的探讨和改进

nachos线程调度实例剖析为了有效的管理CPU资源在处理Nachos线程调度的修改问题上,首先应该着重考虑这样几个问题:何时进行线程调度?遵循何种规则完成调度?以及调度过程中需要完成哪些工作?同时要兼顾线程调度的考量标准,即响应时间、周转时间、CPU吞吐量等。调度策略的选择取决于系统的类型,Nachos作为一个分时系统,若将其改为抢占式调度,其调度策略的主要目标应该达到如下内容: (1)加快

超新星工作室 3632

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

上一篇: POJ-2778 ac自动机+矩阵快速幂
下一篇: HDU-3397 线段树+区间合并
AC_Machine
博客等级 码龄11年 1粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值