Windows程序设计
2021-03-03 03:29
标签:back uid onstop sea char debug 指针 scanf director windows.h 头文件 链接到指定库文件,这一步VC帮我链接好了,对我们来说是透明的,如果要显示链接某个库,可以使用 #pragma comment(lib,"mylib.lib") :: 为全局函数,帮助文档 F1 代码风格 名称简短 富有意义 g_ m_ bRet _nErrorCode g_szTitle MAXBUFFER 动作 代码对齐 {} 独立单元 注释,短注释在语句末尾,常注释在语句的上一行 创建工程 VS2015 创建 Win32 Console程序,带有预编译头文件,并且不是空工程 一,CPU的保护模式和windows操作系统 [x] windows 是多任务实现 [x] 虚拟内存和 各个进程的地址空间安排:2G系统空间,2G用户空间,2G用户空间是各个进程私有的,很少被其他应用打断,保证系统稳定 [x] 内核模式和用户模式:虽然用户模式下是独立4G空间,但是内核模式的系统和驱动共用一个2G空间;内核空间的数据只有在特定的权限下才能访问 [x] 当应用程序调用系统函数比如ReadFile,应用程序会从用户模式进入内核模式去执行; 因为访问系统内部数据,必须运行在内核模式下 二,内核对象 三,对象句柄 原则上,内核对象的句柄仅对当前进程有效;当然也有手段多进程共用一个内核对象 四,应用程序启动流程 应用程序的启动过程就是应用程序的创建过程 在这种情况下,可执行模块的名字必须处于 lpCommandLine 参数的最前面并由空格符与后面的字符分开,当CreateProcess解析lpCommandLine 字符串时,它会检查字符串中的第一个标记(token),并假记此标记为我们想运行的可执行文件的名称,如果可执行文件的名称没有扩展名,默认为.exe,并且如果文件名不包含一个完整的路径,CreateProcess还会按以下顺序来搜索可执行文件: (1)主调进程.exe文件所在的目录 (2)主调进程的当前目录 (3)windows系统目录,即GetSystemDirectory返回的System32子文件夹 (4)windows目录 (5)PATH环境变量中列出的目录 获取系统内所有正在运行进程的信息 拓展:CreateToolhelp32Snapshot详解 可以枚举: TH32CS_SNAPHEAPLIST:表示快照信息包含特定进程的堆栈列表 TH32CS_SNAPMODULE :表示快照信息包含特定进程的使用模块的列表 TH32CS_SNAPPROCESS:表示快照信息包含系统的所有进程的列表 TH32CS_SNAPTHREAD :表示快照信息包含系统所有线程的列表 TH32CS_SNAPPROCESS 进程ID可以为0., 其他标志位的进程ID不能为0,枚举函数和返回值都应该相应的变化 输入 notepad++的进程id,然后,运行该程序,nodepad++.exe进程会被关闭 如果你创建了一个新的文件new.file,但是文件并未保存,再次打开,还是会出现new.file.文件依然没有保存 小游戏程序: win10运行在 x86目标程序 由于搜索出来的全局变量,的地址不止一个,需要在目标游戏程序再按下两次回车,直到,输出的地址唯一。 然后写入新的值,改变全局变量的值,从人 进程内核对象 当进程正在运行时,进程内核对象处于未通知状态。当进程停止运行时,就处于已通知状态。可以通过等待进程来检查进程是否仍然运行。 无成功等待的副作用。 线程内核对象 当线程正在运行时,线程内核对象处于未通知状态。当线程停止运行时,就处于已通知状态。可以通过等待线程来检查线程是否仍然运行。 无成功等待的副作用。 线程内核对象就是一个包含线程状态信息的数据结构。 创建线程使用 _begainthreadex 函数 所谓线程同步就是,保证一个时间内只有一个线程对某个共享资源有控制权。共享资源包括全局变量,公共数据成员或者句柄等 两个线程同时执行ThreadFunc 并修改静态区的变量。1秒之后,g_nCount1和g_nCount2 数值不一样, 原因g_nCount1++并非原子操作, 临界区对象是定义在数据段中的一个critical_section结构,windows内部使用这个结构记录一些信息,确保在同一时间只有一个线程访问改数据段的数据。 临界区对象能够很好地保护共享数据,但是不能够用于进程之间资源的锁定,因为它不是内核对象。如果要在进程间维持线程的同步,可以使用事件内核对象。 互锁函数为同步访问多线程共享变量提供一个简单机制。如果变量在共享内存,不同进程的线程也可以使用此机制。 主线程通过事件状态设为"授信"来通知子线程开始工作。这是事件内核对象一个很重要的用途 事件内核对象主要用于线程间通信,因为它是一个内核对象,所以可以跨进程使用。 依靠在线程间通信就可以使用各线程的工作协调进行,达到同步的目的。 信号量允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问次资源的最大线程数目。 信号量是通过计数来对线程访问资源进行控制,实际上,信号量也被称作 Dijstra计数器3. windows信号量使用 上述代码在开启线程前首先创建了一个初始计数和最大资源计数均为2的信号量对象hSemaphore。即在同一时刻只允许2个线程进入由hSemaphore保护的共享资源。 随后开启的三个线程均试图访问此共享资源,在前两个线程试图访问共享资源时,由于hSemaphore的当前可用资源计数分别为2和1,此时的hSemaphore是可以得到通知的,也就是说位于线程入口处的WaitForSingleObject()将立即返回,而在前两个线程进入到保护区域后,hSemaphore的当前资源计数减少到0,hSemaphore将不再得到通知,WaitForSingleObject()将线程挂起。直到此前进入到保护区的线程退出后才能得以进入。 保证多个线程对同一共享资源的互斥访问 线程局部存储(TLS)是一个方便存储线程局部数据的系统。 利用TLS机制可以为进程中所有的线程关联若干个数据,各个线程通过TLS 分配的全局索引来访问与自己关联的数据。这样每个线程都可以有线程局部的静态存储数据。 下面的例子就是将每个线程的创建时间与该线程关联起来,这样,在线程终止的时候就可以得到线程的生命周期。 Windows程序设计 标签:back uid onstop sea char debug 指针 scanf director 原文地址:https://www.cnblogs.com/chance0x1/p/12994959.html
1. Windows程序设计基础
1.1 代码风格
#include "stdafx.h"
#include
-- Beep--
WINBASEAPI
BOOL
WINAPI
Beep(
DWORD dwFreq,
DWORD dwDuration
);
说明
//用于生成简单的声音
返回值
//BOOL,TRUE 表示成功,否则返回零。会设置GetLastError
参数表
参数 类型及说明
//dwFreq Long,声音频率(从37Hz到32767Hz)。在windows95中忽略
//dwDuration Long,声音的持续时间,以毫秒为单位。如为-1
1.2 使用windowsAPI
#include "stdafx.h"
#include
-- MessageBox--
WINUSERAPI
int
WINAPI
MessageBoxA(
HWND hWnd ,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType);
WINUSERAPI
int
WINAPI
MessageBoxW(
HWND hWnd ,
LPCWSTR lpText,
LPCWSTR lpCaption,
UINT uType);
#ifdef UNICODE
#define MessageBox MessageBoxW
#else
#define MessageBox MessageBoxA
#endif // !UNICODE
说明
//消息弹框
返回值
int
//IDOK用户按下了“确认”按钮
//IDCANCEL用户按下了“取消”按钮
//IDABORT用户按下了“中止”按钮
//IDRETRY用户按下了“重试”按钮
//IDIGNORE用户按下了“忽略”按钮
//IDYES用户按下了“是”按钮
//IDNO用户按下了“否”按钮
参数表
参数 类型及说明
hWnd
//1. 该消息框的父窗口句柄
//2. 如果此参数为NULL,则该消息框没有拥有父窗口
lpText
//消息框的内容
lpCaption
//消息框的标题
uType
//1. 指定一个决定对话框的内容和行为的位标志集
//2. 此参数可以通过指定下列标志或标志的组合,来显示消息框中的按钮以及图标
uType参数定义解析
按钮含义
MB_OK默认值,有一个“确认”按钮在里面
MB_YESNO有“是”和“否”两个按钮在里面
MB_ABORTRETRYIGNORE有“中止”,“重试”和“跳过”三个按钮在里面
MB_YESNOCANCEL有“是”,“否”和“取消”三个按钮在里面
MB_RETRYCANCEL有“重试”和“取消”两个按钮在里面
MB_OKCANCEL有“确定”和“取消”两个按钮在里面
图标含义
MB_ICONEXCLAMATION一个惊叹号出现在消息框:?
MB_ICONWARNING一个惊叹号出现在消息框(同上)
MB_ICONINFORMATION一个圆圈中小写字母i组成的图标出现在消息框:?
MB_ICONASTERISK一个圆圈中小写字母i组成的图标出现在消息框(同上)
MB_ICONQUESTION一个问题标记图标出现在消息框:?
MB_ICONSTOP一个停止消息图标出现在消息框:?
MB_ICONERROR一个停止消息图标出现在消息框(同上)
MB_ICONHAND一个停止消息图标出现在消息框(同上)
默认按钮含义
MB_DEFBUTTON1指定第一个按钮为默认按钮
MB_DEFBUTTON2指定第二个按钮为默认按钮
MB_DEFBUTTON3指定第三个按钮为默认按钮
MB_DEFBUTTON4指定第四个按钮为默认按钮
2. Win32程序运行原理
2.1 创建进程
#include "stdafx.h"
#include
-- CreateProcess--
WINBASEAPI
BOOL
WINAPI
CreateProcessW(
LPCWSTR lpApplicationName,
LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCWSTR lpCurrentDirectory,
LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
#ifdef UNICODE
#define CreateProcess CreateProcessW
#else
#define CreateProcess CreateProcessA
#endif // !UNICODE
说明
//创建一个新进程(比如执行一个程序)
返回值
//Long,非零表示成功,零表示失败。会设置GetLastError
参数表
参数 类型及说明
lpApplicationName
//要执行的应用程序的名字。可设为vbNullString;在这种情况下,应用程序的名字应在lpCommandLine参数的起始处出现
lpCommandLine
//要执行的命令行。可用GetCommandLine函数取得一个进程使用的命令行。Windows会尽可能地根据下述搜索顺序来查找执行文件:
(1)包含了父进程执行文件的目录
(2)父进程当前的目录
(3)由GetSystemDirectory返回的系统目录
(4)仅适于windows NT:16位系统目录
(5)由GetWindowDirectory返回的Windows目录
(6)由PATH环境变量指定的目录
lpProcessAttributes
//指定一个SECURITY_ATTRIBUTES结构,或传递零值(将参数声明为ByVal As Long,并传递零值)——表示采用不允许继承的默认描述符。该参数定义了进程的安全特性
lpThreadAttributes
//指定一个SECURITY_ATTRIBUTES结构,或传递零值(将参数声明为ByVal As Long,并传递零值)——表示采用不允许继承的默认描述符。该参数定义了进程之主线程的安全特性
bInheritHandles
//表示允许当前进程中的所有句柄都由新建的子进程继承
dwCreationFlags
//来自API32.TXT文件的一个或多个下述常数之一,它们都带有前缀CREATE_。下面这些用于VB程序员:
//CREATE_SEPARATE_WOW_VDM(仅适用于NT) 启动一个16位的Windows应用程序时,强迫它在自己的内存空间运行
//CREATE_SHARED_WOW_VDM(仅适用于NT) 启动一个16位的Windows应用程序时,强迫它在共享的16位虚拟机(VM)内运行
//CREATE_SUSPENDED 立即挂起新进程。除非调用了ResumeThread函数函数,否则它不会恢复运行
也可能是下述常数之一,用于指定优先级
//IDLE_PRIORITY_CLASS 新进程应该有非常低的优先级——只有在系统空闲的时候才能运行。基本值是4
//HIGH_PRIORITY_CLASS 新进程有非常高的优先级,它优先于大多数应用程序。基本值是13。注意尽量避免采用这个优先级
//NORMAL_PRIORITY_CLASS 标准优先级。如进程位于前台,则基本值是9;如在后台,则优先值是7
//不要在VB中使用REALTIME_PRIORITY_CLASS
//lpEnvironment Any,指向一个环境块的指针(环境缓冲区的头一个字符,或者环境块的地址)
//lpCurrentDriectory String,新进程的当前目录路径。调用函数的时候,可用vbNullString指定当前目录
lpStartupInfo STARTUPINFO
//指定一个STARTUPINFO结构,其中包含了创建进程时使用的附加信息
lpProcessInformation
//该结构用于容纳新进程的进程和线程标识符。大多数情况下,一旦这个函数返回,父应用程序都会关闭两个句柄。
2.2 获取进程列表(跟任务管理器看到的一样)
#include "stdafx.h"
#include
输出
进程名称:atiesrxx.exe
进程ID号:1460
进程名称:dasHost.exe
进程ID号:1596
进程名称:atieclxx.exe
进程ID号:1632
进程名称:igfxCUIService.exe
进程ID号:1756
进程名称:svchost.exe
进程ID号:1916
进程名称:svchost.exe
进程ID号:2008
进程名称:svchost.exe
进程ID号:1812
进程名称:spoolsv.exe
标志位
枚举函数
返回值
PID
TH32CS_SNAPPROCESS
Process32First
PROCESSENTRY32
0
TH32CS_SNAPTHREAD
Thead32ListFirst
THREADENTRY32
非0
TH32CS_SNAPMODULE
Module32First
MODULEENTRY32
非0
TH32CS_SNAPHEAPLIST
Heap32ListFirst
HEAPLIST32
非0
2.3 终止线程
终止当前进程
#include "stdafx.h"
#include
终止其他进程
#include "stdafx.h"
#include
2.4 写一个修改内存的小游戏
#include "stdafx.h"
#include
#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
#include
3. windows程序执行单元
基本概念
已通知状态(受信状态) 未通知状态(非受信状态)
线程
3.1 线程创建
#include
3.2 线程内核对象
每一次对crateThread函数的成功调用,系统会在内部为新的线程分配一个内核对象。
系统提供的管理线程的函数其实就是依靠访问线程内核对象来实现管理的3.3 线程终止 见 2.3
3.4 线程优先级
#include
运行结果
Normal Thread is running
Normal Thread is running
Normal Thread is running
Normal Thread is running
Normal Thread is running
Normal Thread is running
Normal Thread is running
Normal Thread is running
Normal Thread is running
Normal Thread is running
Idle Thread is running
Idle Thread is running
Idle Thread is running
Idle Thread is running
Idle Thread is running
Idle Thread is running
Idle Thread is running
Idle Thread is running
Idle Thread is running
Idle Thread is running
只要有优先级高的线程调度是不允许 IDLE线程被CPU调度的
3.5 C++运行时库
线程同步
3.6 线程同步
3.6.1错误的demo
#include
3.6.2 使用临界区对象
#include
3.6.3 互锁函数
#include
3.6.4 事件内核对象
#include
运行结果
Please input a char to tell the Child Thread to work:
c
Child thread is working......
All the work has been finished.
3.6.5 信号量内核对象
// 信号量对象句柄
HANDLE hSemaphore;
UINT ThreadProc15(LPVOID pParam)
{
// 试图进入信号量关口
WaitForSingleObject(hSemaphore, INFINITE);
// 线程任务处理
AfxMessageBox("线程一正在执行!");
// 释放信号量计数
ReleaseSemaphore(hSemaphore, 1, NULL);
return 0;
}
UINT ThreadProc16(LPVOID pParam)
{
// 试图进入信号量关口
WaitForSingleObject(hSemaphore, INFINITE);
// 线程任务处理
AfxMessageBox("线程二正在执行!");
// 释放信号量计数
ReleaseSemaphore(hSemaphore, 1, NULL);
return 0;
}
UINT ThreadProc17(LPVOID pParam)
{
// 试图进入信号量关口
WaitForSingleObject(hSemaphore, INFINITE);
// 线程任务处理
AfxMessageBox("线程三正在执行!");
// 释放信号量计数
ReleaseSemaphore(hSemaphore, 1, NULL);
return 0;
}
……
void CSample08View::OnSemaphore()
{
// 创建信号量对象
hSemaphore = CreateSemaphore(NULL, 2, 2, NULL);
// 开启线程
AfxBeginThread(ThreadProc15, NULL);
AfxBeginThread(ThreadProc16, NULL);
AfxBeginThread(ThreadProc17, NULL);
}
3.6.6 互斥内核对象
#include "stdafx.h"
#include
3.6.7 线程局部存储
#include
结果
This thread is coming to end. Thread ID: 7296 , Used Time: 593
This thread is coming to end. Thread ID: 10108, Used Time: 609
This thread is coming to end. Thread ID: 6612 , Used Time: 640
This thread is coming to end. Thread ID: 10132, Used Time: 609
This thread is coming to end. Thread ID: 6248 , Used Time: 641
This thread is coming to end. Thread ID: 4748 , Used Time: 641
This thread is coming to end. Thread ID: 10540, Used Time: 625
This thread is coming to end. Thread ID: 1876 , Used Time: 625
This thread is coming to end. Thread ID: 9164 , Used Time: 625
This thread is coming to end. Thread ID: 7860 , Used Time: 641
下一篇:C#特性