天天看點

一個定時器的普通實作,多程序實作和多線程實作的對比

要求實作一個簡單的定時器,該程式要求的輸入格式為:

N prompt message

其中N表示時間,prompt message表示提示資訊。即過了N秒之後要在終端上顯示出提示資訊。一共用了三種方式實作:(1)最普通的方式,阻塞I/0+同步。(2)使用程序實作。(3)使用線程實作。

/*alarm.c*/ 

#include "../error.h" 

#include<time.h> 

int main(int argc,char *argv[]) 

        int seconds; 

        char line[128]; 

        char message[64]; 

        while(NULL != fgets(line,sizeof(line),stdin)) 

        { 

                if( 2 > sscanf(line,"%d %64[^\n]",&seconds,message)) 

                        fprintf(stderr,"Bad Command\n"); 

                else 

                { 

                        sleep(seconds); 

                        fprintf(stdout,"%s\n",message); 

                } 

        } 

        return 0; 

評注:

1.常量和函數比較的時候,将常量放在前面可以防止将==寫成=,因為編譯器會報錯。

2.sscanf為從一個字元緩沖區中格式化讀取資料。注意字元緩沖區放在第一個參數位置。使用%N可以控制讀取字元的數量,中括号的作用和正規表達式中的作用一樣,将不讀取的字元排除掉或者僅讀取中括号内指定的字元集,成功時,傳回讀取的參數的個數。

3.使用fgets+sscanf,簡化了從指令行中提取參數問題。

3.fgets從指定的檔案描述符中讀取一行字元串,失敗時傳回NULL。

4.對于每個函數都添加了判斷語句,特别有助于調試。

/*alarm_fork.c*/ 

#include <sys/types.h> 

#include<wait.h> 

        pid_t pid; 

                if(2 > sscanf(line,"%d %64[^\n]",&seconds,message)) 

                        fprintf(stdout,"Bad command.\n"); 

                        continue; 

                        pid = fork(); 

                        if((pid_t)-1 == pid) 

                        { 

                                error_abort("fork error..."); 

                        } 

                        else if((pid_t)0 == pid) 

                                sleep(seconds); 

                                fprintf(stdout,"%s\n",message); 

                                exit(0); 

                        else 

                                do 

                                { 

                                        pid = waitpid((pid_t)-1,NULL,WNOHANG); 

                                        if((pid_t)-1 == pid) 

                                        { 

                                                error_abort("waitpid error..."); 

                                        } 

                                }while((pid_t)0 != pid); 

1.pid_t這個類型在sys/types.h頭檔案中。

2.比較的時候要進行強制類型轉換,比如判斷程序id是不是為0,就要使用(pid_t)0 == pid這樣的判斷語句。

3.waitpid的第一個參數設定為-1,第三個參數設定為WNOHANG,表示非阻塞等待任何一個子程序。如果發現一個子程序傳回,立即再判斷是否還有其他程序傳回。可以迅速的釋放不再使用的資源。

/*alarm_thread.c*/ 

#include <pthread.h> 

#include <time.h> 

typedef struct alarm_tag 

}alarm_t,*alarm_p; 

void * alarm_thread(void * arg) 

        int status; 

        status = pthread_detach(pthread_self()); 

        if(0 != status) 

                err_abort("detaching thread failure...",status); 

        alarm_p alarm = (alarm_p) arg; 

        sleep(alarm->seconds); 

        fprintf(stdout,"%s\n",alarm->message); 

        pthread_t thread; 

        alarm_p alarm; 

                alarm = (alarm_p) malloc(sizeof(alarm_t)); 

                if( NULL == alarm) 

                        error_abort("Allocating alarm failure..."); 

                if(2 > sscanf(line,"%d %64[^\n]",&alarm->seconds,alarm->message)) 

                        fprintf(stdout,"%s\n","Bad command"); 

                        free(alarm); 

                        status = pthread_create(&thread,NULL,alarm_thread,(void *)alarm); 

                        if(0 != status) 

                                err_abort("creating thread failure...",status); 

1.Pthreads相關的類型,接口原型,常量都在pthread.h這個頭檔案中,編譯的時候要加 -lpthread.

2.由于線程的參數隻有一個,是以要将傳給線程的所有參數封裝到一個結構體中。

使用普通方式,多程序,多線程的比較

alarm一次隻能發出一個定時請求。如果發出一個10分鐘的請求,那麼必須要等十分鐘才能發出下一個請求。多程序解決了這個同步問題,但是在一個系統中,一個使用者能夠啟動的程序的數量是非常有限的,多線程受到這個影響要小得多。

多線程的幾個好處

(1)發掘多核計算潛力

(2)發掘程式自身的并發性

(3)子產品式的程式設計模型,可以更加清晰的表達不同僚件之間的關系

本文轉自hipercomer 51CTO部落格,原文連結:http://blog.51cto.com/hipercomer/908959

繼續閱讀