【转】Native Thread for Win32 C- Creating Processes(通俗易懂,非常好)
To create a new process, we need to call CreateProcess().
Syntax:
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
);
Parameters:
- lpApplicationName [in, optional]
The name of the module to be executed.
This module can be a Windows-based application.
It can be some other type of module (for example, MS-DOS or OS/2) if the appropriate subsystem is available on the local computer.
The string can specify the full path and file name of the module to execute or it can specify a partial name. In the case of a partial name, the function uses the current drive and current directory to complete the specification. The function will not use the search path. This parameter must include the file name extension; no default extension is assumed.
The lpApplicationName parameter can be NULL.
In that case, the module name must be the first white space delimited token in the lpCommandLine string. - lpCommandLine [in, out, optional]
The command line to be executed. The maximum length of this string is 32,768 characters, including the Unicode terminating null character. If lpApplicationName is NULL, the module name portion of lpCommandLine is limited to MAX_PATH characters.
The lpCommandLine parameter can be NULL. In that case, the function uses the string pointed to by lpApplicationName as the command line.
If both lpApplicationName and lpCommandLine are non-NULL, the null-terminated string pointed to by lpApplicationName specifies the module to execute, and the null-terminated string pointed to by lpCommandLine specifies the command line. The new process can use GetCommandLine to retrieve the entire command line. Console processes written in C can use the argc and argv arguments to parse the command line. Because argv[0] is the module name, C programmers generally repeat the module name as the first token in the command line.
- lpProcessAttributes [in, optional]
A pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle to the new process object can be inherited by child processes. If lpProcessAttributes is NULL, the handle cannot be inherited.
- lpThreadAttributes [in, optional]
A pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle to the new thread object can be inherited by child processes. If lpThreadAttributes is NULL, the handle cannot be inherited.
The lpSecurityDescriptor member of the structure specifies a security descriptor for the main thread. If lpThreadAttributes is NULL o rlpSecurityDescriptor is NULL, the thread gets a default security descriptor. The ACLs in the default security descriptor for a thread come from the process token.
- bInheritHandles [in]
If this parameter TRUE, each inheritable handle in the calling process is inherited by the new process. If the parameter is FALSE, the handles are not inherited. Note that inherited handles have the same value and access rights as the original handles.
- dwCreationFlags [in]
The flags that control the priority class and the creation of the process.
This parameter also controls the new process's priority class, which is used to determine the scheduling priorities of the process's threads.
If none of the priority class flags is specified, the priority class defaults to NORMAL_PRIORITY_CLASS unless the priority class of the creating process is IDLE_PRIORITY_CLASSBELOW_NORMAL_PRIORITY_CLASS. In this case, the child process receives the default priority class of the calling process.
- lpEnvironment [in, optional]
A pointer to the environment block for the new process. If this parameter is NULL, the new process uses the environment of the calling process.
An environment block consists of a null-terminated block of null-terminated strings. Each string is in the following form:name=value\0
Because the equal sign is used as a separator, it must not be used in the name of an environment variable.
An environment block can contain either Unicode or ANSI characters.
If the environment block pointed to by lpEnvironment contains Unicode characters, be sure that dwCreationFlags includes CREATE_UNICODE_ENVIRONMENT.
If this parameter is NULL and the environment block of the parent process contains Unicode characters, you must also ensure that dwCreationFlags includes CREATE_UNICODE_ENVIRONMENT.
- lpCurrentDirectory [in, optional]
The full path to the current directory for the process. The string can also specify a UNC path.
If this parameter is NULL, the new process will have the same current drive and directory as the calling process. (This feature is provided primarily for shells that need to start an application and specify its initial drive and working directory.)
- lpStartupInfo [in]
A pointer to a STARTUPINFO or STARTUPINFOEX structure.
To set extended attributes, use a STARTUPINFOEX structure and specify EXTENDED_STARTUPINFO_PRESENT in the dwCreationFlags parameter. Handles in STARTUPINFO must be closed with CloseHandle when they are no longer needed.
- lpProcessInformation [out]
A pointer to a PROCESS_INFORMATION structure that receives identification information about the new process.
Handles in PROCESS_INFORMATION must be closed with CloseHandle when they are no longer needed.
The following example shows the steps necessary to create a new process. If the application is started with a command-line parameter, the process will print this out and then create a child process without any parameters. If the process is started without any parameters, it prints out a message indicating this and exits.
#include <Windows.h>
#include <stdio.h> int main(int argc, char* argv[])
{
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInfo; if(argc > 1) {
printf("Argument %s\n", argv[1]);
printf("Starting child process\n"); memset(&startupInfo;, 0, sizeof(startupInfo));
memset(&processInfo;, 0, sizeof(processInfo)); startupInfo.cb = sizeof(startupInfo); if(CreateProcess(argv[0], 0, 0, 0, 0, 0, 0, 0,
&startupInfo;, &processInfo;) == 0)
{
printf(" Error %d\n", GetLastError());
}
WaitForSingleObject(processInfo.hProcess, INFINITE);
}
else {
printf("No argument\n");
} getchar(); return 0;
}
Suppose the executable of the above code is MyProc.exe. If we type "MyProc.exe myArgument" into command line, the output we get is:
Argument myArgument
Starting child process
No argument
The handle of the created process is returned in processInfo.hProcess. This handle is used to call WaitForSingleObject(). This call returns when the child process exits. The child process did not have any argument in the example, so the "No argument" was the output from the child process while the "Argument myArgument" was from the main process.
The following example is passing arguments to a child process. We need to repeat the application name as the first command-line parameter, "MyProc.exe myArgument". The entire command line gets passed to the child process.
#include <Windows.h>
#include <stdio.h> int main(int argc, char* argv[])
{
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInfo; if(argc == 1) {
char Args[256];
sprintf_s(Args, "dummyArgs %s", argv[0]);
memset(&startupInfo;, 0, sizeof(startupInfo));
memset(&processInfo;, 0, sizeof(processInfo)); startupInfo.cb = sizeof(startupInfo); if(CreateProcess(argv[0], Args,
0, 0, 0, 0, 0, 0, &startupInfo;, &processInfo;) == 0)
{
printf(" Error %d\n", GetLastError());
}
WaitForSingleObject(processInfo.hProcess, INFINITE);
}
else {
printf("Argument %s\n", argv[1]);
} getchar(); return 0;
}
Output is:
Argument myArgument
Processes can share memory between them. Once one process has set up a region of memory with sharing attributes, another can open that region of memory and map it into its address space.
The file mapping function CreateFileMapping() is used by the shared memory. The parameter INVALID_HANDLE_VALUE is for creating a handle to a region of shared memory. This can then be mapped into the process by calling MapViewOfFile(). Except the fact that the function OpenFileMapping() is used to obtain the handle, the steps of attaching to an existing region of shared memory are similar.
An object can be shared between processes either by sharing the object's handle or by using a common name. The name can contain any character except a backslash and must start with either the local namespace identifier Local\ or the global namespace identifier Global\. The local namespace is private to each user while the global namespace is shared by all users.
The OpenFileMapping() call which opens an existing file mapping object takes three parameters:
HANDLE WINAPI OpenFileMapping(
__in DWORD dwDesiredAccess,
__in BOOL bInheritHandle,
__in LPCTSTR lpName );
- The first parameter gives the security attributes for the mapping object, which usually will be FILE_MAP_ALL_ACCESS to allow both reading and writing to the share memory.
- The second parameter is a boolean that determines whether the handle can be inherited by child processes.
- The third parameter is the name of the mapping object.
The CreateFileMapping() call creates the mapping object in the kernel, however, it does not actually map the object into user space. The call to MapViewOfFile() causes the shared object to be mapped into memory. The return value of this call is a pointer to the base address of the memory. This call takes file parameters:
LPVOID WINAPI MapViewOfFile(
__in HANDLE hFileMappingObject,
__in DWORD dwDesiredAccess,
__in DWORD dwFileOffsetHigh,
__in DWORD dwFileOffsetLow,
__in SIZE_T dwNumberOfBytesToMap );
Parameters:
- hFileMappingObject [in]
A handle to a file mapping object. The CreateFileMapping and OpenFileMappingfunctions return this handle.
- dwDesiredAccess [in]
The type of access to a file mapping object, which determines the protection of the pages. This parameter can be one of the following values.
- dwFileOffsetHigh [in]
A high-order DWORD of the file offset where the view begins.
- dwFileOffsetLow [in]
A low-order DWORD of the file offset where the view is to begin. The combination of the high and low offsets must specify an offset within the file mapping. They must also match the memory allocation granularity of the system. That is, the offset must be a multiple of the allocation granularity. To obtain the memory allocation granularity of the system, use the GetSystemInfo function, which fills in the members of a SYSTEM_INFO structure.
- dwNumberOfBytesToMap [in]
The number of bytes of a file mapping to map to the view. All bytes must be within the maximum size specified by CreateFileMapping . If this parameter is 0 (zero), the mapping extends from the specified offset to the end of the file mapping.
Once the process has finished with the shared memory, it needs to be unmapped by calling UnMapViewOfFile(), which takes the base address of the shared memory as a parameter:
BOOL WINAPI UnmapViewOfFile(
__in LPCVOID lpBaseAddress
);
Then, the handle can be closed by calling CloseHandle().
The following example demonstrates how a region of memory can be created and then shared between two processes. If the application is started without any parameters, it will create a child process. The parent process will also create a region of shared memory and store a string into the shared memory. The shared memory is given the name sharedmemory:
char ID[] = TEXT("Local\\sharedmemory");
It is created in the Local\ namespace. So, it is visible to all the processes owned by the user.
The child process attaches to the shared memory and can print out the value of the string stored there by the parent process. Once the child process has printed the string, it unmaps the memory and closes the file handle before exiting. Once the child process has exited, the parent process is free to unmap the memory, close the file handle, and then exit.
#include <Windows.h>
#include <stdio.h> int main(int argc, char* argv[])
{
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInfo;
HANDLE fileHandle;
char ID[] = TEXT("Local\\sharedmemory");
char *memory; if(argc == 1) {
fileHandle = CreateFileMapping(INVALID_HANDLE_VALUE,
NULL, PAGE_READWRITE, 0, 1024, ID);
memory = (char*)MapViewOfFile(fileHandle,
FILE_MAP_ALL_ACCESS, 0, 0, 0);
sprintf_s(memory, 1024, "%s", "Data from first process");
printf("First process: %s\n", memory); memset(&startupInfo;, 0, sizeof(startupInfo));
memset(&processInfo;, 0, sizeof(processInfo));
startupInfo.cb = sizeof(startupInfo); char Args[256];
sprintf_s(Args, "dummyArgs %s", argv[0]); CreateProcess(argv[0], Args,
0, 0, 0, 0, 0, 0, &startupInfo;, &processInfo;);
WaitForSingleObject(processInfo.hProcess, INFINITE); UnmapViewOfFile(memory);
CloseHandle(fileHandle);
}
else {
fileHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, ID);
memory = (char*)MapViewOfFile(fileHandle,
FILE_MAP_ALL_ACCESS, 0, 0, 0); printf("Second process %s\n", memory); UnmapViewOfFile(memory);
CloseHandle(fileHandle);
} getchar(); return 0;
}
The output we get:
First process: Data from first process
Second process Data from first process
To share a mutex between processes, we need to create mutex with a name. Then, other process can use the OpenMutex() or CreateMutex() to get a handle to the mutex. Here are the complexities involved in this:
- Only one process can create the mutex, and the others just open the existing mutex.
- The name should be unique.
- The name of the mutex should be passed to the other processes.
In the example below, the mutex is created by CteateMutex(). Here, we create two copies of the same processes and enables them to share a mutex.
#include <Windows.h>
#include <stdio.h> int main(int argc, char* argv[])
{
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInfo;
HANDLE sharedmutex; ZeroMemory(&startupInfo;,sizeof(startupInfo));
ZeroMemory(&processInfo;,sizeof(processInfo));
startupInfo.cb = sizeof(startupInfo); sharedmutex = CreateMutex(0,0,"MyMutex"); if(GetLastError() != ERROR_ALREADY_EXISTS)
{
if(CreateProcess(argv[0],0,0,0,0,0,0,0, &startupInfo;, &processInfo;) == 0) {
printf("ERROR %d : Mutex already exists\n", GetLastError());
} WaitForInputIdle(processInfo.hProcess, INFINITE);
} WaitForSingleObject(processInfo.hProcess, INFINITE); for(int i = 0; i <20; i++) {
printf("Process %d Count %d\n", GetCurrentProcessId(),i);
} ReleaseMutex(sharedmutex);
CloseHandle(sharedmutex); getchar();
return 0;
}
Output is;
ERROR 2 : Mutex already exists
Process 6200 Count 0
Process 6200 Count 1
Process 6200 Count 2
Process 6200 Count 3
Process 6200 Count 4
Process 6200 Count 5
Process 6200 Count 6
Process 6200 Count 7
Process 6200 Count 8
Process 6200 Count 9
Process 6200 Count 10
Process 6200 Count 11
Process 6200 Count 12
Process 6200 Count 13
Process 6200 Count 14
Process 6200 Count 15
Process 6200 Count 16
Process 6200 Count 17
Process 6200 Count 18
Process 6200 Count 19
If the mutex already exists, then a handle to the existing mutex is returned, and the error condition is set to ERROR_ALREADY_EXISTS. If this is not the error condition, then it is assumed by the code that this means that the mutex was created by the calling process, and the calling process needs to start a second copy. Note that the call to CreateMutex() takes the name of the mutex. The shared mutex is used to ensure that only one of the two processes counts up to 20 at a time. If there was no mutex, then both processes could be active simultaneously, and the console output would be a mix of the output from both processes. By using the mutex, the output is from just one of the processes at a time.
【转】Native Thread for Win32 C- Creating Processes(通俗易懂,非常好)的更多相关文章
- 【转】Native Thread for Win32 B-Threads Synchronization(通俗易懂,非常好)
http://www.bogotobogo.com/cplusplus/multithreading_win32B.php Synchronization Between Threads In t ...
- 【转】Native Thread for Win32 A- Create Thread(通俗易懂,非常好)
http://www.bogotobogo.com/cplusplus/multithreading_win32A.php Microsoft Windows operating system's s ...
- JVM最多能创建多少个线程: unable to create new native thread
转载自:http://www.rigongyizu.com/jvm-max-threads/ 有应用报出这样的异常“java.lang.OutOfMemoryError: unable to crea ...
- 记一次tomcat线程创建异常调优:unable to create new native thread
测试在进行一次性能测试的时候发现并发300个请求时出现了下面的异常: HTTP Status 500 - Handler processing failed; nested exception is ...
- 解决Unable to create new native thread
两种类型的Out of Memory java.lang.OutOfMemoryError: Java heap space error 当JVM尝试在堆中分配对象,堆中空间不足时抛出.一般通过设定J ...
- JVM截至多少线程可以创建: unable to create new native thread
最近的测试需要很长的连接server.这些数据需要达到100W长连接,试client.一个线程来保持连接.查找linuxserver创建者默认3200当多个线程.这个错误将得到"java.l ...
- spark大批量读取Hbase时出现java.lang.OutOfMemoryError: unable to create new native thread
这个问题我去网上搜索了一下,发现了很多的解决方案都是增加的nproc数量,即用户最大线程数的数量,但我修改了并没有解决问题,最终是通过修改hadoop集群的最大线程数解决问题的. 并且网络上的回答多数 ...
- JVM虚拟机宕机_java.lang.OutOfMemoryError: unable to create new native thread
原因:当前用户的系统最最大程序数数已达到最大值,使用ulimit -u可以看到是1024 解决办法:在当前用户下使用ulimit -u 65535 然后再执行jsp,一切ok 功能说明:控 ...
- 剥下“java.lang.OutOfMemoryError: unable to create new native thread”的外衣 创建线程数公式(MaxProcessMemory - JVMMemory – ReservedOsMemory)
剥下“java.lang.OutOfMemoryError: unable to create new native thread”的外衣 星期一早上到了公司,据称产品环境抛出了最可爱的异常—OutO ...
随机推荐
- 关于RHEL6下桥网配置的写法(ifcfg-eth0,ifcfg-br0) / 在阿里云的CentOS上安装docker
Posted on 2011-07-28 16:46 zhousir1991 阅读(1978) 评论(0) 编辑 收藏 以下仅仅是我在做练习的时候下的环境,参照写即可: [root@desktop2 ...
- PHP - MAC下PhpStorm安装调试环境xdebug
今天下午一直在捣鼓如何用PhpStorm进行调试,查找了许多资料,零零碎碎的,所以自己弄篇文章记录一下步骤. 安装xdebug 使用brew安装xdebug,语法如下 brew install hom ...
- Android 5.0最应该实现的8个期望
毫无疑问,Android 5 将是令人兴奋的操作系统,因为 Android4.0 至 4.4 版本之间并没有显著的差异,显然谷歌会在 5.0 版本中进行一些较大幅度的革新.那么,代号为“柠檬芝士蛋糕” ...
- ItelliJ基于Gradle创建及发布Web项目(二)
上一篇介绍了IteliJ创建WEB项目的过程,这一篇介绍一下和本地WEB服务器(以Tomcat为例)的关联方法和发布流程. WEB服务器的关联 1. 点击IDE右上角的一个带有三角形标识的按钮,如下图 ...
- DataGridView添加右键菜单等技巧
1). 添加一个快捷菜单contextMenuStrip1:2). 给dataGridView1的CellMouseDown事件添加处理程序: 程序代码 private void DataGridV ...
- MS SQL表字段自增相关的脚本
--查询表是否有自增字段 SELECT OBJECTPROPERTY(OBJECT_ID('[表名]'), 'TableHasIdentity') --查询表的自增字段 SELECT COLUMN_N ...
- 应用SVN比较文件定位修改
用SVN checkout一个版A本到一个目录中,再从别的地方找到版本B复制到版本A所在的目录中,选择复制和替换,再要比较的文件上右键-->SVN-->diff
- UIImageView的一些用法
转自:http://blog.sina.com.cn/s/blog_60e2dbcf01014bfm.html //初始化 UIImageView *imageView=[[UIImageView ...
- docker使用问题总结
1. docker报[Error response from daemon: Error running DeviceCreate (createSnapDevice) dm_task_run fai ...
- Android 开发之Android 应用程序如何调用支付宝接口
1.到支付宝官网,下载支付宝集成开发包 由于android设备一般用的都是无线支付,所以我们申请的就是支付宝无线快捷支付接口.下面是申请的地址以及下载接口开发包的网址:https://b.alipay ...