Write a C program to measure time spent in context switch in Linux OS

后端 未结 6 1386
独厮守ぢ
独厮守ぢ 2020-12-04 07:54

Can we write a c program to find out time spent in context switch in Linux? Could you please share code if you have one? Thanks

6条回答
  •  北荒
    北荒 (楼主)
    2020-12-04 08:09

    Measuring the cost of a context switch is a little trickier. We can compute time spent in context switch by running two processes on a single CPU, and setting up three Linux pipes between them;

    • two pipes for sharing string between the process and
    • 3rd one will be used to share a time spent at child process.

    The first process then issues a write to the first pipe, and waits for a read on the second; upon seeing the first process waiting for something to read from the second pipe, the OS puts the first process in the blocked state, and switches to the other process, which reads from the first pipe and then writes to the second. When the second process tries to read from the first pipe again, it blocks, and thus the back-and-forth cycle of communication continues. By measuring the cost of communicating like this repeatedly, you can make a good estimate of the cost of a context switch.

    One difficulty in measuring context-switch cost arises in systems with more than one CPU; what you need to do on such a system is ensure that your context-switching processes are located on the same processor . Fortunately, most operating systems have calls to bind a process to a particular processor; on Linux, for example, the sched_setaffinity()call is what you’re looking for. By ensuring both processes are on the same processor, you are making sure to measure the cost of the OS stopping one process and restoring another on the same CPU.

    Here I'm posting my solution for computing context-switch between processes.

        #define _GNU_SOURCE
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    pid_t getpid( void )
    {
        return syscall( __NR_getpid );
    }
    
    int main()
    {
        /*********************************************************************************************
            To make sure context-switching processes are located on the same processor :
            1. Bind a process to a particular processor using sched_setaffinity.    
            2. To get the maximum priority value (sched_get_priority_max) that can be used with 
               the scheduling algorithm identified by policy (SCHED_FIFO).** 
            **********************************************************************************************/
    
        cpu_set_t set;
        struct sched_param prio_param;
        int prio_max;
    
        CPU_ZERO( &set );
        CPU_SET( 0, &set );
            memset(&prio_param,0,sizeof(struct sched_param));
    
        if (sched_setaffinity( getpid(), sizeof( cpu_set_t ), &set ))
        {
            perror( "sched_setaffinity" );
                    exit(EXIT_FAILURE);
        }
    
        if( (prio_max = sched_get_priority_max(SCHED_FIFO)) < 0 )
        {
                    perror("sched_get_priority_max");
            }
    
        prio_param.sched_priority = prio_max;
        if( sched_setscheduler(getpid(),SCHED_FIFO,&prio_param) < 0 )
        {
                    perror("sched_setscheduler");
                    exit(EXIT_FAILURE);
            }
    
        /*****************************************************************************************************
            1. To create a pipe for a fork, the parent and child processes use pipe to read and write, 
               read and write string, using this for context switch.
            2. The parent process first to get the current timestamp (gettimeofday), then write to the pipe,. 
               Then the child should be read in from the back, 
               then the child process to write string, the parent process reads. 
               After the child process to get the current timestamp. 
               This is roughly the difference between two timestamps n * 2 times the context switch time.
        *******************************************************************************************************/
    
        int     ret=-1;
        int     firstpipe[2];
        int     secondpipe[2];
        int     timepipe[2];
            int     nbytes;
            char    string[] = "Hello, world!\n";
            char    temp[] = "Sumit Gemini!\n";
            char    readbuffer[80];
            char    tempbuffer[80];
        int     i=0;
        struct  timeval start,end;
    
        // Create an unnamed first pipe
            if (pipe(firstpipe) == -1) 
        {
                fprintf(stderr, "parent: Failed to create pipe\n");
                return -1;
            }
    
        // create an unnamed Second pipe
            if (pipe(secondpipe) == -1) 
        {
                fprintf(stderr, "parent: Failed to create second pipe\n");
                return -1;
            }
    
        // Create an unnamed time pipe which will share in order to show time spend between processes
            if (pipe(timepipe) == -1) 
        {
                fprintf(stderr, "parent: Failed to create time pipe\n");
                return -1;
            }
    
    
        if((ret=fork())==-1)
            perror("fork");
        else if(ret==0)
        {
                    int n=-1;
            printf("Child  ----> %d\n",getpid());
    
            for(n=0;n<5;n++)
            {
                        nbytes = read(firstpipe[0], readbuffer, sizeof(readbuffer));
                        printf("Received string: %s", readbuffer);
                write(secondpipe[1], temp, strlen(temp)+1);
            }
    
            gettimeofday(&end,0);
                    n = sizeof(struct timeval);
    
                    if( write(timepipe[1],&end,sizeof(struct timeval)) != n )
            {
                    fprintf(stderr, "child: Failed to write in time pipe\n");
                            exit(EXIT_FAILURE);
                    }
    
        }
        else
        {
            double switch_time;
                    int n=-1;
            printf("Parent  ----> %d\n",getpid());
            gettimeofday(&start,0);
                    /* Read in a string from the pipe */
    
            for(n=0;n<5;n++)
            {
                write(firstpipe[1], string, strlen(string)+1);
                read(secondpipe[0], tempbuffer, sizeof(tempbuffer));
                        printf("Received temp: %s", tempbuffer);
            }
    
            n = sizeof(struct timeval);
                    if( read(timepipe[0],&end,sizeof(struct timeval)) != n )
            {
                    fprintf(stderr, "Parent: Failed to read from time pipe\n");
                            exit(EXIT_FAILURE);
                    }
    
            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/(5*2));
    
    
        }   
    
        return 0;
    }
    

提交回复
热议问题