进程的创建

进程的创建

进程的启动过程

  1. 打开目标exe的映象文件
  2. 创建进程内核对象
  3. 映射NTDLL到内存
  4. 创建线程内核对象
  5. 通知子系统对进程进行管理
  6. 启动线程初始化空间和加载其他DLL
  7. 跳转到入口处开始执行

CreateProcess api

BOOL CreateProcess(
  LPCTSTR lpApplicationName,                 // name of executable module
  LPTSTR lpCommandLine,                      // command line string
  LPSECURITY_ATTRIBUTES lpProcessAttributes, // SD
  LPSECURITY_ATTRIBUTES lpThreadAttributes,  // SD
  BOOL bInheritHandles,                      // handle inheritance option
  DWORD dwCreationFlags,                     // creation flags
  LPVOID lpEnvironment,                      // new environment block
  LPCTSTR lpCurrentDirectory,                // current directory name
  LPSTARTUPINFO lpStartupInfo,               // startup information
  LPPROCESS_INFORMATION lpProcessInformation // process information
);
//中文版注释
BOOL CreateProcess(
  LPCTSTR lpApplicationName,                 // 可执行模块名称 (全路径 必须是const字符串
  LPTSTR lpCommandLine,                      // 命令行(字符串 可以不是const字符串
  LPSECURITY_ATTRIBUTES lpProcessAttributes, // 进程安全描述符
  LPSECURITY_ATTRIBUTES lpThreadAttributes,  // 线程描述符
  BOOL bInheritHandles,                      // 继承标志位
  DWORD dwCreationFlags,                     // 创建标志位 (指定控制优先级和创建过程的额外标志,除了如前说,可以在任何组合中指定下列创建标标志
  LPVOID lpEnvironment,                      // 进程环境块
  LPCTSTR lpCurrentDirectory,                // 驱动目录
  LPSTARTUPINFO lpStartupInfo,               // 启动信息 指向一个窗体结构,该接口体表示新进程的窗口应该如何出现
  LPPROCESS_INFORMATION lpProcessInformation // 进程信息
);
//启动信息参数的结构体
typedef struct _STARTUPINFO {
    DWORD   cb;     //记录指定结构体大小,以字节为单位
    LPTSTR  lpReserved;
    LPTSTR  lpDesktop;
    LPTSTR  lpTitle;  //对于控制台进程,日过创建了新的控制欲窗口,则会显示标题栏中的标题,如果NULL。可执行文件额名称将会用作窗口标题, This parameter must be NULL for GUI or console processes that do not create a new console window.
    DWORD   dwX;  //控制窗口位置x
    DWORD   dwY;  //控制窗口位置y
    DWORD   dwXSize; //控制窗口宽度
    DWORD   dwYSize; //控制窗口高度
    DWORD   dwXCountChars;
    DWORD   dwYCountChars;
    DWORD   dwFillAttribute;
    DWORD   dwFlags;
    WORD    wShowWindow; //窗口显示方式
    WORD    cbReserved2;
    LPBYTE  lpReserved2;
    HANDLE  hStdInput;
    HANDLE  hStdOutput;
    HANDLE  hStdError;
} STARTUPINFO, *LPSTARTUPINFO;
//进程信息结构体
typedef struct _PROCESS_INFORMATION {
    HANDLE hProcess; //进程句柄
    HANDLE hThread;  //主线程句柄
    DWORD dwProcessId; //被创建的进程id
    DWORD dwThreadId; //被创建的主线程ID
} PROCESS_INFORMATION;

exp: 启动qq

……

进程和线程

进程和线程

什么是进程?

进程和普通计算机程序的区别

  • 进程 是运行中的程序
  • 进程 活在内存中 有血有肉有灵魂
  • 程序 死在 硬盘上的 有肉没血没灵魂

如果进程是空间的概念,那么这段空间里有什么?

……

窗口与事件

窗口与事件

窗口

什么是窗口?

Windows中称为视窗,是一个程序的操作显示界面

窗口执行动作是由什么驱动的?

Windows中通过什么机制将发生的一些动作和响应的响应函数连接起来

……

API与宽字符

API与宽字符

API(Application Programming Interface,应用程序编程接口)

Api的定义

api就是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或者硬件的一访问一组例程的能力,而又无需访问源码,或者理解内部工作机制的细节

……

win32中的宽字符

win32中的宽字符

宽字符

数据类型 容器、模板
ASCII 一个字符 一个字节
GB码(扩展了的ASCII) 英文字符 一个字节
GB码 中文字符 两个字节
UNICODE字符集(unicode编码实际指的是utf-16) 常用字符 两个字节

宽字符: 用多个字节来表示的字符称之为宽字符(只要不是以单字节存储都可称为宽字符)

……

unicode和utf8编码

兼容问题

由于ASCII存在字符含量过少的缺陷,所以不但我国自己搞出了国际码。其他国家也都设计出了符合自己国情的字符集

……

GB2312原文到GB2312机内码

GB2312原文到GB2312机内码

ANSCII

汉字编码国家标准

区位码

01-09区 为特殊字符区
10-15区 为自定义区
16-87区 为汉字编码区

……

Cpp9 模板

模板

下面是一个针对int的冒泡排序

// _20180301.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
void Sort(int* arr,int nLength)
{
    int i,k;
    for (i = 0;ix > base.x && this->y > base.y;
    }
private:
    int x;
    int y;
};
template
void Sort(T* arr,int nLength)
{
    int i,k;
    for (i = 0;iy)
            return x;
        else
            return y;
    }
    M min()
    {

Cpp8 运算符重载和深浅拷贝

深浅拷贝

相同类型间可以直接拷贝

// _20180212.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include
#include
class A
{
private:
    int* a;
public:
    A()
    {
        a = new int[10];
    }
    virtual ~A()
    {
        delete a;
        printf("析构 A \n");
    }
};
int main(int argc,char* argv[])
{
    A a1;
    A a2;
    a1 = a2;
    return 0;
}
//反汇编
27:       A a1;
0040108D   lea         ecx,[ebp-14h]
00401090   call        @ILT+15(B::B) (00401014)
00401095   mov         dword ptr [ebp-4],0
28:       A a2;
0040109C   lea         ecx,[ebp-1Ch]
0040109F   call        @ILT+15(B::B) (00401014)
004010A4   mov         byte ptr [ebp-4],1
29:       a1 = a2;
004010A8   lea         eax,[ebp-1Ch]
004010AB   push        eax              //a2 作为参数传递
004010AC   lea         ecx,[ebp-14h]    //a1 作为this指针传递
004010AF   call        @ILT+45(A::operator=) (00401032)
30:       return 0;
A::operator=:
004012E0   push        ebp
004012E1   mov         ebp,esp
004012E3   sub         esp,44h
004012E6   push        ebx
004012E7   push        esi
004012E8   push        edi
004012E9   push        ecx
004012EA   lea         edi,[ebp-44h]
004012ED   mov         ecx,11h
004012F2   mov         eax,0CCCCCCCCh
004012F7   rep stos    dword ptr [edi]
004012F9   pop         ecx
//eax = a1首地址
004012FA   mov         dword ptr [ebp-4],ecx
004012FD   mov         eax,dword ptr [ebp-4]
//ecx = a2首地址
00401300   mov         ecx,dword ptr [ebp+8]
//ecx + 4 这里是 class A中变量a的地址(ecx 对应虚表地址)
//因为ecx是变量a2 所以这里的edx = a2.a
00401303   mov         edx,dword ptr [ecx+4]
//a2.a 赋值给a1.a
00401306   mov         dword ptr [eax+4],edx
//返回a1首地址
00401309   mov         eax,dword ptr [ebp-4]
0040130C   pop         edi
0040130D   pop         esi
0040130E   pop         ebx
0040130F   mov         esp,ebp
00401311   pop         ebp
00401312   ret         4

我们发现使用=直接赋值对象,编译器自动生成了operator= 函数用于处理类型赋值
我们观察编译器自动生成的函数operator=,这里赋值直接略过了虚表(ecx+4)

……

Ruby11 拾遗

Agenda

  1. Loop
  2. Expression
  3. File Read/Write
  4. Debug
  5. Process & Thread

Loop

while

a = 10
while a > 0
  puts a
  a -= 1
end

until

a = 100
until a == 0
  puts a
  a -= 1
end

loop

a = 10
loop do
  break if a  0

!~ 正则匹配 是否匹配不到 匹配到返回fals 匹配不到返回true

……