⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 漫谈兼容内核之四:kernel-win32的进程管理.txt

📁 漫谈系统内核内幕 收集得很辛苦 呵呵 大家快下在吧
💻 TXT
📖 第 1 页 / 共 2 页
字号:
    IN LPVOID       lpEnvironment,
    IN LPCSTR       lpCurrentDirectory,
    IN LPSTARTUPINFOA    lpStartupInfo,
    OUT LPPROCESS_INFORMATION  lpProcessInformation
);[/code]
    这是Win32 API界面上的函数定义,所以是个DLL函数,还不是系统调用。Windows系统调用的界面是不公开的。不过好在我们已经有了ReactOS,从ReactOS的代码中可以看到这个系统调用的函数定义是:

[code]NtCreateProcess(
  OUT PHANDLE     ProcessHandle,
  IN ACCESS_MASK    DesiredAccess,
  IN POBJECT_ATTRIBUTES  ObjectAttributes  OPTIONAL,
  IN HANDLE      ParentProcess,
  IN BOOLEAN     InheritObjectTable,
  IN HANDLE      SectionHandle  OPTIONAL,
  IN HANDLE      DebugPort  OPTIONAL,
  IN HANDLE      ExceptionPort  OPTIONAL
)[/code]

    详细说明这些参数的作用是件颇费篇幅的事,读者可以自己阅读“Windows NT/2000 Native API Reference”第六章中关于ZwCreateProcess()的说明(ZwCreateProcess()和NtCreateProcess()是同一个函数的两个名字,有的文献说在用户空间叫ZwCreateProcess()、在内核中叫NtCreateProcess())。我们这里只是长话短说,提一下往往会使Linux程序员感到惊讶的东西。
    首先当然是InheritObjectTable。这是个布尔量,表示是否要从父进程继承已经打开的对象,但是即使要继承也不是全盘照收,还要看具体对象在打开时是否允许遗传。
    另一个参数ParentProcess是个已打开进程对象的Handle,如果是有效Handle的话就表示新创建的对象应该“过继”给这个进程、作为它的子进程,而不是作为其创建者即“生父”的子进程。或者,换句话说就是包办、替别的进程创建一个子进程。
    而DesiredAccess,则有下列选项:

[code]#define PROCESS_TERMINATE    1
#define PROCESS_CREATE_THREAD  2
#define PROCESS_SET_SESSIONID   4
#define PROCESS_VM_OPERATION   8
#define PROCESS_VM_READ    16
#define PROCESS_VM_WRITE    32
#define PROCESS_DUP_HANDLE   64
#define PROCESS_CREATE_PROCESS  128
#define PROCESS_SET_QUOTA    256
#define PROCESS_SET_INFORMATION  512
#define PROCESS_QUERY_INFORMATION 1024
#define PROCESS_ALL_ACCESS  \
     (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0xFFF)[/code]

    别的就不说了,光是上面这些,读者就可以看出NtCreateProcess()与fork()、execve()等Linux系统调用的差距有多大了。显然,以目前的kernel-win32,要实现与Windows的高度兼容是不可能的。
    还要注意,这个系统调用只创建进程、而不包括其第一个线程。这跟Win32 API函数CreateProcess()是不一样的,后者实际上先调用NtCreateProcess(),再调用NtCreateThread()。
    那么是否可以通过在用户空间、即在DLL中把CreateProcess()化解成一个kernel-win32和Linux系统调用的序列来解决问题呢?有的可以,有的不行。例如上述把所创建的进程过继给另一个进程就不行,因为过继给另一个进程也意味着从“继父”那里、而不是从“生父”那里、继承已打开对象(如果需要的话)。
    再看线程的创建。

[code]CreateThread(
    IN LPSECURITY_ATTRIBUTES  lpThreadAttributes,
    IN DWORD       dwStackSize,
    IN LPTHREAD_START_ROUTINE  lpStartAddress,
    IN LPVOID       lpParameter,
    IN DWORD       dwCreationFlags,
    OUT LPDWORD      lpThreadId
);[/code]

   同样,这只是API函数,而相应的系统调用是NtCreateThread(),下列函数定义取自ReactOS的代码:

[code]NtCreateThread(
OUT PHANDLE T     hreadHandle,
    IN ACCESS_MASK     DesiredAccess,
    IN POBJECT_ATTRIBUTES   ObjectAttributes  OPTIONAL,
    IN HANDLE       ProcessHandle,
    OUT PCLIENT_ID     ClientId,
    IN PCONTEXT      ThreadContext,
    IN PINITIAL_TEB     InitialTeb,
    IN BOOLEAN      CreateSuspended
)[/code]

    同样,详细的说明请看“Windows NT/2000 Native API Reference”第五章,这里只是简单地提一下。首先是ProcessHandle,这是个已打开进程对象的Handle。这就是说,NtCreateThread()的调用者可以为别的进程创建线程,而不仅仅是为调用者本身所属的进程。再看CreateSuspended,这是个布尔量,表示新创建的线程是否一出生就先被挂起、等到有别的线程对其执行NtResumeThread()后才投入运行,抑或一生下来就立即投入运行。还有ThreadContext,这是个指针,可以指向一个数据结构,里面规定了新线程降生之初各个寄存器的值(真令人难以理解这到底是为什么)。还有参数InitialTeb,在“Native API”一书中说是UserStack,用来指定新线程的用户空间堆栈的位置(这倒有道理)。至于DesiredAccess,则又有下列许多选项:

[code]#define THREAD_TERMINATE     (0x0001L)
#define THREAD_SUSPEND_RESUME   (0x0002L)
#define THREAD_ALERT       (0x0004L)
#define THREAD_GET_CONTEXT    (0x0008L)
#define THREAD_SET_CONTEXT    (0x0010L)
#define THREAD_SET_INFORMATION   (0x0020L)
#define THREAD_QUERY_INFORMATION  (0x0040L)
#define THREAD_SET_THREAD_TOKEN   (0x0080L)
#define THREAD_IMPERSONATE    (0x0100L)
#define THREAD_DIRECT_IMPERSONATION  (0x0200L)
#define THREAD_ALL_ACCESS    (0x1f03ffL)[/code]

    读者不难看出,这与fork()的差距可真够大的了。而且,有些差异是不能在用户空间弥补的,例如为别的进程创建线程,还有让新创建的线程进入“挂起”状态等等就是这样。
    这还只是NtCreateProcess()和NtCreateThread()两个系统调用。与进程/线程管理有关的Windows系统调用至少还有下面这些:

[code]NtAlertThread()
NtCreateProcess()
NtCreateThread()
NtDuplecateObject()
NtGetContextThread()
NtImpersonateThread()
NtOpenProcess()
NtOpenThread()
NtQueueApcThread()
NtResumeThread()
NtSetContextThread()
NtSetInformationProcess()
NtSetInformationThread()
NtSetThreadExecutionState()
NtSuspendThread()
NtTerminateProcess()
NtTerminateThread()
NtYieldExecution()[/code]

    由此可见,要跟Windows高度兼容,可真是路慢慢其修远。不过也不要被吓倒,还是那句老话:战略上藐视困难,战术上重视困难。再说也确实并非所有特性都必须加以实现,因为绝大多数应用软件都不会去用那些刁钻古怪的功能。
    但是有一点是明白无误的,那就是迄今为止的Kernel-win32还只是朝正确的方向走了一小步。而且,其设计方案也有不当之处,想要用fork()加Win32Init()实现进程/线程的创建就是。这也是我认为对于兼容内核而言ReactOS远比Kernel-win32重要的原因。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -