как запланировать две задачи? - PullRequest
8 голосов
/ 11 января 2012

Я новичок в управлении процессами / задачами. Я хотел бы наметить две задачи. предположим,

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 ]

15 голосов
/ 11 января 2012

Редактировать: Это ставится на голосование, поэтому я хотел бы добавить разъяснение для потомков. Это не очень хороший способ решить эту проблему - вы бы никогда не захотели сделать это вручную. Совместные пользовательские потоки хороши и могут быть использованы для реализации умных вещей, таких как сопрограммы, но если вы хотите сделать это, вам следует использовать библиотеку типа libcoroutine , которая обрабатывает кусочки волосков для вас. Однако, хотя это и не практичное решение, оно все же представляет интересную идею и является интересным примером планирования и ограничений чистого C99.

Это плохой ответ. Однако он не зависит от платформы и, кроме того, использует только функции, определенные в стандарте C99.

С другой стороны, он загружает процессор (в C99 нет функций sleep, поэтому нам приходится ждать-занят), использует то, что я могу назвать только магией, чтобы зарезервировать место в стеке и полностью злоупотребляет setjmp. Он даже использует глобальные переменные! И все же, это работает.

Техника называется взаимодействующими пользовательскими потоками, также называемыми волокнами. Я реализовал это, как я уже говорил, используя setjmp и longjmp. context_switch выполняет простое планирование Round Robin.

Это код:

#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
...
3 голосов
/ 11 января 2012

Ваш пример тривиален и может быть запланирован без обращения к какой-либо операционной системе, предоставляемой по расписанию, или даже к службам синхронизации ОС, однако в целом (для нетривиальных требований) в 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. Имейте в виду, что .Net Framework также предоставляет более простой интерфейс на основе классов для многопоточности.

3 голосов
/ 11 января 2012

Ну, было бы лучше, если бы вы могли указать свою операционную систему (или требование кроссплатформенности)

Йо может написать:

  • OS-зависимый код
  • Кроссплатформенный код (работает на нескольких ОС)

Для многозадачности каждый из вышеперечисленных может использовать:

  • Темы или
  • Процессы
  • Таймеры

нелогич-. 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) + threads: используйте функцию pthread_create для создания потоков
  • Windows + потоки / процессы: используйте функцию CreateThread () или CreateProcess ()
  • Кроссплатформенность: используйте специальные библиотеки высокого уровня, такие как GLIB, для создания потоков / процессов
2 голосов
/ 11 января 2012

Следующее создает две темы.Нить № 1 печатается один раз в минуту, а нить № 2 печатается один раз в 2 минуты.Эти потоки будут запланированы планировщиком вашей ОС.В Linux у нас есть cfs для планирования.И чтобы получить общее представление о планировании, прочитайте это

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

Надеюсь, это поможет!

1 голос
/ 10 февраля 2012

Этот подход заключается в операциях setjmp и longjmp с использованием команды sleep.

#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);
}
1 голос
/ 11 января 2012

Самый простой, хотя и не точный способ сделать это - использовать функцию POSIX sleep() внутри бесконечного цикла.

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

Если вам нужно реализовать более сложные задачи, вас могут заинтересовать потоки POSIX и таймеры POSIX.

0 голосов
/ 11 января 2012

Я думаю, вы должны использовать алгоритм планирования, такой как Round-Robin, или создать свой собственный алгоритм.Здесь вы найдете несколько алгоритмов http://www.centos.org/docs/5/html/5.1/Virtual_Server_Administration/s2-lvs-sched-VSA.htmlВы можете найти примеры, как они реализованы и какие использовать.

...