• <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>

            思勤無邪

            上學時,因我年齡最小,個頭也最小,上課時,就像大猩猩堆里的猴一般。如今,這猴偶爾也把最近的一些情況寫在這里。

               :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
              132 Posts :: 1 Stories :: 178 Comments :: 0 Trackbacks

            公告

                 吾日常三省吾身,曰思、曰勤、曰無邪。

            積分與排名

            • 積分 - 185139
            • 排名 - 140

            最新隨筆

            最新評論

            閱讀排行榜

            評論排行榜

             

              進程

              進程是當前操作系統(tǒng)下一個被加載到內(nèi)存的、正在運行的應(yīng)用程序的實例。每一個進程都是由內(nèi)核對象和地址空間所組成的,內(nèi)核對象可以讓系統(tǒng)在其內(nèi)存放有關(guān)進程的統(tǒng)計信息并使系統(tǒng)能夠以此來管理進程,而地址空間則包括了所有程序模塊的代碼和數(shù)據(jù)以及線程堆棧、堆分配空間等動態(tài)分配的空間。進程僅僅是一個存在,是不能獨自完成任何操作的,必須擁有至少一個在其環(huán)境下運行的線程,并由其負責執(zhí)行在進程地址空間內(nèi)的代碼。在進程啟動的同時即同時啟動了一個線程,該線程被稱作主線程或是執(zhí)行線程,由此線程可以繼續(xù)創(chuàng)建子線程。如果主線程退出,那么進程也就沒有存在的可能了,系統(tǒng)將自動撤消該進程并完成對其地址空間的釋放。

              加載到進程地址空間的每一個可執(zhí)行文件或動態(tài)鏈接庫文件的映象都會被分配一個與之相關(guān)聯(lián)的全局唯一的實例句柄( Hinstance )。該實例句柄實際是一個記錄有進程加載位置的基本內(nèi)存地址。進程的實例句柄在程序入口函數(shù) WinMain ()中通過第一個參數(shù) HINSTANCE hinstExe 傳遞,其實際值即為進程所使用的基本地址空間的地址。對于 VC++ 鏈接程序所鏈接產(chǎn)生的程序,其默認的基本地址空間地址為 0x00400000 ,如沒有必要一般不要修改該值。在程序中,可以通過 GetModuleHandle ()函數(shù)得到指定模塊所使用的基本地址空間。

              子進程的創(chuàng)建

              進程的創(chuàng)建通過 CreateProcess ()函數(shù)來實現(xiàn), CreateProcess ()通過創(chuàng)建一個新的進程及在其地址空間內(nèi)運行的主線程來啟動并運行一個新的程序。具體的,在執(zhí)行 CreateProcess ()函數(shù)時,首先由操作系統(tǒng)負責創(chuàng)建一個進程內(nèi)核對象,初始化計數(shù)為 1 ,并立即為新進程創(chuàng)建一塊虛擬地址空間。隨后將可執(zhí)行文件或其他任何必要的動態(tài)鏈接庫文件的代碼和數(shù)據(jù)裝載到該地址空間中。在創(chuàng)建主線程時,也是首先由系統(tǒng)負責創(chuàng)建一個線程內(nèi)核對象,并初始化為 1 。最后啟動主線程并執(zhí)行進程的入口函數(shù) WinMain (),完成對進程和執(zhí)行線程的創(chuàng)建。

               CreateProcess ()函數(shù)的原型聲明如下:

            BOOL CreateProcess(

              LPCTSTR lpApplicationName, // 可執(zhí)行模塊名

              LPTSTR lpCommandLine, // 命令行字符串

              LPSECURITY_ATTRIBUTES lpProcessAttributes, // 進程的安全屬性

              LPSECURITY_ATTRIBUTES lpThreadAttributes, // 線程的安全屬性

              BOOL bInheritHandles, // 句柄繼承標志

              DWORD dwCreationFlags, // 創(chuàng)建標志

              LPVOID lpEnvironment, // 指向新的環(huán)境塊的指針

              LPCTSTR lpCurrentDirectory, // 指向當前目錄名的指針

              LPSTARTUPINFO lpStartupInfo, // 指向啟動信息結(jié)構(gòu)的指針

              LPPROCESS_INFORMATION lpProcessInformation // 指向進程信息結(jié)構(gòu)的指針

            );

              在程序設(shè)計時,某一個具體的功能模塊可以通過函數(shù)或是線程等不同的形式來實現(xiàn)。對于同一進程而言,這些函數(shù)、線程都是存在于同一個地址空間下的,而且在執(zhí)行時,大多只對與其相關(guān)的一些數(shù)據(jù)進行處理。如果算法存在某種錯誤,將有可能破壞與其同處一個地址空間的其他一些重要內(nèi)容,這將造成比較嚴重的后果。為保護地址空間中的內(nèi)容可以考慮將那些需要對地址空間中的數(shù)據(jù)進行訪問的操作部分放到另外一個進程的地址空間中運行,并且只允許其訪問原進程地址空間中的相關(guān)數(shù)據(jù)。具體的,可在進程中通過 CreateProcess ()函數(shù)去創(chuàng)建一個子進程,子進程在全部處理過程中只對父進程地址空間中的相關(guān)數(shù)據(jù)進行訪問,從而可以保護父進程地址空間中與當前子進程執(zhí)行任務(wù)無關(guān)的全部數(shù)據(jù)。對于這種情況,子進程所體現(xiàn)出來的作用同函數(shù)和線程比較相似,可以看成是父進程在運行期間的一個過程。為此,需要由父進程來掌握子進程的啟動、執(zhí)行和退出。下面這段代碼即展示了此過程:

            // 臨時變量

            CString sCommandLine;

            char cWindowsDirectory[MAX_PATH];

            char cCommandLine[MAX_PATH];

            DWORD dwExitCode;

            PROCESS_INFORMATION pi;

            STARTUPINFO si = {sizeof(si)};

            // 得到 Windows 目錄

            GetWindowsDirectory(cWindowsDirectory, MAX_PATH);

            // 啟動 " 記事本 " 程序的命令行

            sCommandLine = CString(cWindowsDirectory) + "\\NotePad.exe";

            ::strcpy(cCommandLine, sCommandLine);

            // 啟動 " 記事本 " 作為子進程

            BOOL ret = CreateProcess(NULL, cCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);

            if (ret) {

              // 關(guān)閉子進程的主線程句柄

              CloseHandle(pi.hThread);

              // 等待子進程的退出

              WaitForSingleObject(pi.hProcess, INFINITE);

              // 獲取子進程的退出碼

              GetExitCodeProcess(pi.hProcess, &dwExitCode);

              // 關(guān)閉子進程句柄

              CloseHandle(pi.hProcess);

            }

              此段代碼首先通過 CreateProcess ()創(chuàng)建 Windows 自帶的 記事本 程序為子進程,子進程啟動后父進程通過 WaitForSingleObject ()函數(shù)等待其執(zhí)行的結(jié)束,在子進程沒有退出前父進程是一直處于阻塞狀態(tài)的,這里子進程的作用同單線程中的函數(shù)類似。一旦子進程退出, WaitForSingleObject ()函數(shù)所等待的 pi.hProcess 對象將得到通知,父進程將得以繼續(xù),如有必要可以通過 GetExitCodeProcess ()來獲取子進程的退出代碼。

              相比而言,更多的情況是父進程在啟動完子進程后就再不與其進行任何數(shù)據(jù)交換和通訊,由其創(chuàng)建的子進程的執(zhí)行成功與否均與父進程無關(guān)。許多大型軟件在設(shè)計時也多采用了這類思想,將某些功能完全通過獨立的應(yīng)用程序來完成,當需要執(zhí)行某操作時只要通過主程序啟動相應(yīng)的子進程即可,具體的處理工作均由子進程去完成。這類子進程的創(chuàng)建過程更為簡單,例如對于上面那段代碼只需去除對子進程句柄 pi.hProcess 的等待即可:

            BOOL ret = CreateProcess(NULL, cCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);

            if (ret) {

              // 關(guān)閉子進程的主線程句柄

              CloseHandle(pi.hThread);

              // 關(guān)閉子進程句柄

              CloseHandle(pi.hProcess);

            }

              可以通過 dwCreationFlags 參數(shù)在創(chuàng)建進程時設(shè)置子進程的優(yōu)先級。前面的示例代碼在創(chuàng)建子進程時使用的均是默認的優(yōu)先級,如果要將優(yōu)先級設(shè)置為高,可以修改如下:

            BOOL ret = CreateProcess(NULL, cCommandLine, NULL, NULL, FALSE, HIGH_PRIORITY_CLASS, NULL, NULL, &si, &pi);

              如果在進程創(chuàng)建時沒有特別設(shè)置優(yōu)先級,可以通過 SetPriorityClass ()函數(shù)來動態(tài)設(shè)定,該函數(shù)需要待操作進程的句柄和優(yōu)先級標識符作為入口參數(shù),函數(shù)原型為:

            BOOL SetPriorityClass(HANDLE hProcess, DWORD dwPriorityClass);

              對于前面沒有設(shè)定優(yōu)先級的例子代碼,可以在子進程啟動后由父進程來動態(tài)改變其優(yōu)先級設(shè)置:

            SetPriorityClass(pi.hProcess, HIGH_PRIORITY_CLASS);

              或是由子進程在其啟動后自行改變優(yōu)先級設(shè)置,需要注意的是這時進程句柄應(yīng)設(shè)置為子進程自身的句柄,可通過 GetCurrentProcess ()函數(shù)來獲取:

            HANDLE hProcess = GetCurrentProcess();

            SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS);

              進程的互斥運行

              正常情況下,一個進程的運行一般是不會影響到其他正在運行的進程的。但是對于某些有特殊要求的如以獨占方式使用串行口等硬件設(shè)備的程序就要求在其進程運行期間不允許其他試圖使用此端口設(shè)備的程序運行的,而且此類程序通常也不允許運行同一個程序的多個實例。這就引出了進程互斥的問題。

              實現(xiàn)進程互斥的核心思想比較簡單:進程在啟動時首先檢查當前系統(tǒng)是否已經(jīng)存在有此進程的實例,如果沒有,進程將成功創(chuàng)建并設(shè)置標識實例已經(jīng)存在的標記。此后再創(chuàng)建進程時將會通過該標記而知曉其實例已經(jīng)存在,從而保證進程在系統(tǒng)中只能存在一個實例。具體可以采取內(nèi)存映射文件、有名事件量、有名互斥量以及全局共享變量等多種方法來實現(xiàn)。下面就分別對其中具有代表性的有名互斥量和全局共享變量這兩種方法進行介紹:

            // 創(chuàng)建互斥量

            HANDLE m_hMutex = CreateMutex(NULL, FALSE, "Sample07");

            // 檢查錯誤代碼

            if (GetLastError() == ERROR_ALREADY_EXISTS) {

              // 如果已有互斥量存在則釋放句柄并復(fù)位互斥量

              CloseHandle(m_hMutex);

              m_hMutex = NULL;

              // 程序退出

              return FALSE;

            }

              上面這段代碼演示了有名互斥量在進程互斥中的用法。代碼的核心是 CreateMutex ()對有名互斥量的創(chuàng)建。 CreateMutex ()函數(shù)可用來創(chuàng)建一個有名或無名的互斥量對象,其函數(shù)原型為:

            HANDLE CreateMutex(

              LPSECURITY_ATTRIBUTES lpMutexAttributes, // 指向安全屬性的指針

              BOOL bInitialOwner, // 初始化互斥對象的所有者

              LPCTSTR lpName // 指向互斥對象名的指針

            );

              如果函數(shù)成功執(zhí)行,將返回一個互斥量對象的句柄。如果在 CreateMutex ()執(zhí)行前已經(jīng)存在有相同名字的互斥量,函數(shù)將返回這個已經(jīng)存在互斥量的句柄,并且可以通過 GetLastError ()得到錯誤代碼 ERROR_ALREADY_EXIST 。可見,通過對錯誤代碼 ERROR_ALREADY_EXIST 的檢測可以實現(xiàn) CreateMutex ()對進程的互斥。

              使用全局共享變量的方法則主要是在 MFC 框架程序中通過編譯器來實現(xiàn)的。通過 #pragma data_seg 預(yù)編譯指令創(chuàng)建一個新節(jié),在此節(jié)中可用 volatile 關(guān)鍵字定義一個變量,而且必須對其進行初始化。 Volatile 關(guān)鍵字指定了變量可以為外部進程訪問。最后,為了使該變量能夠在進程互斥過程中發(fā)揮作用,還要將其設(shè)置為共享變量,同時允許具有讀、寫訪問權(quán)限。這可以通過 #pragma comment 預(yù)編譯指令來通知編譯器。下面給出使用了全局變量的進程互斥代碼清單:

            #pragma data_seg("Shared")

            int volatile g_lAppInstance =0;

            #pragma data_seg()

            #pragma comment(linker,"/section:Shared,RWS")

            ……

            if(++g_lAppInstance>1)

            return FALSE;

              此段代碼的作用是在進程啟動時對全局共享變量 g_nAppInstancd 1 ,如果發(fā)現(xiàn)其值大于 1 ,那么就返回 FALSE 以通知進程結(jié)束。這里需要特別指出的是,為了使以上兩段代碼能夠真正起到對進程互斥的作用,必須將其放置在應(yīng)用程序的入口代碼處,即應(yīng)用程序類的初始化實例函數(shù) InitInstance ()的開始處。

              結(jié)束進程

              進程只是提供了一段地址空間和內(nèi)核對象,其運行是通過在其地址空間內(nèi)的主線程來體現(xiàn)的。當主線程的進入點函數(shù)返回時,進程也就隨之結(jié)束。這種進程的終止方式是進程的正常退出,進程中的所有線程資源都能夠得到正確的清除。除了這種進程的正常推出方式外,有時還需要在程序中通過代碼來強制結(jié)束本進程或其他進程的運行。 ExitProcess ()函數(shù)即可在進程中的某個線程中使用,并將立即終止本進程的運行。 ExitProcess ()函數(shù)原型為:

            VOID ExitProcess(UINT uExitCode);

              其參數(shù) uExitCode 為進程設(shè)置了退出代碼。該函數(shù)具有強制性,在執(zhí)行完畢后進程即已經(jīng)被結(jié)束,因此位于其后的任何代碼將不能被執(zhí)行。雖然 ExitProcess ()函數(shù)可以在結(jié)束進程的同時通知與其相關(guān)聯(lián)的動態(tài)鏈接庫,但是由于它的這種執(zhí)行的強制性,使得 ExitProcess ()函數(shù)在使用上將存在有安全隱患。例如,如果在程序調(diào)用 ExitProcess ()函數(shù)之前曾用 new 操作符申請過一段內(nèi)存,那么將會由于 ExitProcess ()函數(shù)的強制性而無法通過 delete 操作符將其釋放,從而造成內(nèi)存泄漏。有鑒于 ExitProcess ()函數(shù)的強制性和不安全性,在使用時一定要引起注意。

               ExitProcess ()只能強制執(zhí)行本進程的退出,如果要在一個進程中強制結(jié)束其他的進程就要用 TerminateProcess ()來實現(xiàn)。與 ExitProcess ()不同, TerminateProcess ()函數(shù)執(zhí)行后,被終止的進程是不會得到任何關(guān)于程序退出的通知的。也就是說,被終止的進程是無法在結(jié)束運行前進行退出前的收尾工作的。所以,通常只有在其他任何方法都無法迫使進程退出時才會考慮使用 TerminateProcess ()去強制結(jié)束進程的。下面給出 TerminateProcess ()的函數(shù)原型:

            BOOL TerminateProcess(HANDLE hProcess, UINT uExitCode);

             

              參數(shù) hProcess uExitCode 分別為進程句柄和退出代碼。如果被結(jié)束的是本進程,可以通過 GetCurrentProcess ()獲取到句柄。 TerminateProcess ()是異步執(zhí)行的,在調(diào)用返回后并不能確定被終止進程是否已經(jīng)真的退出,如果調(diào)用 TerminateProcess ()的進程對此細節(jié)關(guān)心,可以通過 WaitForSingleObject ()來等待進程的真正結(jié)束。

              小結(jié)

              多進程是多任務(wù)管理中的重要內(nèi)容,文中上述部分對其基本概念和主要的技術(shù)如子進程的創(chuàng)建與結(jié)束、進程間的互斥運行等做了較詳細的介紹。通過本文讀者應(yīng)能對多進程管理有一個初步的認識。

            posted on 2006-05-31 17:44 思勤無邪 閱讀(574) 評論(0)  編輯 收藏 引用 所屬分類: C++其他與技術(shù)相關(guān)
            中文字幕无码久久久| 69SEX久久精品国产麻豆| 久久久久免费视频| 一本久久精品一区二区| 天堂久久天堂AV色综合| 久久se精品一区二区| 无码任你躁久久久久久久| 人妻无码αv中文字幕久久| 青青草国产精品久久| 97精品伊人久久大香线蕉| 久久99精品国产麻豆宅宅| 久久综合色区| 99久久精品无码一区二区毛片| 欧美精品国产综合久久| 久久精品国产精品亚洲精品| 久久天天躁狠狠躁夜夜2020一 | 欧美日韩精品久久久免费观看| 久久九九青青国产精品| 日韩精品久久久久久免费| 亚洲国产成人精品女人久久久 | 91精品国产综合久久久久久| 香港aa三级久久三级老师2021国产三级精品三级在| 亚洲AV无码久久精品色欲| 久久se精品一区二区影院| 久久国产精品久久久| 精品蜜臀久久久久99网站| 伊人久久大香线蕉亚洲| 国内精品综合久久久40p| 色老头网站久久网| 久久人人爽人爽人人爽av| 色综合久久精品中文字幕首页 | 久久人人妻人人爽人人爽| 波多野结衣AV无码久久一区| 偷窥少妇久久久久久久久| 精品伊人久久久| 综合人妻久久一区二区精品| 久久强奷乱码老熟女网站| 亚洲中文久久精品无码ww16| 久久综合香蕉国产蜜臀AV| 久久久无码精品亚洲日韩按摩 | 久久综合伊人77777|