`
猫太的鱼
  • 浏览: 239263 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Linux下测量一次context switch所花的时间

阅读更多
看到水木上的一道题,Write a C program which measures the speed of a context switch on a UNIX/Linux system.刚开始想了好久都没有思路,后来想到了一个办法,不过不知道是不是出题者想要的东西,但是我觉得这个已经算是精度比较高的一个办法了。
具体做做法是:

在父子进程之间切换,来计算context switch的时间,于是写了一段代码(Linux only 的程序)

1.通过sched_setaffinity将进程绑定在某一个CPU上(如果是多核的话,比如CPU0),fork出来的子进程也会继承这个属性

2. 通过sched_setscheduler讲进程设置成SCHED_FIFO(这步需要root权限),即实时进程调度,同时,将优先级调到最高(最高优先级可以通过sched_get_priority_max系统调用得到,fork出来的子进程也会继承这个属性,这么做是为了保证CPU0上父进程和子进程优先级最高,父进程切换出来内核调度到的一定是子进程)

3.创建管道,用于在fork之后,父进程和子进程利用管道循环读写n次,读写一个int,用此来进行context switch

4. fork,,父进程先获取当前时间戳(gettimeofday),然后往管道中写,。这时子进程应该能从read中返回,然后子进程写一个int,父进程读,如此循环n次。结束之后,子进程获取当前时间戳。这两个时间戳之差就是大致n*2次的context switch的时间

附上实际的代码:


#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sched.h>
#include <time.h>
#include <sys/time.h>
#include <pthread.h>
#include <sys/wait.h>


int main(int argc, char* argv[])
{
        int prio_max,data,i,iter_count;        
        int pfd1[2],pfd2[2],time_pipe[2];
        pid_t pid,child;

        struct timeval start,end;
        struct sched_param prio_param;

        cpu_set_t cpuset;      

        if( argc > 1 )
                iter_count = atoi(argv[1]);
        else
                iter_count = 10000;

        CPU_ZERO(&cpuset);              
        CPU_SET(0,&cpuset);

        memset(&prio_param,0,sizeof(struct sched_param));

        pid = getpid();



        if( sched_setaffinity(pid,sizeof(cpu_set_t),&cpuset) < 0 ){
                perror("sched_setaffinity");
                exit(EXIT_FAILURE);
        }

        if( (prio_max = sched_get_priority_max(SCHED_FIFO)) < 0 ){
                perror("sched_get_priority_max");
                exit(EXIT_FAILURE);
        }
        printf("prio_max:      %d\n",prio_max);
        prio_param.sched_priority = prio_max;
        if( sched_setscheduler(pid,SCHED_FIFO,&prio_param) < 0 ){
                perror("sched_setscheduler");
                exit(EXIT_FAILURE);
        }

        if( pipe(pfd1) < 0 ){
                perror("pipe");
                exit(EXIT_FAILURE);
        }

        if( pipe(pfd2) < 0 ){
                perror("pipe");
                exit(EXIT_FAILURE);
        }

        if( pipe(time_pipe) < 0 ){
                perror("pipe");
                exit(EXIT_FAILURE);
        }

        if( (child = fork()) < 0 ){
                perror("fork");
                exit(EXIT_FAILURE);
        }else if( child == 0 ){        
                int n = sizeof(data);
                close(pfd1[1]);      
                close(pfd2[0]);
                close(time_pipe[0]);

                for( i = 0; i < iter_count; i++ ){
                        if( read(pfd1[0],&data,sizeof(data)) != n ){
                                perror("read at child process");
                                exit(EXIT_FAILURE);
                        }
                        if( write(pfd2[1],&data,sizeof(data)) != n){
                                perror("write at child process");
                                exit(EXIT_FAILURE);
                        }
                }
                gettimeofday(&end,NULL);

                n = sizeof(struct timeval);
                if( write(time_pipe[1],&end,sizeof(struct timeval)) != n ){
                        perror("write at child process");    
                        exit(EXIT_FAILURE);
                }
                close(pfd1[0]);
                close(pfd2[1]);
                close(time_pipe[1]);
                exit(EXIT_SUCCESS);
        
        }else{
                double switch_time,yield_time;        
                struct timeval yield;
                int n;
                close(pfd1[0]);
                close(pfd2[1]);
                close(time_pipe[1]);

                data = 1;
                n = sizeof(data);

                gettimeofday(&start,NULL);
                for( i = 0; i < iter_count;i++){
                        if( write(pfd1[1],&data,sizeof(data)) != n ){
                                perror("write at parent process");
                                exit(EXIT_FAILURE);
                        }
                        if( read(pfd2[0],&data,sizeof(data)) != n ){
                                perror("write at parent process");
                                exit(EXIT_FAILURE);
                        }
                }

                n = sizeof(struct timeval);
                if( read(time_pipe[0],&end,sizeof(struct timeval)) != n ){
                        perror("read at parent");    
                        exit(EXIT_FAILURE);
                }

                close(pfd1[1]);
                close(pfd2[0]);
                close(time_pipe[0]);

                wait(NULL);                  
                switch_time = ((end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec))/1000.0;
                printf("context switch between two processes: %0.6lfms\n",switch_time/(iter_count*2));

        }
        return 0;
}





实际在一个Intel(R) Xeon(R) CPU E5310  @ 1.60GHz  8核4GB内存的机器上,测出来一次context switch的时间大约在3.706us,所花费的指令数大致是5000~6000条指令的样子,实际的时间应该要比这个快一些吧。不过如果循环的n比较小的话,测出来的误差挺大的,比如iter_count取1,测出来的context switch时间貌似接近100us,相差了近100倍啊啊啊啊
分享到:
评论

相关推荐

    什么是context switch.doc

    上下文切换(Context Switch)是操作系统中的一个关键概念,它涉及到多任务处理和资源调度。在计算机系统中,中央处理器(CPU)一次只能执行一个进程或线程的指令。为了实现多个任务看似同时进行的“多工”效果,...

    测试Context Switch time()

    ### 一、上下文切换(Context Switch)简介 在操作系统中,上下文切换是指操作系统内核在多任务环境中将CPU资源从一个进程或线程转移到另一个进程或线程的过程。这个过程包括保存当前执行任务的状态(即上下文),并...

    Project2任务二-context switch开销测量1

    在这个项目中,我们关注的是如何测量这种切换的开销,即从一个任务切换到另一个任务所需的时间和资源。 **1. Context Switch** 上下文切换分为两个主要阶段:保存当前任务的状态(上下文)和恢复新任务的状态。在...

    最新版linux SwitchHosts._linux_x64_3.5.4.5517.zip

    SwitchHosts 是一款在Linux系统中使用的hosts文件管理工具,主要功能是方便用户切换不同的hosts配置,例如在开发、测试和生产环境之间快速切换网络设置。这个最新版本为linux_x64_3.5.4.5517,表明它是专为64位Linux...

    最新倾斜摄影测量软件Context Capture (CC10.20)完整安装包

    综上所述,Context Capture (CC10.20)作为一款前沿的倾斜摄影测量软件,在三维建模领域展现出了强大而全面的功能特性。无论是科研工作者还是行业从业者都能从中受益匪浅。希望本文能帮助大家更好地了解并掌握该软件...

    Project2任务一-多tasks启动与context switch1

    在这个“Project2任务一-多tasks启动与context switch1”中,我们将探讨多任务处理、上下文切换、进程和线程的概念,以及它们在操作系统中的实现。 首先,多任务是指操作系统同时处理多个任务或进程的能力。在非...

    Linux驱动drm-context

    Linux驱动drm_context

    压力测试衡量CPU的三个指标

    一般来说,Context Switch Rate小于5000是一个合理的标准,但是这个标准可能不太适用在所有情况下。 在实际应用中,需要根据具体情况选择合适的指标和计算方法,以确保系统的性能和稳定性。 压力测试衡量CPU的三个...

    aix5.3 Switch Network Interface for eServer™ pSeries® High Performance Switch Guide

    - **网络表服务(Network Table Services)**:提供了一种机制,用于管理和优化网络资源分配,确保网络流量的均衡和合理利用,这对于大型网络环境下的资源调度至关重要。 ### 结论 “AIX5.3 Switch Network ...

    linux进程切换核心代码switchto剖析实用教案.ppt

    首先,进程切换在Linux中分为两个阶段:上下文切换(Context Switch)和进程调度(Process Scheduling)。上下文切换是指保存当前进程的状态,并恢复下一个将要运行进程的状态。而进程调度则是决定哪个进程应该获得...

    RTT-Mini-context-switch.rar

    本项目聚焦于RT-Thread(Real-Time Thread)的一个重要概念——“上下文切换”(Context Switch),并具体演示了如何在STM32F10x微控制器上实现线程间的切换。STM32F10x是STMicroelectronics公司推出的基于ARM ...

    spring-context.jar

    spring-context-1.2.8.jar, spring-context-1.2.9.jar, spring-context-2.0-m2.jar, spring-context-2.0.1.jar, spring-context-2.0.2.jar, spring-context-2.0.4.jar, spring-context-2.0.6.jar, spring-context-...

    Android的context使用

    如上文示例所示,创建一个名为MainApplication的类,继承自Application,并在onCreate()方法中初始化全局Context: ```java public class MainApplication extends Application { private static Context mContext;...

    context-switch:Rust异步与Linux线程上下文切换时间的比较

    Rust异步和Linux线程上下文切换时间和内存使用情况的比较 这是一些试图以各种方式衡量上下文切换时间和任务内存使用情况的程序。 总之: 异步任务之间的上下文切换大约需要0.2µs,而内核线程之间的切换大约需要1.7...

    js中获取contextPath

    在Web开发中,`contextPath`是一个非常关键的概念,它代表了Web应用程序在服务器上的根目录路径。在Java Servlet环境中,`contextPath`是Servlet容器(如Tomcat、Jetty等)分配给Web应用的唯一标识,用于区分同一个...

    使用多个Context的CoreData

    1. **父子Context模式**:一个MOC可以作为另一个MOC的父级,这种模式下,子Context的变更会自动传播到父Context,最后由父Context统一保存到持久化存储。创建子Context的代码如下: ```swift let parentContext =...

    mcgs 组态软件 Linux操作系统 sp1组态软件

    MCGS(Machine Configuration & Graphic System)是一款常用的组态软件,主要应用于工业自动化领域的监控系统设计。在Linux操作系统上运行MCGS组态软件,可以提供稳定、高效且灵活的控制系统解决方案。本文将详细...

    反射获取Context的实例

    这在某些场景下非常有用,比如当我们需要在没有直接访问`Context`的情况下显示`Toast`消息。 首先,让我们了解`Context`在Android中的角色。`Context`是Android应用的基础组件,它提供了与系统交互的各种方法,如...

    pascal context

    PASCAL Context,全称为PASCAL Context Dataset,是计算机视觉领域一个重要的数据集,尤其在语义分割和场景理解任务中占据着至关重要的地位。该数据集是PASCAL VOC(Visual Object Classes Challenge)的扩展,旨在...

Global site tag (gtag.js) - Google Analytics