Windows内核之进程基本含义以及进程的创建

进程

1 进程的含义:

1.1   一个是操作系统用来管理进程的内核对象。

内核对象也是系统用来存放关于进程的统计信息的地方。

1.2   还有一个是地址空间,它包括全部可运行模块或DL L 模块的代码和数据。它还包括动态内存分配的空间。

如线程堆栈和堆分配空间。

2 操作系统启动应用程序的步骤

2.1 调用C/c++执行时的启动函数

启动函数总共4种,WinMainCRTStartup,wWinMainCRTStartup,mainCRTStartup,wmainCRTStartup。

启动函数完毕例如以下任务:

<1>检索指向新进程的完整命令行的指针

<2>检索指向新进程的环境变量的指针

<3>对C/ C + +执行期的全局变量进行初始化。

假设包括了S t d L i b . h 文件,代码就能訪问这些变量

<4>对C执行期内存单元分配函数(m a l l o c 和c a l l o c )和其它低层输入/输出例程使用的内存栈进行初始化。

<5>为全部全局和静态C+ +类对象调用构造函数。

<6>调用入口点函数

如:int nMainRetVal = wmain(__argc, __wargv, _wenviron); 

<7>当进入点函数返回时,启动函数便调用C 执行期的ex i t 函数。将返回值(nMainRetVal )传递给它。

<8>调用由_onexit函数的调用而注冊的不论什么函数

<9>为全部全局的和静态的C++类对象调用析构函数

<10>调用操作系统的ExitProcess函数,将nMainRetVal传递给它。这使得该操作系统可以撤消进程并设置它的e x i t 代码

3 进程的实例句柄

3.1 进程的当前实例句柄

载入到进程地址空间的每一个exe或者dll文件都会被赋予一个独一无二的句柄。

获取载入的模块(exe,dll)的方法:

GetModuleFileName(HMOUDLEhModule,LPTSTR lpFileName,DWROD nSize);

当hModule的值为NULL 的时候,会返回当前调用模块的所有路径名字。

3.2 进程的前一个实例句柄

C++代码总是将NULL赋值给WinMain函数的第二个參数HINSTANCEhPreInstance,这种原因是在16位的程序中对这个參数有保留使用,那么保留它就方便转用16位程序。

4 进程的命令行

LPTSTR GetCommandLine();获取命令行字符串

5  进程的环境变量

每一个进程都有一个与它相关的环境变量块,环境块是进程的地址空间中分配的一个内存块。每一个环境块都包括一组字符串,形式例如以下所看到的:

VarName1=VarValue1\0

VarName2=VarValue2\0

VarName3=VarValue3\0

当中要注意变脸等号前有没有空格,有空格和没空格代表的是全然不同的环境变量。如:

XYZ=xxx;和XYZ =xxx。这就是两个全然不同的环境变量了。

操作华景变量相关的 函数

<1>

LPVOIDGetEnvironmentStrings(VOID);

<2>

BOOL SetEnvironmentVariable(
 LPCTSTR lpName,  // environment variable name
 LPCTSTR lpValue  // new value for variable);

<3>

DWORD GetEnvironmentVariable(  LPCTSTR lpName,  // environment variable name
 LPTSTR lpBuffer, // buffer for variable value
 DWORD nSize      // size ofbuffer);

<4>

BOOL FreeEnvironmentStrings(LPTSTRlpszEnvironmentBlock  // environmentstrings);

6 进程的当前文件夹

程序的当前文件夹是能够进行改变的,当前文件夹和进程的启动文件夹是不同的,启动文件夹就是exe或者dll被调用的文件夹,我们能够通过GetModuleFineName函数进行处理。

<1>

DWORD GetCurrentDirectory(
 DWORD nBufferLength,    //size of directory buffer
 LPTSTR lpBuffer            //directory buffer);

<2>

BOOL SetCurrentDirectory(  LPCTSTR lpPathName   // new directory name);

7 系统的版本号信息获得

GetVersion()

可是这个函数有bug,就是程序猿把主版本。次版本放错了高低字节。

BOOL GetVersionEx(  LPOSVERSIONINFO lpVersionInfo // versioninformation);

这个是新的修正过来的。

8 创建进程

BOOL WINAPI CreateProcess(
  _In_opt_     LPCTSTR lpApplicationName,
  _Inout_opt_   LPTSTR lpCommandLine,
  _In_opt_     LPSECURITY_ATTRIBUTES lpProcessAttributes,
  _In_opt_     LPSECURITY_ATTRIBUTES lpThreadAttributes,
  _In_         BOOL bInheritHandles,
  _In_         DWORD dwCreationFlags,
  _In_opt_     LPVOID lpEnvironment,
  _In_opt_     LPCTSTR lpCurrentDirectory,
  _In_         LPSTARTUPINFO lpStartupInfo,
  _Out_        LPPROCESS_INFORMATION lpProcessInformation
);

參数解释:

<1> lpApplicationName

被载入模块的名字,必须制定模块的格式,比方exe。由于系统不会默觉得exe,模块的名字能够是部门名字,那么系统就会在当前文件夹去寻找该模块。

通常将其设置为NULL,由于lpCommandLine具有比它更加强大的功能来完毕模块的调用。

<2> lpCommandLine

系统寻找可运行文件exe的顺序是:

应用程序载入的文件夹。

父进程的当前文件夹;

Windows System 文件夹。

Windows文件夹;

环境变量列出的文件夹。

注意:当字符集是Unicode时候,參数类型不能是const类型的。若是就会报错。

<3> lpProcessAttributes

指向 SECURITY_ATTRIBUTES的指针。决定进程创建函数返回的的新进程对象的句柄能否被子进程继承。

当为NULL的时候。获取的是默认安全描写叙述符

<4> lpThreadAttributes

       指向SECURITY_ATTRIBUTES 的指针。决定进程创建函数范湖的新线程对象的句柄能否被子进程继承。

当为NULL的时候,获取的是默认安全描写叙述符。

<5> bInheritHandles

假设为True,那么不论什么能够被继承的句柄都会别新创建的进程所继承。

假设为FALSE,那么则不会被新进程继承。

<6>dwCreationFlags

新创建的进程的创建标志位设置,决定是父子进程调试信息的反馈,子进程窗体的产生等行为。

<7> lpEnvironment

新进程中指向的环境块。

假设该值为NULL,那么就表示新进程继承了父进程的环境块。

<8>lpCurrentDirectory

指向新进程的当前文件夹的指针。

假设为NULL,那么则就和调用进程(父进程)具有同样的当前文件夹。

<9> lpStartupInfo

       指向 STARTUPINFO or STARTUPINFOEX的指针。主要指定窗体的状态,外观,标准句柄。

当Wi
n d o w s 创建新进程时,它将使用该结构的有关成员。大多数应用程序将要求生成的应用程序只使用默认值。至少应该将该结构中的全部成员初始化为零。然后将cb 成员设置为该结构的大小。

当里面创建的句柄不在是用的使用。要通过CloseHandle来关闭。

<10> lpProcessInformation

指向PROCESS_INFORMATION结构体的指针。

typedef struct _PROCESS_INFORMATION {
  HANDLE hProcess;
  HANDLE hThread;
  DWORD  dwProcessId;
  DWORD  dwThreadId;
} PROCESS_INFORMATION, *LPPROCESS_INFORMATION;

里面是用的句柄不在使用的时候,要通过CloseHandle函数来关闭。

当进程内核对象创建后,系统赋予该对象一个独一无二的标识号。系统中的其它不论什么进程内核对象都不能使用这个同样的ID号。线程内核对象的情况也一样。

当一个线程内核对象创建时,该对象被赋予一个独一无二的、系统范围的ID号。进程ID和线程ID共享同样的号码池。这意味着进程和线程不可能拥有同样的ID 。

9 创建进程的实例:

#include <Windows.h>
#include <iostream>
using namespace std;

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).
        TEXT("Notepad++"),	// 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.
    )
    {
        cout<<TEXT("CreateProcess failed.");
    }

    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );

    // Close process and thread handles.
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
}
时间: 2024-10-11 21:11:29

Windows内核之进程基本含义以及进程的创建的相关文章

Windows内核原理研究——进程创建

进程可能是用户接触的Windows系统中最多的部分了,对于Windows系统而言,进程是一个独立的地址空间可以为线程提供一个独立的执行环境, 也就是说 进程= 独立的地址空间 一个进程内核对象 线程= 一个线程自己的栈 一个线程内核对象 当然这个栈是在进程的地址空间中.那么,也就是说线程才是真正“干活”的东西,进程只不过是一些资源的集合而已.只能说是“原材料”. 在我学习Windows内核以前一直觉得进程的种种特性很神奇,比如说地址空间独立是怎么实现的呢?我们的电脑使用的都是同一块内存怎么能实现

Windows内核之进程的终止和子进程

1 进程终止的方法: <1>主线程的进入点函数返回(最好使用这个方法) <2>进程中的一个线程调用ExitProcesss函数(应该避免使用这种方法). <3>另一个进程中的线程调用TerminateProcess函数(应该避免使用这种方法). <4>进程中的所有线程自行终止运行(这种情况几乎从未发生). 1.1  主线程进入点函数返回 始终都应该这样来设计应用程序,即只有当主线程的进入点函数返回时,它的进程才终止运行.这是保证所有线程资源能够得到正确清除的

C++windows内核编程笔记day13 进程、线程与信号量

Windows进程 进程是一个容器,包含程序执行需要的代码.数据.资源等信息, windows进程的特点: 每个进程都有自己的ID号 每个进程都有自己的地址空间,进程之间无法访问对方的地址空间. 每个进程都有自己的安全属性 每个进程至少包含一个线程. 获取和释放环境信息 GetEnvironmentStrings FreeEnvironmentStrings 获取或设置 本程序的环境变量 GetEnvironmentVariable SetEnvironmentVariable 示例: char

windows 内核下获取进程路径

windows 内核下获取进程路径 思路:1):在EPROCESS结构中获取.此时要用到一个导出函数:PsGetProcessImageFileName,申明如下: NTSYSAPI UCHAR *    PsGetProcessImageFileName(    __in PEPROCESS Process    ); 此函数获取的是一个简单的进程名,并不是绝对路径. 2):ZwQueryInformationProcess. 要想获取进程的绝对路径,可用一个未公开的函数:ZwQueryInf

windows内核代码之进程操作

[toc] 一丶简介 整理一下windows内核中.常用的代码.这里只整理下进程的相关代码. 二丶 windows内核之遍历进程 内核中记录进程的结构体是EPROCESS结构.所以只需要遍历这个结构即可.标准方法可以使用ZwQuerySystemInformation函数.使用SystemProcessInformation功能号. 另外也有很多种枚举进程的方法比如找到EPROCESS结构进行枚举的.(CPU结构体 KPCR)等等.不过兼容性都是不太好.另一种方法是枚举句柄表 PspCidTab

20135201李辰希《Linux内核分析》第六周 进程的描述与创建

李辰希 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.进程的描述 操作系统的三大管理功能: 进程管理(最重要的) 内存管理 文件系统 为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息. 进程控制块PCB task_struct: 进程状态 进程打开的文件 进程优先级信息 task_struct总体数据结构的抽象: tty:控制台 fs:文件系统

Linux内核分析——进程的描述和进程的创建

Linux内核分析——进程的描述和进程的创建 20135111李光豫 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.实验内容 阅读理解task_struct数据结构http://codelab.shiyanlou.com/xref/linux-3.18.6/include/linux/sched.h#1235: 分析fork函数对应的内核处理过程sys_clone,理解创建一个新进

LINUX内核分析第六周学习总结——进程的描述和进程的创建

LINUX内核分析第六周学习总结——进程的描述和进程的创建 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.知识概要 进程的描述 进程描述符task_struct数据结构(一) 进程描述符task_struct数据结构(二) 进程的创建 进程的创建概览及fork一个进程的用户态代码 理解进程创建过程复杂代码的方法 浏览进程创建过程相关的关键代码 创建的新进程是从哪里开始执行的

windows Service启动带有管理员权限的进程

事情是这样的,公司的产品有个守护进程(windows Service)需要启动产品的主程序exe,让主程序它运行为管理员权限(因为主程序会加载一个插件,插件中有列出端口监听的功能,需要由端口查找到进程PID,由进程PID查找进程名或进程镜像路径,这些对于一些特殊进程例如svchost需要有管理员权限才能查到进程名和路径).windows下的程序是不能在运行时获得管理员权限的,只能在创建进程的时候提升为管理员权限.如果是普通进程运行一个管理员权限程序,可以调用ShellExcute API.双击鼠