how to schedule two tasks?

霸气de小男生 提交于 2019-12-03 13:07:55

Your example is trivial and can be scheduled without resorting to any OS provided scheduling or even OS timing services, however in general (for non-trivial requirements) in Windows, you would use multi-threading and allow the OS to perform the scheduling. main() is already a thread, so you only need create one other. In its simplest form:

#include <stdio.h>
#include <windows.h>

DWORD WINAPI OneMinthread( LPVOID lpParam ) 
{  
    for(;;)
    {
        printf("It will be printed in every 1 min \n");  
        Sleep(60000) ;
    }
}  

int main()  
{  
    CreateThread( NULL, 0, OneMinthread, 0, 0, 0) ;
    for(;;)
    {
        printf("It will be printed in every 2 min \n");  
        Sleep(120000) ;
    }
}  

See Creating Threads for a more complete treatment of threading in Win32. Be aware that the .Net framework also provides a simpler class based interface to threading.

Edit: This is getting upvoted, so I'd like to add a clarification for posterity. This isn't a good way to solve this problem - you would never want to do this by hand. Co-operative user threads are nice, and can be used to implement clever things like coroutines, but if you want to do that you should use a library like libcoroutine that handles the hairy bits for you. However, while this isn't a practical solution, it still presents an interesting idea and is an interesting example of scheduling and the limitations of pure C99.

This is a bad answer. However, it is platform-independent, and moreover, only uses functions that are defined in the C99 standard.

On the other hand, it hogs the CPU (there are no sleep functions in C99, so we have to busy-wait), uses what I can only call magic to reserve space on the stack, and completely abuses setjmp. It even uses global variables! And yet, it works.

The technique is named co-operative user threads, also called fibers. I implemented it, as I mentioned, using setjmp and longjmp. The context_switch does simple Round Robin scheduling.

This is the code:

#include <stdio.h>
#include <setjmp.h>
#include <time.h>

static jmp_buf jmp[2];
static int cur;

void context_switch()
{
    /* sleep(1) */ /* C99 doesn't have any sleeping functions */
    if (!setjmp(jmp[cur])) {
        if ((sizeof(jmp)/sizeof(*jmp)) == ++cur)
            cur = 0;
        longjmp(jmp[cur], 1);
    }
}

void fun2()
{
    char cushion[1000]; /* reserve some stack space */
    time_t old_time, new_time;
    cushion[0] = '@'; /* don't optimize my cushion away */
    old_time = time(NULL);
        cur = 1; /* the first thread to context switch is this one */
    setjmp(jmp[1]);
    while (1) {
        context_switch();
        new_time = time(NULL);
        if ((new_time - old_time) > (2 * 60)) {
            old_time = new_time;
            printf("Printed every 2 minutes\n");
        }
    }
}

void fun1()
{
    char cushion[1000]; /* reserve some stack space */
    time_t old_time, new_time;
    cushion[0] = '@'; /* don't optimize my cushion away */
    if (!setjmp(jmp[0]))
        fun2();
    old_time = time(NULL);
    while (1) {
        context_switch();
        new_time = time(NULL);
        if ((new_time - old_time) > (1 * 60)) {
            old_time = new_time;
            printf("Printed every 1 minute\n");
        }
    }
}

int main(int argc, char **argv)
{
    fun1();
    return 0;
}

And this is the output I get:

$ gcc -ggdb -std=c99 -o silly silly_setjmp.c 
$ ./silly
Printed every 1 minute
Printed every 2 minutes
Printed every 1 minute
Printed every 1 minute
...

Well, it would be better if you could specify your operating system (or the requirement of crossplatformness)

Yo can write:

  • OS dependent code
  • Cross-platform code (working on multiple OSs)

For the multitasking each of above can use :

  • Threads or
  • Processes
  • Timers

Examle. POSIX compatible OS (Like Linux), Using processes

void fun1()
{  
   for(;;)     
   {
     printf("It will be printed in every 1 min \n");
     sleep(60);
   }
}
void fun2()
{  
   for(;;)     
   {
     printf("It will be printed in every 2 min \n");
     sleep(2*60);
   }
}
int main()
{
  pid_t pID = fork();
  if ( 0 == pID ) // new, child process
  {
      func1();
  }
  else if(pID<0)
  {
      printf("Fork failed 1\n");
  }
  else //parent process succeeded forking and now continue running
  {
      func2();
  }


  return 0;
}

Other cases:

  • POSIX(Linux/UNIX) + threads: use pthread_create function to create threads
  • Windows + threads/processes: use CreateThread() or CreateProcess() function
  • Crossplatform: use special high level libraries like GLIB to create threads/processes

The following creates two threads. Thread #1 prints once in a minute and thread #2 prints once in 2 minutes. These threads will be scheduled by the scheduler of your OS. In Linux, we have cfs to do the scheduling. And to get an overview on scheduling, read this

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define NOTHREADS 2

void * fun1(void *thread_id)
{
    int i;
    int *id = (int *) thread_id;

    while(1) {
        usleep(1000 * 1000 * 60);
        printf("1 minute \n");
    }

    pthread_exit(NULL);
}

void * fun2(void *thread_id)
{
    int i;
    int *id = (int *) thread_id;

    while(1) {
        usleep(2000 * 1000 * 60);
        printf("2 minute \n");
    }

    pthread_exit(NULL);
}

int main()
{
    pthread_t tids[NOTHREADS];
    int ids[NOTHREADS] = {1, 2};
    int ret; 
    long t;
    int i;

    printf("Creating fun1 thread \n");
    ret = pthread_create(&tids[0], NULL, fun1, &ids[0]);
    if (ret) {
        printf("unable to create thread! \n");
        exit(-1);
    } 

    printf("Creating fun2 thread \n");
    ret = pthread_create(&tids[1], NULL, fun2, &ids[1]);
    if (ret) {
        printf("unable to create thread! \n");
        exit(-1);
    } 

    for (i=0 ; i<NOTHREADS; i++) {
        pthread_join(tids[i], NULL);
    }

    pthread_exit(NULL);     

    return 0;
}

output:

$ gcc t.c -lpthread
$ ./a.out 
Creating fun1 thread 
Creating fun2 thread 
1 minute 
2 minute 
1 minute 
1 minute 
^C
$ 

Hope this helps!

The simplest, though not accurate, way of doing this is to use the POSIX sleep()function inside an infinite loop.

while(1)
{
    fun1();
    sleep(60);
    fun1();
    fun2();
    sleep(60);
}

If you have more complex tasks to implement, you may be interested in POSIX threads and POSIX timers.

This approach is through setjmp and longjmp operations using sleep command.

#include<stdio.h>
#include<setjmp.h>

main()
{
        jmp_buf env;
        int i;

        i=setjmp(env);
        if(i==1)
        {
                sleep(1);
                printf("It will be printed in every 1 min \n");
                longjmp(env,3);
        }
        else if(i==2){
                printf("It will be printed in every 2 min \n");
                longjmp(env,1);
        }
        else if(i==3)
        {
                sleep(1);
                printf("It will be printed in every 1 min \n");
                longjmp(env,2);
        }
        longjmp(env,1);
}

I think you should use a scheduling algorithm like Round-Robin, or make your own algorithm.
Here you find some algorithms http://www.centos.org/docs/5/html/5.1/Virtual_Server_Administration/s2-lvs-sched-VSA.html
You cand find examples, how they are implemented, and which to use.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!