2012-01-11 29 views
8

Tôi là người mới trong quản lý quy trình/nhiệm vụ. Tôi muốn lên lịch hai nhiệm vụ. giả sử,cách lên lịch hai tác vụ?

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

Vì vậy, cách lên lịch để tôi có được kết quả mong muốn.

Tôi muốn nó chạy trong Mã :: Khối (Windows). Tôi muốn fun1 chạy 1 phút và fun2 để chạy 2 phút một lần. Nếu tôi có thể làm điều đó trong hai quá trình riêng biệt, sau đó cho tôi biết làm thế nào tôi có thể làm điều đó. Tôi có cần sử dụng semaphore, mutex và tất cả không?

+4

tạo chủ đề riêng biệt với kích hoạt hẹn giờ xuất hiện trong tâm trí của tôi. bạn không thể làm điều đó trong tiêu chuẩn C mà không cần sự giúp đỡ của hệ điều hành – Donotalo

+2

Vì vậy, những gì bạn muốn là cho fun1 để chạy mỗi phút và fun2 để chạy mỗi 2 phút? Và ý của bạn là để chúng hoạt động, hay bạn muốn các quá trình riêng biệt, như câu hỏi của bạn ngụ ý? Cuối cùng, hệ điều hành nào? – cha0site

+0

Vui lòng đọc [this] (http://en.wikipedia.org/wiki/Scheduling_ (computing)) để biết tổng quan về lịch trình là gì? –

Trả lời

3

dụ của bạn là tầm thường và có thể được sắp xếp mà không cần đến bất kỳ kế hoạch OS đã cung cấp hoặc thậm chí thời gian OS dịch vụ, tuy nhiên nói chung (đối với các yêu cầu không tầm thường) trong Windows, bạn sẽ sử dụng đa luồng và cho phép hệ điều hành thực hiện lập lịch biểu. main() đã là một chủ đề, vì vậy bạn chỉ cần tạo một chủ đề khác. Ở dạng đơn giản nhất của nó:

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

Xem Creating Threads cho một điều trị đầy đủ hơn về luồng trong Win32. Hãy lưu ý rằng khuôn khổ .Net cũng cung cấp một giao diện dựa trên lớp đơn giản hơn cho luồng.

+0

Bạn nói đúng, nhưng tôi muốn viết mã theo tiêu chuẩn C. Tôi sử dụng Code :: Blocks IDE. Nó không hỗ trợ sleep() hoặc delay(). –

+1

@Rasmi Ranjan Nayak: Điều này không đúng. Sleep() là một hàm Windows API, giống như CreateThread. Nó không nên được kết nối với IDE theo bất kỳ cách nào. Mặt khác, nếu bạn không viết ứng dụng gốc Win32, điều đó có nghĩa là bạn đang sử dụng một số thư viện (wxWidgets?), Vì vậy, hãy xem tài liệu hướng dẫn về hỗ trợ giấc ngủ và luồng. – LiMar

+0

@LiMar: Có thể bạn đã đúng. Nhưng khi tôi đã thử nó đã cho tôi một lỗi. Thậm chí bạn có thể thử tương tự trong Code :: Blocks. viết một chương trình đơn giản. 'main() {sleep (1000); printf ("Ngủ được thực hiện"); } ' –

2

Phần sau tạo hai chuỗi. Chủ đề # 1 in một lần trong một phút và bản in # 2 một lần trong 2 phút. Những chủ đề này sẽ được lên lịch bởi bộ lập lịch của hệ điều hành của bạn. Trong Linux, chúng tôi có cfs để lên lịch. Và để có được một cái nhìn tổng quan về lịch trình, đọc 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; 
} 

đầu ra:

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

Hope this helps!

+0

Tôi nghĩ rằng bạn đã làm một phần lớn của sự giúp đỡ. Điều này thực sự giúp tôi hiểu hệ điều hành UNIX. Nhưng tôi vẫn còn một câu hỏi nữa, mà không tạo chuỗi, chúng ta có thể làm tương tự trong Tiêu chuẩn C không? –

+0

@ user1105805 Tôi rất vui! Cảm ơn! :) –

+0

@ user1105805 Để tạo chủ đề, bạn cần một thư viện chuỗi như 'pthread' cung cấp cơ sở hạ tầng cơ bản để tạo, quản lý, theo dõi và xóa chủ đề. –

3

Vâng, nó sẽ tốt hơn nếu bạn có thể xác định hệ điều hành của bạn (hoặc các yêu cầu của crossplatformness)

Yo có thể viết:

  • OS mã phụ thuộc
  • đang Cross-nền tảng (làm việc trên nhiều hệ điều hành)

Để đa nhiệm, mỗi thao tác trên có thể sử dụng:

  • Chủ đề hay
  • Processes
  • Timers

examle.POSIX OS tương thích (như Linux), Sử dụng các quy trình

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

Các trường hợp khác:

  • POSIX (Linux/UNIX) + đề: chức năng sử dụng pthread_create tạo chủ đề
  • Windows + đề/processes: sử dụng chức năng CreateThread() hoặc CreateProcess()
  • Crossplatform: sử dụng các thư viện cấp cao đặc biệt như GLIB để tạo các luồng/quy trình
+0

Tôi đang làm việc trong Mã khối IDE, nền tảng Windows –

+0

Vì vậy, ví dụ của tôi hơi không phù hợp với bạn. Bạn có thể muốn thêm một số thẻ "cửa sổ" vào câu hỏi của mình. Tìm các ví dụ về cách sử dụng CreateThread(), có rất nhiều trong mạng. – LiMar

+0

ngủ (60) là xấu: việc thực hiện printf mất một thời gian, vì vậy bạn có thể nhận được ít hơn 60 bản in mỗi phút! –

1

Cách đơn giản nhất, mặc dù không chính xác, cách làm này là sử dụng hàm POSIX sleep() bên trong vòng lặp vô hạn.

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

Nếu bạn có nhiều nhiệm vụ phức tạp để triển khai, bạn có thể quan tâm đến các chủ đề POSIX và bộ định thời POSIX.

+1

Vì "Windows" đã được đề cập đến trong câu hỏi, nên cần có 'Sleep32' Sleep (60000) 'thay vì POSIX' sleep (60) ' – Clifford

+0

Tôi hy vọng rằng Windows có giao diện POSIX, với chữ thường' sleep() ' – mouviciel

+1

Hope tất cả những gì bạn thích; nó không. Và nó luôn luôn hữu ích để trả lời các câu hỏi trong các điều khoản được yêu cầu; đặc biệt là đối với một người mới có thể không hiểu rằng môi trường đích có các thư viện và API khác nhau. Có (một số giải pháp) [http://msdn.microsoft.com/en-us/library/y23kc048.aspx], hoặc bạn có thể sử dụng Cygwin, nhưng trong trường hợp này nó là một cái búa-búa để crack một hạt, đặc biệt là khi chức năng Win32 Sleep có độ phân giải mili giây thực tế là linh hoạt hơn. 'unsigned sleep (unsigned s) {Sleep (s/1000); trả về 0; } 'nếu bạn thực sự nhấn mạnh ;-) – Clifford

15

Chỉnh sửa: Điều này đang được tăng hạng, vì vậy tôi muốn thêm làm rõ cho hậu thế. Đây không phải là cách hay để giải quyết vấn đề này - bạn sẽ không bao giờ muốn thực hiện việc này bằng tay. Chủ đề người dùng hợp tác là tốt đẹp, và có thể được sử dụng để thực hiện những điều thông minh như coroutines, nhưng nếu bạn muốn làm điều đó bạn nên sử dụng một thư viện như libcoroutine xử lý các bit lông cho bạn. Tuy nhiên, mặc dù đây không phải là giải pháp thiết thực nhưng nó vẫn là một ý tưởng thú vị và là một ví dụ thú vị về lập kế hoạch và những hạn chế của C99 thuần túy.

Đây là câu trả lời không tốt. Tuy nhiên, nó là nền tảng độc lập, và hơn thế nữa, chỉ sử dụng các hàm được định nghĩa trong tiêu chuẩn C99.

Mặt khác, nó nâng cấp CPU (không có chức năng sleep trong C99, vì vậy chúng tôi phải bận), sử dụng những gì tôi chỉ có thể gọi phép thuật để đặt chỗ trên ngăn xếp và hoàn toàn lạm dụng setjmp. Nó thậm chí còn sử dụng các biến toàn cầu! Tuy nhiên, nó hoạt động.

Kỹ thuật này được đặt tên là chủ đề người dùng hợp tác, còn gọi là sợi. Tôi đã thực hiện nó, như tôi đã đề cập, sử dụng setjmplongjmp. context_switch lập lịch trình Round Robin đơn giản.

Đây là mã:

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

Và đây là kết quả tôi nhận được:

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

cảm ơn. ý tưởng rất thú vị. Tôi không có đủ thời gian để đọc và kiểm tra, sẽ làm điều đó sau. :) – Donotalo

+0

@ cha0site: Ya Đó là một ý tưởng khá thú vị. Cảm ơn –

+0

Nó minh họa setjmp() _very_ độc đáo, tôi chỉ _had_ để upvote. Lấy làm tiếc. –

1

Cách tiếp cận này thông qua các hoạt động setjmp và longjmp bằng lệnh ngủ.

#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); 
} 
Các vấn đề liên quan