• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            不在浮沙筑高臺-demons
            C++/OS/disassembly/Anti-virus
            posts - 5,  comments - 5,  trackbacks - 0

            昨天接到操作系統課程設計題目,是用信號量同步進程(線程)的,由于要用到Windows API ,好幾個同學問我API是干什么的,由于大家都沒接觸過,不知怎么用,所以我就以課設題目為例,給大家介紹一下API的一些基本知識。但請您注意,本文旨在介紹API使用,而不是給您提供現成的代碼讓您直接復制到課程設計報告中去,您應該只把這做為一份參考,然后寫出自己的代碼。好了,我們從最基本的講起,首先看題目:

            Linux或Windows或Unix環境下,采用系統調用中的信號量、P、V操作,編程解決以問題。讀者與寫者問題。一個數據集為多個并發進程所共享,其中一些進程只要求讀該數據集的內容,這些進程稱為“讀者”,而另一些進程則要求修改該數據集的內容,這些進程稱為“寫者”。具體要求是:允許多個讀者同時讀該數據集的內容;若有一個寫者在寫,則其他讀者不能讀;若一個寫者在寫或有其他讀者在讀,則其他寫者均被拒絕;當一個寫者正在寫,而有多個讀者與寫者在等待時,寫者應優先喚醒。請用P、V操作寫出進程的同步算法。要求打印:初始狀態,中間變化的狀態信息,以及最終狀態信息。

            我以Windows做為示例,考慮到大家并非都懂C++,故代碼用C寫。分析:

            1.理想狀態:我們程序中完全和作業中的方式一樣,比如定義信號量用 semaphore mutex; P操作就直接P(mutex),V操作就直接V(mutex),盡量避免直接使用API。

            好的,我們首先實現這兩種功能。由于筆者平時開發習慣,都會在特定的工程中的函數、數據類型加上工程標志,這個項目是Operating system Course Design,我就取OSCD,做為函數和數據類型前綴。所以上面的semaphore mutex;定義信號量的方式就變為OSCD_semaphore mutex(只是換了個衣服而已)。下面介紹第一個API函數(為了先避免字符編碼的問題,看我這個不要對函數名后的A太過在意,以后接觸Windows編程后,你自然就懂了):

            HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,LONG lInitialCount,LONG lMaximumCount,LPCSTR lpName );首先看一下這個中的數據類型;其實 LONG 就是typedef long LONG;  LPCSTR 就是char * (字符串的指針),LPSECURITY_ATTRIBUTES 和HANDLE目前不是一兩句話能將清楚的,LPSECURITY_ATTRIBUTES 可以先直接忽略掉,你可以把HANDLE 理解為操作信號的“手柄”,也可以先理解為指向信號量的類型,以后我們對信號量的操作就是通過它來完成的,在直接一點,我們就可以把它就當作是信號量,其中lInitialCount就好比我們作業里mutex.value,中的value,我們需要在調用這個函數時給它賦初值,lMaximumCount是指定信號量的最大值,本例中我們取10,最后一個參數lpName 課設用不到,直接傳NULL。回過頭來看看這個函數實現的功能:創建一個信號量并返回,在創建信號量時我們必須對信號量賦初值。也就是說我們真正用到的參數只有一個lInitialCount,下面我們對其封裝;

             

              typedef HANDLE OSCD_semaphore    //這樣以后就可以直接這樣 OSCD_semaphore mutex;定義信號量了;
               #define MAX_SEM_COUNT 10 //信號量最大值我們取10
            OSCD_semaphore OSCD_CreateSemaphore(int nInitialCount)  //參數是初值,返回的是信號量。
            {
                OSCD_semaphore hSemaphore;
                if (nInitialCount>MAX_SEM_COUNT){ //
                    printf("semaphore count too big ,please specify a value range 0 to 10\n");
                    exit(0);
                } 
                hSemaphore=::CreateSemaphoreA(NULL,nInitialCount,MAX_SEM_COUNT,NULL );//真正創建信號量
                if (hSemaphore == NULL) {
                    printf("CreateSemaphore error: %d\n", GetLastError());
                    exit(0);
                }
                return hSemaphore;
            }

             

            拿本例中的 mutex 為例;我們只需要這么初始化它:OSCD_semaphore mutex;//定義mutex,    mutex= OSCD_CreateSemaphore(1);//初始化;下面是刪除信號量的函數:

             

            void OSCD_DelSemaphore( OSCD_semaphore semaphore)
            {
                ::CloseHandle(semaphore);//你可以認為這個API可以刪除掉用上面函數創建的信號量,要刪除那個信號量,參數就是哪個信號量,比如OSCD_DelSemaphore(mutex);
            }

             

            P操作:按照P操作的定義,先對信號量值減1,然后再和0比較,若大于等于0,就可以得到資源繼續運行,小于0的話就等待。我先給出代碼再做解釋:

             

            void P( OSCD_semaphore semaphore)
            {
                ::WaitForSingleObject(semaphore,INFINITE);//這個API是等待信號量的函數,若等待的信號量值大于等于0時,便返回,程序繼續運行,若無資源了,便會一直等待,函數不會返回,程序就不能再往下運行
            }

             

            V操作:使信號量加1;很簡單:

             

            void V(OSCD_semaphore semaphore)
            {
                if (!::ReleaseSemaphore(semaphore,1,NULL))//該API使信號量加1(第二個參數,如果你想使它一次加2,只需給第二個參數傳2 即可)
                {
                    printf("release semaphore error: %d\n",GetLastError());//檢查上面函數是否調用成功
                     exit(0);
                }
            }//該函數使用方法,還以mutex為例說明:V(mutex);

             

            至此我們的初步目標已經實現,接下來就是創建線程的函數;

             

            HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags, Lpdword lpThread); 
            去枝葉剪頁,其中只有第3個和第4個參數有用,LPTHREAD_START_ROUTINE 是一個線程函數指針(其實你也可以把線程理解為特殊的函數,特殊主要體現在它能和其它線程函數并發執行)函數的原型是這樣的DWORD WINAPI  threadfunction(LPVOID lpParameter),意思是,這個函數有一個空指針類型的參數,該參數返回值是DWORD(unsigned long)型的,WINAPI 就是_stdcall 是函數的一種調用方式(如果現在不懂,沒關系,以后會懂的,不必糾結),第四個參數是一個空類型指針,仔細看,這個參數其實就是傳遞給線程函數的,趕緊看線程函數的參數是不是正是LPVOID lpParameter,我們可以把寫者要寫的內容的指針放到這個參數里面傳遞給線程函數,讓線程函數執行時會從這個參數所指的內容取出然后再寫進緩沖區。總結一些,也就是我們要創建一個線程就必須提供一個固定的函數指針(也就是函數名),然后再把要傳給線程的數據的指針給lpParameter。好了我給出調用這個函數的示例:

             

             

            DWORD WINAPI  Writer(LPVOID lpParameter){
                  寫者的具體代碼…
            }
            char * p="DataToWrite";
            HANDLE  hThreads=::CreateThread(NULL,0,Reader,p,SW_NORMAL,NULL);//只需注意第3、4個參數就行,其它的參數不要管。

             

            這樣線程創建就完了;但看一下這種情況 //把創建線程作為最后一個語句時main函數會在創建完線程后退出,也就意味著程序結束,但這是線程只是創建成功,但并沒有執行的機會。

             

            int main(){
            ………..
            HANDLE  hThreads=::CreateThread(NULL,0,Reader,p,SW_NORMAL,NULL);
            }

             

            要解決這個問題,就要用到另一個API,在這個實驗中一共有多個線程,我們必須在創建完線程后等待它們全部運行結束后才能讓main函數退出。

            WaitForMultipleObjects( DWORD nCount,  HANDLE* lpHandles,  BOOL bWaitAll,  DWORD dwMilliseconds);這個函數中第一個參數指得是要等待線程的總數量,第二個參數是所有線程的“手柄”數組,因為等待函數是通過線程的“手柄”才能操作線程,等待函數也一樣,只有得到它的句柄才能在其內核對象上等待;所以我們應該這樣做:

            HANDLE hThreads[12];//本例中有六個讀者線程,六個寫者線程;

            然后再創建線程成功后把每個線程的句柄都保存在這個數組中WaitForMultipleObjects( DWORD nCount,  HANDLE* lpHandles,  BOOL bWaitAll,  DWORD dwMilliseconds);然后再這樣調用:

            WaitForMultipleObjects(12,hThreads,TRUE,INFINITE); //這個函數會在所有等待的線程都執行完成后返回,接著main函數返回,程序結束。由于這個函數也可用于等待其中任一形成結束,后返回(第三個參數傳FALSE時,意思是不必等所有線程都執行完,只要有一個執行完,就返回),所以我們在這傳TRUE,并且在最后一個參數(等待超時,如果在這個時間內線程還沒有結束,該函數也會返回,所以我們應該把超時設置為無限。。)

            到了這里,基本都講完了,下面給出完整代碼

            /******************************************************************
                Student Number: 3100604012
                              Name: Duwen
                              Date:2012-6-9
                              Type:Demonstration code
                      Description:Operating System  Course Design (OSCD)---Thread synchronization 
                      with semaphore. you must know this code only as a demonstration of the Windows
                      API , it's unwise to copy this code to OSCD report directly, you should regard this
                      code as a reference to you. and then write it by yourself.
                
            ******************************************************************
            */

            #include "stdafx.h"
            #include <Windows.h>
            #define MAX_SEM_COUNT 10
            #pragma warning(disable:4996)        //Ignore 4996 warning 

            typedef HANDLE  OSCD_semaphore;

            ////////////////////////////////////////////////////////////////////////////

            //Define the semaphores needed as global variables
            OSCD_semaphore mutex,reader,writer;
            //Define the counters
            int readcount=0, writecount=0,readapp=0;
            //Allocate buffer
            char buffer[256]={0};

            ///////////////////////////////////////////////////////////////////

            //Function to create and initialize a new semaphore
            OSCD_semaphore OSCD_CreateSemaphore(int nInitialCount) 
            {
                OSCD_semaphore hSemaphore;
                if (nInitialCount>MAX_SEM_COUNT){ //sanity check
                    printf("semaphore count too big ,please specify a value range 0 to 10\n");
                    exit(0);
                }
                hSemaphore=::CreateSemaphoreA(NULL,nInitialCount,MAX_SEM_COUNT,NULL );
                if (hSemaphore == NULL) {
                    printf("CreateSemaphore error: %d\n", GetLastError());
                    exit(0);
                }
                return hSemaphore;
            }

            //Function to delete the semaphore
            void OSCD_DelSemaphore( OSCD_semaphore semaphore)
            {
                ::CloseHandle(semaphore);

            }

            //P operation
            void P(OSCD_semaphore semaphore)
            {
               ::WaitForSingleObject(semaphore,INFINITE);
            }

            //V operation
            void V(OSCD_semaphore semaphore)
            {
                if (!::ReleaseSemaphore(semaphore,1,NULL))
                {
                    printf("release semaphore error: %d\n",GetLastError());
                    exit(0);
                }
            }

            //Reader thread function
            DWORD WINAPI Reader(LPVOID lpParameter)
            {  
                char *pThreadName=(char *)lpParameter;
                Sleep((pThreadName[6]-'0')*5);
                P(mutex);
                if (writecount>0||buffer[0]==NULL){
                    if(writecount>0)
                        printf("%s find there exists writer(s) trying to write ,  wait\n",pThreadName);
                    else
                        printf("There is no data in buffer now,%s  wait\n" ,pThreadName);
                    readapp++;
                    V(mutex);
                    P(reader);
                    printf("%s gets semaphore successfully !",pThreadName);
                    P(mutex);
                    readapp--;
                    readcount++;
                    if (readapp>0) V(reader);
                    V(mutex);
                }
                else{
                    readcount++;
                    V(mutex);
                }
                printf("%s read the data that :%s\n",pThreadName,buffer);
                P(mutex);
                readcount -- ; 
                if ( readcount == 0 && writecount>0 )
                    V(writer) ;
                V(mutex) ;
                return 0;
            }

            //Writer thread function 
            DWORD WINAPI  Writer(LPVOID lpParameter)
            {  
                char *pDataToWrite=(char *)lpParameter;
                Sleep((pDataToWrite[7]-'0')*7);
                P(mutex);
                writecount ++ ;
                printf("A new writer is trying to write\n");
                //when there are  readers are  reading or writers are trying to write, waiting..
                if (readcount>0 || writecount>1 ){
                    V(mutex);
                    printf(" Waiting(writer) semaphore\t The contents to write is:%s\n ", pDataToWrite);
                    P(writer);
                }
                else V(mutex) ; //skip waiting
                int nLen=strlen(pDataToWrite);
                strncpy(buffer,pDataToWrite,nLen/2);//write
                Sleep(3);//wait 3 ms
                strcpy(buffer+nLen/2,pDataToWrite+nLen/2);
                P(mutex); 
                writecount -- ;
                if (writecount>0 ) V(writer) ; 
                else if (readapp>0 ) V(reader) ;
                printf("A writer waited gets semaphore ,Writing: \" %s \" to buffer \n ", pDataToWrite );
                V(mutex) ;

                return 0;
            }




            int _tmain(int argc, _TCHAR* argv[])
            {
                //Create semaphores
               mutex= OSCD_CreateSemaphore(1);
               reader=OSCD_CreateSemaphore(0);
               writer=OSCD_CreateSemaphore(0);

               int i,j; 
               char *DataToWrite[6]={
                   "(writer1) ","(writer2)","(writer3)",
                   "(writer4) ","(writer5)","(writer6)"
               };

               char *ReaderName[6]={
                   "reader1","reader2","reader3","reader4","reader5","reader6"
               };

               HANDLE  hThreads[12];
               for ( i=0,j=0;i<6;i++)
               {
                   hThreads[j]=::CreateThread(NULL,0,Reader,ReaderName[i],SW_NORMAL,NULL);
                   if(!hThreads[j++]){ printf("create thread failed\n") ;return 0;}

                   hThreads[j]=::CreateThread(NULL,0,Writer,DataToWrite[i],SW_NORMAL,NULL);
                   if(!hThreads[j++]){ printf("create thread failed\n"); return 0;}
                  
               }
               printf("CREATE THREADS COMPLETED\n");

               //Wait for all the threads ending up.and then exit.
               WaitForMultipleObjects(12,hThreads,TRUE,INFINITE);

               //Delete semaphores
               OSCD_DelSemaphore(mutex);
               OSCD_DelSemaphore(writer);
               OSCD_DelSemaphore(reader);

                return 0;
            }
            posted on 2012-06-09 20:44 demons 閱讀(1780) 評論(2)  編輯 收藏 引用 所屬分類: Operating System

            FeedBack:
            # re: Operating system Course Design(操作系統課程設計)
            2012-06-10 08:39 | liji
            留個言,!  回復  更多評論
              
            # re: Operating system Course Design(操作系統課程設計)
            2012-06-10 11:03 | Duwen
            李集?@liji
              回復  更多評論
              

            <2012年6月>
            272829303112
            3456789
            10111213141516
            17181920212223
            24252627282930
            1234567

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案

            文章分類

            文章檔案

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            久久午夜福利无码1000合集| 久久青草国产手机看片福利盒子| 国内精品久久久久| 97精品国产97久久久久久免费| 久久国产成人亚洲精品影院| 久久九九有精品国产23百花影院| 久久久久久国产精品无码超碰| 久久人与动人物a级毛片| 久久只有这精品99| 久久婷婷五月综合成人D啪 | 亚洲色欲久久久综合网东京热 | 99国产精品久久| 久久精品国产亚洲精品2020| 蜜臀av性久久久久蜜臀aⅴ| 久久国产精品成人影院| 高清免费久久午夜精品| 成人精品一区二区久久| 深夜久久AAAAA级毛片免费看| 亚洲精品WWW久久久久久| 2021国产精品午夜久久| 久久精品无码一区二区无码| 久久精品国产半推半就| 久久国产免费直播| 中文字幕久久久久人妻| 国产精品久久久久久福利漫画| 99久久精品国产综合一区 | 一本一本久久A久久综合精品| 精品久久久久久久无码| 97精品伊人久久久大香线蕉| 久久久久久午夜精品| 99久久久国产精品免费无卡顿| 久久99精品久久久久久秒播| 亚洲人成网亚洲欧洲无码久久 | 99久久超碰中文字幕伊人| 国产日韩久久久精品影院首页| 色偷偷88欧美精品久久久| 久久99亚洲网美利坚合众国| 久久久久黑人强伦姧人妻| 亚洲女久久久噜噜噜熟女| 国产精品免费久久久久影院| 亚洲国产综合久久天堂|