介绍
在现代操作系统中,每个进程都有自己的地址空间和一个控制线程。然而,在实践中,我们经常遇到需要在单个进程中执行多个并发任务并访问相同进程组件的情况:结构、打开的文件描述符等。
在任何情况下组织多线程模型都需要同时访问相同的资源。本文提供了有关 Windows 和 Linux 操作系统中线程的一般信息,然后介绍了防止访问共享资源的同步机制[1] 。
对于那些处理从一个系统移植到另一个系统的应用程序或在一个系统中创建多线程应用程序并想知道它在另一个系统中如何实际实现的人来说,这篇文章将会很有趣。本文对于那些从未编写过多线程应用程序但计划在未来这样做的人也很有用。
线程概念
这些线程是做什么用的?为什么我们不能只创建流程?后一种范式已经工作了很多年,但是流程创建有一些缺点,下面举几个例子:
进程创建操作是资源密集型的。
进程需要复杂的机制来访问相同的资源(命名或未命名的管道、消息队列、套接字等),而线程会自动获得对相同地址空间的访问权。
多线程进程的性能高于单线程。
多线程允许多个线程作为一个进程的一部分执行。具有线程的编程模型为开发人员提供了对同时执行的舒适抽象。具有线程的程序的优点之一是它在具有多核处理器的计算机上运行得更快。线程在创建时几乎不使用资源,或者额外的插件,例如资源访问机制;此外,线程的性能和应用程序交互性更高。除了地址空间,所有线程都使用:
工艺规定
信号处理程序(处理信号的设置)
当前目录
用户和组标识符
同时,每个线程都有自己的:
线程标识符
堆
寄存器集
信号屏蔽
优先
使用线程的主要函数
在通过 exec 调用启动程序时,会创建一个主线程(初始线程)。辅助线程是通过调用 Linux 的 pthread_create 或 Windows 的 _beginthread(ex) 创建的。
让我们更仔细地看看 Linux 的线程创建:
#include
int pthread_create(
pthread_t *tid,
const pthread_attr_t *attr,
void *(*func)(void *),
void *arg
);
/* Returns 0 in case of a successful completion, positive value in case of an error*/
每个线程都有它的标识符——pthread_t——和属性:优先级、初始堆栈大小、守护进程特性。创建线程时,需要指明将要执行的函数地址(func),以及单指针参数(arg)。Linux 中的线程应显式退出——通过调用pthread_exit函数——或隐式退出——通过从该函数返回[2]。如果在问题的条件下需要将多个参数传递给线程,则必须使用带参数的结构地址。
在 Windows 中,线程是在_beginthread(ex)或CreateThread函数的帮助下创建的。两者都是 ?-runtime 调用,它们之间的主要区别在于CreateThread是一个“原始”Win32 API,而_beginthread(ex)在其内部调用CreateThread 。在本文中,我们将讨论_beginthread(ex)函数。_beginthreadex的语法如下:
uintptr_t _beginthreadex(
void *security,
unsigned stack_size,
unsigned(__stdcall *start_address)(void *),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);
可以观察到pthread_create和_beginthreadex调用之间有一些模糊的相似性;但是,也存在差异。?hus,在 Windows 中:security– 指向SECURITY_ATTRIBUTES结构的指针,thrdaddr– 指向接收线程标识符的 32 位变量。
让我们考虑以下线程创建示例:
#include
#ifdef __PL_WINDOWS__
#include
#endif //__PL_WINDOWS__
#ifdef __PL_LINUX__
#include
#endif //__PL_LINUX__
#define STACK_SIZE_IN_BYTES (2097152) //2MB
#ifdef __PL_WINDOWS__
unsigned int __stdcall process_command_thread(void) {
#endif //__PL_WINDOWS__
#if defined (__PL_LINUX__) || (__PL_SOLARIS__) || (__PL_MACOSX__)
void *process_command_thread(void *p) {
#endif //(__PL_LINUX__) || (__PL_SOLARIS__) || (__PL_MACOSX__)
printf("Hello from process command thread\n");
return 0;
}
int main(int argc, char *argv[])
{
#ifdef __PL_WINDOWS__
DWORD process_command_thread_id;
HANDLE h_process_command_thread;
h_process_command_thread = (HANDLE)_beginthreadex(
NULL,
STACK_SIZE_IN_BYTES,
process_command_thread,
NULL,
0,
(unsigned long *)&process_command_thread_id
);
if (h_process_command_thread == NULL)
return -1;
#endif //__PL_WINDOWS__
#ifdef __PL_LINUX__
pthread_t h_process_command_thread;
int h_process_command_thread_initialized;
int ret;
ret = pthread_create(
&h_process_command_thread,
NULL,
process_command_thread,
NULL
);
if (ret != 0)
return -1;
h_process_command_thread_initialized = 1;
#endif // __PL_LINUX__
printf("Hello from main thread\n");
return 0;
}
输出将如下:
很容易注意到 process_command_thread 没有以可视方式运行。当用于线程管理的内部结构被pthread_create或_beginthreadex函数初始化时,主线程完成执行。在 Linux 中调用 pthread_join 后,我们可以期待线程退出。
int pthread_join(pthread_t tid, void **retval);
线程可以是可连接的(默认情况下)或分离的。当一个可连接线程终止时,信息(标识符、终止状态、线程计数器等)会一直保存到调用pthread_join为止。
在 Windows 操作系统中,可以认为等待函数之一类似于pthread_join。等待函数系列允许线程中断其执行并等待资源被释放。让我们看一下pthread_join的类似物,即WaitForSingleObject:
DWORD WaitForSingleObject(HANDLE hObject, DWORD dwMilliseconds);
调用此函数时,第一个参数hObject标识内核对象。该对象可能处于以下两种状态之一:“空闲”或“忙碌”。
第二个参数dwMilliseconds表示线程准备等待释放对象的毫秒数。
以下示例说明了pthread_join\WaitForSingleObject调用:
#ifdef __PL_WINDOWS__
DWORD status = WaitForSingleObject(
h_process_command_thread,
INFINITE
);
switch (status) {
case WAIT_OBJECT_0:
// The process terminated
break;
case WAIT_TIMEOUT:
// The process did not terminate within timeout
break;
case WAIT_FAILED:
// Bad call to function
break;
}
#endif //__PL_WINDOWS__
#ifdef __PL_LINUX__
int status = pthread_join(
h_process_command_thread,
NULL
);
switch (status) {
case 0:
// The process terminated
break;
case default:
// Bad call to function
break;
}
#endif //__PL_LINUX__
#ifdef __PL_WINDOWS__
//Windows code
#endif //__PL_WINDOWS__
#ifdef __PL_LINUX__
//Code for UNIX OS systems
#endif //__PL_LINUX__
审核编辑:郭婷
-
Linux
+关注
关注
87文章
11285浏览量
209267 -
WINDOWS
+关注
关注
3文章
3540浏览量
88596 -
操作系统
+关注
关注
37文章
6794浏览量
123275
发布评论请先 登录
相关推荐
评论