如何安排两个任务?

时间:2012-01-11 07:59:48

标签: c windows operating-system embedded scheduled-tasks

我是流程/任务管理的新手。 我想安排两个任务。 假设,

fun1()  
{  
    printf("It will be printed in every 1 min \n");  
}  
fun2()  
{  
    printf("It will be printed in every 2 min \n");  
}  
main()  
{  
    fun1();  
    fun2();  
}

所以如何安排它们,以便我得到我想要的输出。

我希望它在Code :: Blocks(Windows)中运行。 我想fun1运行1分钟,fun2运行每2分钟一次。 如果我可以在两个单独的过程中完成它,那么告诉我我该怎么做。 我是否需要使用信号量,互斥量和所有?

7 个答案:

答案 0 :(得分:15)

编辑:这是越来越高,所以我想为后代添加一个澄清。这不是解决此问题的好方法 - 您永远想要手动执行此操作。合作用户线程很好,可以用来实现协程等聪明的东西,但如果你想这样做,你应该使用像libcoroutine这样的库来处理毛茸茸的东西。然而,虽然这不是一个实用的解决方案,但它仍然提出了一个有趣的想法,并且是一个有趣的调度示例和纯C99的局限性。

这是一个糟糕的答案。但是,它与平台无关,而且仅使用C99标准中定义的函数。

另一方面,它占用CPU(C99中没有sleep函数,所以我们必须忙等待),使用我只能调用魔法来保留堆栈上的空间,并完全滥用setjmp。它甚至使用全局变量!然而,它有效。

该技术被称为合作用户线程,也称为光纤。正如我所提到的,我使用setjmplongjmp来实现它。 context_switch执行简单的循环调度。

这是代码:

#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;
}

这是我得到的输出:

$ 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
...

答案 1 :(得分:3)

嗯,如果你能指定你的操作系统(或跨平台的要求)会更好

哟可以写:

  • 操作系统相关代码
  • 跨平台代码(在多个操作系统上工作)

对于多任务处理,上述各项都可以使用:

  • 主题或
  • 过程
  • 计时器

<强> Examle。 POSIX兼容的操作系统(如Linux),使用流程

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;
}

其他情况:

  • POSIX(Linux / UNIX)+线程:使用pthread_create函数创建线程
  • Windows +线程/进程:使用CreateThread()或CreateProcess()函数
  • Crossplatform:使用GLIB等特殊高级库来创建线程/进程

答案 2 :(得分:3)

您的示例很简单,无需借助任何操作系统提供的调度甚至操作系统计时服务即可进行安排,但是一般情况下(对于Windows中的非平凡要求),您可以使用多线程并允许操作系统执行调度。 main()已经是一个帖子,所以你只需要创建另一个。最简单的形式:

#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) ;
    }
}  

有关Win32中线程的更完整处理,请参阅Creating Threads。请注意,.Net框架还为线程提供了一个更简单的基于类的接口。

答案 3 :(得分:2)

以下创建两个线程。线程#1每分钟打印一次,线程#2在2分钟内打印一次。这些线程将由您的操作系统的调度程序安排。在Linux中,我们有cfs来进行调度。要了解日程安排,请阅读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;
}

输出:

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

希望这有帮助!

答案 4 :(得分:1)

最简单但不准确的方法是在无限循环中使用POSIX sleep()函数。

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

如果您要执行更复杂的任务,您可能对POSIX线程和POSIX计时器感兴趣。

答案 5 :(得分:1)

这种方法是通过使用sleep命令的setjmp和longjmp操作。

#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);
}

答案 6 :(得分:0)

我认为你应该使用像Round-Robin这样的调度算法,或者制作你自己的算法。
在这里您可以找到一些算法http://www.centos.org/docs/5/html/5.1/Virtual_Server_Administration/s2-lvs-sched-VSA.html您可以找到示例,如何实现它们以及使用哪些算法。