删除的内容 添加的内容
Skw kevin留言 | 贡献
→‎狀態:​ 内容扩充
Cewbot留言 | 贡献
去除重複的轉換規則: 去除與公共轉換組重複的轉換規則 (1): 存在於轉換組 IT: zh-cn:程序;zh-tw:程式 (本次機械人作業已完成609.4%)
 
(未显示32个用户的46个中间版本)
第1行:
{{Merge|进程树|time=2024-08-20T11:25:01+00:00}}
{{noteTA
|G1=IT
|T1=zh-cn:进程; zh-tw:行程(程序);
|12=zh-cn:计算机; zh-tw:電腦; zh-hk:電腦;
|23=zh-cn:线程; zh-tw:執行緒;
|3=zh-cn:程序; zh-tw:程式;
|4=zh-cn:进程; zh-tw:行程;
}}
{{各地中文名
'''行程'''({{lang-en|Process}},{{地区用词|译=1|陆简=进程|陆繁=進程|台简=行程|台繁=行程}})是電腦中已執行[[程式]]的實體。行程為曾经是[[分時系統]]的基本運作單位。在面向进程设计的系统(如早期的[[UNIX]],[[Linux]] 2.4及更早的版本)中,进程是程序的基本执行实体;在面向线程设计的系统(如当代多数操作系统、[[Linux]] 2.6及更新的版本)中,行程本身不是基本執行单位,而是[[執行緒]]的容器。程式本身只是指令、数据及其组织形式的描述,行程才是程式(那些指令和数据)的真正執行实例。若干行程有可能與同一個程式相關聯,且每個行程皆可以同步(循序)或异步([[並行計算|平行]])的方式獨立執行。現代[[電腦系統]]可在同一段時間內以进程的形式将多個程式載入到記憶體中,並藉由時間共享(或稱[[时分复用]]),以在一個[[處理器]]上表現出同時([[平行性]])執行的感覺。同樣的,使用多執行緒技術(多執行緒即每一個執行緒都代表一個行程内的一个独立执行上下文)的作業系統或電腦架構,同樣程式的'''平行'''线程,可在多 CPU 主機或網絡上真正'''同時'''執行(在不同的CPU上)。
|tw = 行程、過程、處理程序
|cn = 进程
}}
{{about|電腦程式的實體|[[引擎]]的-{行程}-|衝程|[[物理学]]中的-{行程}-|路程}}
'''行程'''({{lang-en|process}}),是指電腦中已執行的[[程式]],曾经是[[分時系統]]的基本運作單位。在面向进程设计的系统(如早期的[[UNIX]],[[Linux]] 2.4及更早的版本)中,是程式的基本执行实体;在面向线程设计的系统(如当代多数操作系统、[[Linux]] 2.6及更新的版本)中,行程本身不是基本執行单位,而是[[執行緒]]的容器。
 
程式本身只是指令、数据及其组织形式的描述,相當於一個名詞,行程才是程式(那些指令和数据)的真正執行实例,可以想像說是現在進行式。若干行程有可能與同一個程式相關聯,且每個行程皆可以同步(循序)或异步([[平行計算|平行]])的方式獨立執行。現代[[電腦系統]]可在同一段時間內以进程的形式将多個程式載入到記憶體中,並藉由時間共享(或稱[[时分复用]]),以在一個[[处理器 (计算)|處理器]]上表現出同時([[平行性]])執行的感覺。同樣的,使用[[多執行緒]]技術的作業系統或電腦架構,同樣程式的'''平行'''线程,可在多CPU主機或網絡上真正'''同時'''執行(在不同的CPU上)。
 
==名稱==
*[[整批系統]]環境,行程稱為'''工作'''(''jobs'')。
*[[分時系統]]環境,行程稱為'''使用者程式'''(''user progamsprograms'')或'''任務'''(''tasks'')。
*在多數情況,工作與行程是同義詞,但處理(''process'')已較為人接受
 
==概念==
使用者下達執行-{}-程式的命令後,就會產生行程。同一程式可產生多個行程(一對多關係),以允許同時有多位使用者執行同一程式,卻不會相衝突。
 
行程需要一些資源才能完成工作,如[[CPU]]使用時間、[[記憶體]]、檔案以及[[I/O]]裝置,且為依序逐一進行,也就是每个CPU核心任何時間內僅能執行一項行程。
 
进程与线程的区别:进程是计算机管理运行程序的一种方式,一个进程下可包含一个或者多个线程。线程可以理解为子进程。
 
===內容===
第23行 ⟶ 第31行:
*那個程式的可執行機器碼的一個在記憶體的映像。
*分配到的記憶體(通常是虛擬的一個記憶體區域)。記憶體的內容包括可執行代碼、特定於行程的資料(輸入、輸出)、呼叫堆疊、堆棧(用於保存運行時運輸中途產生的資料)。
*分配給該行程的資源的作業系統描述符,諸如[[檔案描述符]](Unix 術語)或[[句柄|檔案控制代碼]](Windows)、資料源和資料終端。
*安全特性,諸如行程擁有者和行程的權限集(可以容許的操作)。
*處理器狀態(內文),諸如暫存器內容、物理記憶體定址等。當行程正在執行時,狀態通常儲存在暫存器,其他情況在記憶體。
第35行 ⟶ 第43行:
*結束(''terminated''):完成執行。
各狀態名稱可能隨不同作業系統而相異;对于单CPU系统(UP),任何時間可能有多個行程為等待、就緒,但必定僅有一個行程在執行。
 
注意: 进程的各个状态之间是不能随意切换的,例如当进程运行时因IO操作而阻塞,当IO操作完成后并不会直接恢复回运行态,而是转为就绪态等待CPU的调度。
 
===行程控制表===
第45行 ⟶ 第55行:
{{main|排程}}
 
==行程間通訊({{lang|en|Inter-process communication}})==
{{main|行程間通訊}}
==Unix进程==
==Windows进程==
操作系统使用[[进程ID#Microsoft_Windows|进程ID]]来唯一标识每个进程。在一个进程内部,使用进程[[句柄]]来标识关注的每个进程。使用Windows API从进程ID获取进程句柄:
<syntaxhighlight lang="cpp">
OpenProcess(PROCESS_ALL_ACCESS, TRUE, procId); //或者PROCESS_QUERY_INFORMATION
</syntaxhighlight>
使用API函数:GetModuleFileNameEx或GetProcessImageFileName或QueryFullProcessImageName查询进程的exe文件名
 
使用API函数GetCurrentProcess可以获取本进程的伪句柄(值为-1),只能用于本进程的API函数调用;不能被其他进程继承或复制。可用API函数DuplicateHandle获得进程的真句柄。
 
使用API函数CreateProcess创建进程,WaitForSingleObject可等待子进程的结束。例如:
<syntaxhighlight lang="cpp" line="1">
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
 
void main() {
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// Start the child process.
if (!CreateProcess(NULL, // No module name (use command line)
"demo.exe arg1", // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure,用于给出子进程主窗口的属性
) {
printf("CreateProcess failed (%d).\n", GetLastError());
return;
}
// Wait until child process exits.
WaitForSingleObject(pi.hProcess, INFINITE);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
</syntaxhighlight>
创建的子进程可以继承父进程的:
*CreateFile返回的打开句柄,包括[[文件]]、控制台输入缓冲区、控制台屏幕缓冲区, [[命名管道]], 串口通信设备, [[邮槽]].
*打开的句柄,包括:进程、线程、[[互斥锁]]、[[事件 (同步原语)|事件对象]]、信号量、命名管道、匿名管道、文件映射对象。
*环境变量
*当前目录
*控制台,除非进程脱离(detach)或创建了新的控制台。
*错误模式,使用API函数SetErrorMode设置
*进程亲和掩码(affinity mask),用以指示期望使用CPU的哪些核
*在哪个[[作業 (電腦)|作业]]中。
子进程不能继承:
*优先级类别Priority class.
*句柄,由LocalAlloc, GlobalAlloc, HeapCreate, HeapAlloc返回
*伪句柄,由GetCurrentProcess或GetCurrentThread返回
*DLL模块句柄,由LoadLibrary返回
*GDI对象句柄或USER对象句柄,如HBITMAP或HMENU.
为继承句柄,父进程在创建(或者代开、复制)各种可继承对象句柄时,在SECURITY_ATTRIBUTES结构的bInheritHandle成员为TRUE。在CreateProcess的bInheritHandles参数为TRUE;如果要继承标准输入、标准输出、标准错误的句柄,STARTUPINFO结构的dwFlags成员包含STARTF_USESTDHANDLES标志位.
 
下述API的函数用于获取进程相关信息:
*GetCommandLine:当前进程的命令行字符串
*GetStartupInfo:当前进程被创建时的STARTUPINFO结构
*GetProcessVersion:获取可执行头的版本信息
*GetModuleFileName:获取包含了进程代码的可执行文件的全路径与文件名
*GetGuiResources:获取使用中的GUI对象的句柄数量
*IsDebuggerPresent:确定进程是否被调试
*GetProcessIoCounters:获取进程执行的所有I/O操作的薄记信息。
*GetProcessMemoryInfo:获取进程的工作集内存的信息
*GetProcessWorkingSetSize:获取进程的[[工作集]]内存被允许的下限与上限
*SetProcessWorkingSetSize:设置进程的[[工作集]]内存的下限与上限
 
进程终止时,所有打开的句柄被关闭,进程对象被触发(signaled)。进程的退出码(exit code)或者在ExitProcess、TerminateProcess函数中指出,或者是main、WinMain函数返回值。如果进程由于一个致命异常(fatal exception)而终止,退出码是这个异常值,同时进程的所有执行中的线程的退出码也是这个异常值。
 
优雅地关闭其他进程的方法是用RegisterWindowMessage登记私有消息,用BroadcastSystemMessage播放消息,收到消息的进程用ExitProcess关闭。<ref>{{Cite web |url=https://msdn.microsoft.com/en-us/library/windows/desktop/ms686722(v=vs.85).aspx |title=MSDN:Terminating a Process |access-date=2017-09-20 |archive-date=2017-09-11 |archive-url=https://web.archive.org/web/20170911140349/https://msdn.microsoft.com/en-us/library/windows/desktop/ms686722(v=vs.85).aspx |dead-url=no }}</ref>
 
如果想要获取特定名字的进程的ID,需要枚举所有进程。传统办法是CreateToolhelp32Snapshot、Process32First、Process32Next函数;也可以使用EnumProcesses、EnumProcessModules函数来获取所有的进程ID,一个进程的所有模块的句柄。示例如下:
<syntaxhighlight lang="cpp" line="1">
PROCESSENTRY32 pe32;
HANDLE hSnaphot;
HANDLE hApp;
DWORD dProcess;
hSnaphot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // 获取进程快照
Process32First(hSnaphot, &pe32); // 枚举第一个进程
do {
if (lstrcmpi(pe32.szExeFile, _T("NotePad.exe")) == 0) { // 查找进程名称为 NotePad.exe
dProcess = pe32.th32ProcessID;
break;
}
} while (Process32Next(hSnaphot, &pe32)); // 不断循环直到枚举不到进程
hApp = OpenProcess(PROCESS_VM_OPERATION | SYNCHRONIZE, FALSE, dProcess); // 根据进程 ID 获取程序的句柄
if (!WaitForSingleObject(hApp, INFINITE)) // 等待进程关闭
AfxMessageBox(" 记事本已经关闭!");
 
// 另一种方法
DWORD aProcId[1024], dwProcCnt, dwModCnt;
HMODULE hMod[1000];
TCHAR szPath[MAX_PATH];
 
// 枚举出所有进程ID
if (!EnumProcesses(aProcId, sizeof(aProcId), &dwProcCnt)) {
//cout << "EnumProcesses error: " << GetLastError() << endl;
return 0;
}
 
// 遍例所有进程
for (DWORD i = 0; i < dwProcCnt; ++i) {
// 打开进程,如果没有权限打开则跳过
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, aProcId[i]);
if (NULL != hProc) {
// 打开进程的第1个Module,并检查其名称是否与目标相符
if (EnumProcessModules(hProc, &hMod, 1000, &dwModCnt)) {
GetModuleBaseName(hProc, hMod, szPath, MAX_PATH);
if (0 == lstrcmpi(szPath, lpName)) {
CloseHandle(hProc);
return aProcId[i];
}
}
CloseHandle(hProc);
}
}
return 0;
</syntaxhighlight>
 
==相關==
*[[時間片]]
*[[进程树]]
 
== 参考文献 ==
{{Reflist}}
 
{{-}}
{{操作系统}}
 
{{Authority control}}
[[Category:操作系統技術]]
 
[[Category:进程]]
[[Category:操作系统技術]]
[[Category:进程| ]]