c - hvordan man planlægger to opgaver?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg er nybegynder i proces/task management.
Jeg vil gerne planlægge to opgaver.
formode,


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


Så hvordan man planlægger dem, så jeg får mit ønskede output.


Jeg vil have, at den kører i Code :: Blocks (Windows).
Jeg vil have sjov1 at køre 1 min og sjov2 for at køre hvert 2 min.
Hvis jeg kan gøre det i to separate processer, så fortæl mig også hvordan kan jeg gøre det.
Skal jeg bruge semafor, mutex og alle?

Bedste reference


Dit eksempel er trivielt og kan planlægges uden at benytte sig af OS-planlægning eller endog OS-timing-tjenester, men generelt (for ikke-trivielle krav) i Windows, vil du bruge multi-threading og tillade OS at udføre planlægningen. main() er allerede en tråd, så du behøver kun at oprette en anden. I sin enkleste form:


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

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

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


Se Oprettelse af tråde til en mere komplet behandling af gevind i Win32. Vær opmærksom på, at .Net-rammen også giver en enklere klassebaseret grænseflade til tråde. [17]

Andre referencer 1


Rediger: Dette bliver opvokset, så jeg vil gerne tilføje en præcisering for eftertiden. Dette er ikke en god måde at løse dette problem på. Du vil aldrig gerne dette for hånd. Samarbejdende brugertråde er hyggelige og kan bruges til at implementere kloge ting som coroutines, men hvis du vil gøre det, skal du bruge et bibliotek som libcoroutin, der håndterer de hårede bits til dig. Men selvom det ikke er en praktisk løsning, udgør den stadig en interessant ide og er et interessant eksempel på planlægning og begrænsningerne af ren C99. [18]


Dette er et dårligt svar. Det er dog platform uafhængigt, og bruger kun funktioner, der er defineret i C99-standarden.


På den anden side griner den CPU'en (der er ingen sleep funktioner i C99, så vi er nødt til at vente), bruger hvad jeg kun kan kalde magi for at reservere plads på stakken og helt misbruger setjmp. Det bruger endda globale variabler! Og alligevel virker det.


Teknikken hedder kooperative brugertråde, også kaldet fibre. Jeg har implementeret det, som jeg nævnte, ved hjælp af setjmp og longjmp. context\_switch gør simple Round Robin planlægning.


Dette er koden:


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

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

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


Og dette er den output, jeg får:


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

Andre referencer 2


Nå ville det være bedre, hvis du kunne angive dit operativsystem (eller kravet om crossplatformness)


Du kan skrive:



  • OS-afhængig kode

  • Cross platform-kode (arbejder på flere operativsystemer)



For multitasking kan hver af ovenstående bruge:



  • tråde eller

  • Processer

  • Timere



examle. POSIX-kompatibelt OS (Som Linux), Brug af processer


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


  return 0;
}


Andre tilfælde:



  • POSIX (Linux/UNIX) + tråde: brug pthread\_create-funktion til at oprette tråde

  • Windows + tråde/processer: brug CreateThread () eller CreateProcess () -funktionen

  • Crossplatform: Brug special biblioteker på højt niveau som GLIB til at oprette tråde/processer


Andre referencer 3


Følgende opretter to tråde. Tråd 1 udskrives en gang om et minut, og tråd nr. 2 udskriver en gang om 2 minutter. Disse tråde vil blive planlagt af planlæggeren af ​​dit operativsystem. I Linux har vi cfs til at planlægge. Og for at få et overblik over planlægning, læs dette [19] [20]


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

    pthread\_exit(NULL);
}

void * fun2(void *thread\_id)
{
    int i;
    int *id = (int *) thread\_id;

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

    pthread\_exit(NULL);
}

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

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

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

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

    pthread\_exit(NULL);     

    return 0;
}


produktion:


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


Håber dette hjælper!

Andre referencer 4


Den enkleste, men ikke korrekte måde at gøre dette på er at bruge POSIX sleep() funktionen i en uendelig sløjfe.


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


Hvis du har mere komplekse opgaver at implementere, kan du være interesseret i POSIX-tråde og POSIX-timere.

Andre referencer 5


Denne tilgang er gennem setjmp- og longjmp-operationer ved hjælp af 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 
");
                longjmp(env,3);
        }
        else if(i==2){
                printf("It will be printed in every 2 min 
");
                longjmp(env,1);
        }
        else if(i==3)
        {
                sleep(1);
                printf("It will be printed in every 1 min 
");
                longjmp(env,2);
        }
        longjmp(env,1);
}

Andre referencer 6


Jeg tror, ​​du skal bruge en planlægningsalgoritme som Round-Robin, eller lav din egen algoritme.

Her finder du nogle algoritmer http://www.centos.org/docs/5/html/5.1/Virtual\_Server\_Administration/s2-lvs-sched-VSA.html
Du cand finder eksempler, hvordan de er implementeret, og hvilke der skal bruges. [21]