Re_线程与进程

进程与线程是最常用的方式

进程

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

Windows

创建一个新的进程需要用到这个函数CreateProcess,下面是代码范例:

1
2
3
4
5
6
7
8
9
10
11
12
BOOL CreateProcess(
 LPCTSTR lpApplicationName, // 应用程序名称
 LPTSTR lpCommandLine, // 命令行字符串
 LPSECURITY_ATTRIBUTES lpProcessAttributes, // 进程的安全属性
 LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程的安全属性
 BOOL bInheritHandles, // 是否继承父进程的属性
 DWORD dwCreationFlags, // 创建标志
 LPVOID lpEnvironment, // 指向新的环境块的指针
 LPCTSTR lpCurrentDirectory, // 指向当前目录名的指针
 LPSTARTUPINFO lpStartupInfo, // 传递给新进程的信息
 LPPROCESS_INFORMATION lpProcessInformation // 新进程返回的信息
);

创建一个线程的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
TCHAR szCommandLine[] = TEXT("NOTEPAD");//或者WCHAR
//LPWSTR szCommandLine = TEXT("NOTEPAD");//错误
//STARTUPINFO si = { sizeof(si) };
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
si.dwFlags = STARTF_USESHOWWINDOW; // 指定wShowWindow成员有效
si.wShowWindow = TRUE; // 此成员设为TRUE的话则显示新建进程的主窗口,
// 为FALSE的话则不显示
BOOL bRet = ::CreateProcess (
NULL, // 不在此指定可执行文件的文件名
szCommandLine, // 命令行参数
NULL, // 默认进程安全性
NULL, // 默认线程安全性
FALSE, // 指定当前进程内的句柄不可以被子进程继承
CREATE_NEW_CONSOLE, // 为新进程创建一个新的控制台窗口
NULL, // 使用本进程的环境变量
NULL, // 使用本进程的驱动器和目录
&si,
&pi);
if(bRet)
{
WaitForSingleObject(pi.hProcess, INFINITE);
// 既然我们不使用两个句柄,最好是立刻将它们关闭
::CloseHandle (pi.hThread);
::CloseHandle (pi.hProcess);
printf(" 新进程的进程ID号:%d \n", pi.dwProcessId);
printf(" 新进程的主线程ID号:%d \n", pi.dwThreadId);
}
return 0;
}

Linux

fork是linux下创建进程,这里通过pipe来进行进程间的通讯(利用共享内存)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main()
{
int n;
int fd[2];
char buff[128] = {0};
pid_t pid;
if(pipe(fd)<0)
{
exit(1);
}
if((pid=fork())<0)
{
exit(1);
}
if( pid>0 )
{
close(fd[0]);
write(fd[1],"hello\n",6);
wait(NULL);
}
else
{
close(fd[1]);
n=read(fd[0],buff,128);
write(STDOUT_FILENO,buff,n);
}
return 0;
}

线程

Windows

进程是资源分配的最小单位,而线程呢,则是CPU运行的最小单位。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <windows.h>
//线程函数
DWORD WINAPI printThread(LPVOID lpParameter)
{
for (int i = 0; i < 100; i++)
{
printf("sub thread - %d\n",i+(int)lpParameter);
Sleep(500);
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
//创建一个线程,并让其挂起,不运行
HANDLE hThread = CreateThread(0, 0, printThread, (LPVOID)10, CREATE_SUSPENDED, 0);
for (int i = 0; i < 100; i++)
{
printf("main thread - %d\n", i + 1);
//当主线程输出到5的倍数时,恢复子线程运行
if (i % 5 == 0)
{
ResumeThread(hThread);
}
//当主线程输出到8的倍数时,暂停子线程运行
if (i % 8 == 0)
{
SuspendThread(hThread);
}
//直接杀掉子线程
//TerminateThread(hThread,0);
Sleep(500);
}
return 0;
}

Linux

线程标识

线程有ID, 但不是系统唯一, 而是进程环境中唯一有效.
线程的句柄是pthread_t类型, 该类型不能作为整数处理, 而是一个结构.

线程退出的条件

下面任意一个都可以。
1.调用pthread_exit函数退出。
2.其他线程调用pthread_cancel取消该线程,且该线程可被取消。
3.创建线程的进程退出或者整个函数结束。
4.当前线程代码执行完毕。
5.其中的一个线程执行exec类函数执行新的代码,替换当前进程所有地址空间。

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t mutex;
pthread_cond_t cond;
void *thread1(void *arg)
{
pthread_cleanup_push(pthread_mutex_unlock,&mutex);
//提供函数回调保护
while(1){
printf("thread1 is running\n");
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
printf("thread1 applied the condition\n");
pthread_mutex_unlock(&mutex);
sleep(4);
}
pthread_cleanup_pop(0);
}
void *thread2(void *arg)
{
while(1){
printf("thread2 is running\n");
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
printf("thread2 applied the condition\n");
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
int main()
{
pthread_t thid1,thid2;
printf("condition variable study!\n");
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
pthread_create(&thid1,NULL,(void*)thread1,NULL);
pthread_create(&thid2,NULL,(void*)thread2,NULL);
do{
pthread_cond_signal(&cond);
}while(1);
sleep(20);
pthread_exit(0);
return 0;
}

区别

1
2
3
4
进程优点:编程、调试简单,可靠性较高。
进程缺点:创建、销毁、切换速度慢,内存、资源占用大。
线程优点:创建、销毁、切换速度快,内存、资源占用小。
线程缺点:编程、调试复杂,可靠性较差。
Donate
-------------本文结束感谢您的阅读-------------