并行程序设计—进程的创建与终止1/*2*exec.c(*)3*4*5*/67#includestdio.h8#includeprocess.h910void11main(void)12{13char*argv[]={execed,NULL};1415execv(execed,argv);1617printf(neverreached.);18}并行程序设计—进程的创建与终止1/*2*exec_cp.c3*/7#includewindows.h(*)9void10main(void)11{12STARTUPINFOsi;13PROCESS_INFORMATIONpi;1415GetStartupInfo(&si);1617CreateProcess(“execed.exe”,NULL,NULL18NULL,FALSE,0,NULL,NULL,&si,&pi);19}并行程序设计—进程的创建与终止CreateProcess说明:WIN32API函数CreateProcess用来创建一个新的进程和它的主线程,这个新进程运行指定的可执行文件。函数原型:BOOLCreateProcess(LPCTSTRlpApplicationName,LPTSTRlpCommandLine,LPSECURITY_ATTRIBUTESlpProcessAttributes。LPSECURITY_ATTRIBUTESlpThreadAttributes,BOOLbInheritHandles,DWORDdwCreationFlags,LPVOIDlpEnvironment,LPCTSTRlpCurrentDirectory,LPSTARTUPINFOlpStartupInfo,LPPROCESS_INFORMATIONlpProcessInformation);并行程序设计—进程的创建与终止参数lpApplicationName:指向一个NULL结尾的、用来指定可执行模块的字符串这个字符串可以使可执行模块的绝对路径,也可以是相对路径,在后一种情况下,函数使用当前驱动器和目录建立可执行模块的路径。这个参数可以被设为NULL,在这种情况下,可执行模块的名字必须处于lpCommandLine参数的最前面并由空格符与后面的字符分开。这个被指定的模块可以是一个Win32应用程序。如果适当的子系统在当前计算机上可用的话,它也可以是其他类型的模块(如MS-DOS或OS/2)。在WindowsNT中,如果可执行模块是一个16位的应用程序,那么这个参数应该被设置为NULL并且因该在lpCommandLine参数中指定可执行模块的名称。16位的应用程序是以DOS虚拟机或Win32上的Windows(WOW)为进程的方式运行。lpCommandLine:指向一个NULL结尾的、用来指定要运行的命令行。这个参数可以为空,那么函数将使用参数指定的字符串当作要运行的程序的命令行。如果lpApplicationName和lpCommandLine参数都不为空,那么lpApplicationName参数指定将要被运行的模块,lpCommandLine参数指定将被运行的模块的命令行。新运行的进程可以使用GetCommandLine函数获得整个命令行。C语言程序可以使用argc和argv参数。如果lpApplicationName参数为空,那么这个字符串中的第一个被空格分隔的要素指定可执行模块名。如果文件名不包含扩展名,那么.exe将被假定为默认的扩展名。如果文件名以一个点(.)结尾且没有扩展名,或文件名中包含路径,.exe将不会被加到后面。如果文件名中不包含路径,Windows将按照如下顺序寻找这个可执行文件:1.当前应用程序的目录。2.父进程的目录。3.Windows95:Windows系统目录,可以使用GetSystemDirectory函数获得。WindowsNT:32位Windows系统目录。可以使用GetSystemDirectory函数获得,目录名是SYSTEM32。4.在WindowsNT中:16位Windows系统目录。不可以使用Win32函数获得这个目录,但是它会被搜索,目录名是SYSTEM。5.Windows目录。可以使用GetWindowsDirectory函数获得这个目录。6.列在PATH环境变量中的目录。如果被创建的进程是一个以MS-DOS或16位Windows为基础的应用程序,lpCommandLine参数应该是一个以可执行文件的文件名作为第一个要素的绝对路径,因为这样做可以使32位Windows程序工作的很好,这样设置lpCommandLine参数是最强壮的。并行程序设计—进程的创建与终止lpProcessAttributes:指向一个SECURITY_ATTRIBUTES结构体,这个结构体决定是否返回的句柄可以被子进程继承。如果lpProcessAttributes参数为空(NULL),那么句柄不能被继承。在WindowsNT中:SECURITY_ATTRIBUTES结构的lpSecurityDescriptor成员指定了新进程的安全描述符,如果参数为空,新进程使用默认的安全描述符。在Windows95中:SECURITY_ATTRIBUTES结构的lpSecurityDescriptor成员被忽略。lpThreadAttributes:指向一个SECURITY_ATTRIBUTES结构体,这个结构体决定是否返回的句柄可以被子进程继承。如果lpThreadAttributes参数为空(NULL),那么句柄不能被继承。在WindowsNT中,SECURITY_ATTRIBUTES结构的lpSecurityDescriptor成员指定了主线程的安全描述符,如果参数为空,主线程使用默认的安全描述符。在Windows95中:SECURITY_ATTRIBUTES结构的lpSecurityDescriptor成员被忽略。bInheritHandles:指示新进程是否从调用进程处继承了句柄。如果参数的值为真,调用进程中的每一个可继承的打开句柄都将被子进程继承。被继承的句柄与原进程拥有完全相同的值和访问权限。dwCreationFlags:指定附加的、用来控制优先类和进程的创建的标志。并行程序设计—进程的创建与终止lpEnvironment:指向一个新进程的环境块。如果此参数为空,新进程使用调用进程的环境。一个环境块存在于一个由以NULL结尾的字符串组成的块中,这个块也是以NULL结尾的。每个字符串都是name=value的形式。因为相等标志被当作分隔符,所以它不能被环境变量当作变量名。与其使用应用程序提供的环境块,不如直接把这个参数设为空,系统驱动器上的当前目录信息不会被自动传递给新创建的进程。对于这个情况的探讨和如何处理,请参见注释一节。环境块可以包含Unicode或ANSI字符。如果lpEnvironment指向的环境块包含Unicode字符,那么dwCreationFlags字段的CREATE_UNICODE_ENVIRONMENT标志将被设置。如果块包含ANSI字符,该标志将被清空。请注意一个ANSI环境块是由两个零字节结束的:一个是字符串的结尾,另一个用来结束这个快。一个Unicode环境块石油四个零字节结束的:两个代表字符串结束,另两个用来结束块。lpCurrentDirectory:指向一个以NULL结尾的字符串,这个字符串用来指定子进程的工作路径。这个字符串必须是一个包含驱动器名的绝对路径。如果这个参数为空,新进程将使用与调用进程相同的驱动器和目录。这个选项是一个需要启动启动应用程序并指定它们的驱动器和工作目录的外壳程序的主要条件。lpStartupInfo:指向一个用于决定新进程的主窗体如何显示的STARTUPINFO结构体。lpProcessInformation:指向一个用来接收新进程的识别信息的PROCESS_INFORMATION结构体。返回值:如果函数执行成功,返回非零值。如果函数执行失败,返回零,可以使用GetLastError函数获得错误的附加信息。并行程序设计—多线程1/*2*thread1.c(*)5*/7#includestdio.h8#includestdlib.h9#includepthread.h11void*thread_entry_point(void*arg)12{13printf(thread2!\n);14}16int17main(void)18{19pthread_tpt;20intret=0;22ret=pthread_create(&pt,NULL,thread_entry_point,NULL);23if(ret!=0x00)24{25printf(pthread_create()failed.\n);26return(1);27}29sleep(1);31printf(thread1!\n);33return(0);34}并行程序设计—多线程1/*2*thread2.c(*)5*/7#includewindows.h8#includestdio.h10DWORDWINAPIthread_entry_point(LPVOIDarg)11{12printf(thread2!\r\n);14return(0);15}17int18main(void)19{20HANDLEh=NULL;22h=CreateThread(NULL,0,thread_entry_point,NULL,0,NULL);23if(h==NULL)24{25printf(CreateThread()failed.\r\n);26return(1);27}29Sleep(1000);31printf(thread1!\r\n);33return(0);34}并行程序设计—多线程1/*2*thread3.c5*/7#includestdio.h8#includepthread.h10//globalvars..11pthread_mutex_tlock;12intg_val=0;1314void*thread_entry_point(void*arg)15{16while(1)17{18pthread_mutex_lock(&lock);20++g_val;21printf(thread2,g_val:%d\n,g_val);23pthread_mutex_unlock(&lock);25usleep(1000000);26}27}28并行程序设计—多线程29int30main(void)31{32pthread_tpt;33intret=0;35ret=pthread_mutex_init(&lock,NULL);36if(ret!=0x00)37{38printf(pthread_mutex_init()failed.\n);39return(1);40}42ret=pthread_create(&pt,NULL,thread_entry_point,NULL);43if(ret!=0x00)44{45printf(pthread_create()failed.\n);46return(1);47}49while(1)50{51pthread_mutex_lock(&lock);53++g_val;54printf(thread1,g_val:%d\n,g_val);56pthread_mutex_unlock(&lock);58usleep(1000000);59}61pthread_mutex_destroy(&lock);62}并行程序设计—多线程1/*2*thread4.c5*/7#includewindows.h8#includestdio.h10//globalvars..11CRITICAL_SECTIONlock;12intg_val=0;14DWORDWI