0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux和Windows系统中的线程同步

星星科技指导员 来源:嵌入式计算设计 作者:Eduard Trunov 2022-11-30 15:13 次阅读

介绍

在现代操作系统中,每个进程都有自己的地址空间和一个控制线程。然而,在实践中,我们经常面临需要在单个进程中执行多个并发任务并访问相同流程组件的情况:结构、打开文件描述符等。

在任何情况下组织多线程模型都需要同时访问相同的资源。本文提供有关 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

);

/* 成功完成时返回 0,出错时返回正值*/

每个线程都有其标识符 –pthread_t– 和属性:优先级、初始堆栈大小、守护程序功能。创建线程时,必须指示将执行的函数地址 (func) 以及单指针参数 (arg)。Linux 中的线程应显式退出 –pthread_exit通过调用函数 – 或间接退出 – 通过从该函数返回[2]。如果在问题条件下需要将多个参数传递给线程,则必须将结构的地址与参数一起使用。

在Windows中,线程是在_beginthread(ex)或CreateThread函数的帮助下创建的。两者都是运行时调用,它们之间的主要区别在于 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, in Windows:security– 指向结构的指针SECURITY_ATTRIBUTES,thrdaddr– 指向接收线程标识符的 32 位变量。

让我们考虑以下线程创建示例[3]:

#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 threadn”);

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 threadn”);

return 0;

}

输出将如下所示:

Linux目录窗户

[root@localhost~]# 。/进程

来自主线程的你好

[root@localhost ~]#C:》进程.exe

来自主线程的你好

C:》

很容易注意到process_command_thread不是以可视方式运行的。当用于线程管理的内部结构由pthread_createor_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_joinWaitForSingleObject调用:

#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,本文介绍了由 POSIX.1-2001 标准(称为“pthreads”)定义的线程接口

本文稍后将介绍线程退出。

在此示例中,与本文中的其他示例一样,Linux 和 Windows 的代码库都是单一的。区别在于编译条件:

#ifdef __PL_WINDOWS__

//Windows code

#endif //__PL_WINDOWS__

#ifdef __PL_LINUX__

//Code for UNIX OS systems

#endif //__PL_LINUX__

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    11221

    浏览量

    208883
  • WINDOWS
    +关注

    关注

    3

    文章

    3524

    浏览量

    88402
收藏 人收藏

    评论

    相关推荐

    socket 多线程编程实现方法

    是指在同一个进程运行多个线程,每个线程可以独立执行任务。线程共享进程的资源,如内存空间和文件句柄,但每个线程有自己的程序计数器、寄存器集合
    的头像 发表于 11-12 14:16 199次阅读

    Windows操作系统的常用命令

    这些命令不仅能提高工作效率,还能帮助用户解决许多复杂的问题。本系列文章将详细介绍Windows操作系统的常用命令,帮助你成为Windows极客!
    的头像 发表于 08-07 15:40 505次阅读
    <b class='flag-5'>Windows</b>操作<b class='flag-5'>系统</b><b class='flag-5'>中</b>的常用命令

    研华工控机用什么系统WindowsLinux操作系统的较量

    工控机用什么系统WindowsLinux操作系统的较量。工控机(工业控制计算机)作为工业自动化和监控系统的核心组件,其稳定性、可靠性和性
    的头像 发表于 06-14 14:38 623次阅读
    研华工控机用什么<b class='flag-5'>系统</b>?<b class='flag-5'>Windows</b>与<b class='flag-5'>Linux</b>操作<b class='flag-5'>系统</b>的较量

    python5种线程锁盘点

    线程安全是多线程或多进程编程的一个概念,在拥有共享数据的多条线程并行执行的程序线程安全的代
    发表于 03-07 11:08 1477次阅读
    python<b class='flag-5'>中</b>5种<b class='flag-5'>线程</b>锁盘点

    3562-Linux系统启动卡制作及系统固化

    至 eMMC 的方 法。 使用瑞芯微创建升级磁盘工具 SDDiskTool_v1.74 可将 Linux 系统镜像通过读卡器固化 至 Micro SD 卡,将 Micro SD 卡制作成“SD
    的头像 发表于 03-05 15:58 276次阅读
    3562-<b class='flag-5'>Linux</b><b class='flag-5'>系统</b>启动卡制作及<b class='flag-5'>系统</b>固化

    嵌入式系统线程、进程与任务概念与区别

    每个线程与主程序共用地址空间,受限于2GB地址空间; 2)线程之间的同步和加锁控制比较麻烦;一个线程的崩溃可能影响到整个程序的稳定性
    发表于 03-04 15:03 1177次阅读
    嵌入式<b class='flag-5'>系统</b><b class='flag-5'>中</b>的<b class='flag-5'>线程</b>、进程与任务概念与区别

    linux服务器和windows服务器

    Linux服务器和Windows服务器是目前应用最广泛的两种服务器操作系统。两者各有优劣,也适用于不同的应用场景。本文将 对Linux服务器和Win
    发表于 02-22 15:46

    linux线程编程实例

    linux线程
    的头像 发表于 02-15 21:16 412次阅读
    <b class='flag-5'>linux</b>多<b class='flag-5'>线程</b>编程实例

    linuxwindows的区别 linux系统一般用来干嘛

    LinuxWindows是两种不同的操作系统,有着不同的设计理念和用途。本文将对LinuxWindows的区别进行详细分析,并介绍
    的头像 发表于 02-05 14:06 871次阅读

    .NET8性能优化之线程

    目前来说,没有确切的证据证明哪个线程池好用,或者效率更高。但是开发者可以使用上面的选项来进行自己的选择,有一个测试就是在Windows线程池在比较大的机器上的IO扩展性不太好。如果你的应用程序已经
    的头像 发表于 01-22 14:50 1084次阅读

    Linux上怎么配置NTP时间同步呢?

    Linux上怎么配置NTP时间同步呢? NTP是一种用于同步计算机系统时钟的网络协议。在Linux系统
    的头像 发表于 01-16 16:03 2807次阅读

    如何解决Linux系统的网络连接问题?

    如何解决Linux系统的网络连接问题? Linux系统的网络连接问题是常见的技术难题之一,通
    的头像 发表于 01-12 15:17 887次阅读

    mfc多线程编程实例

    (图形用户界面)应用程序的开发。在这篇文章,我们将重点介绍MFC的多线程编程。 多线程编程在软件开发中非常重要,它可以实现程序的并发执行,提高程序的效率和响应速度。MFC提供了丰富
    的头像 发表于 12-01 14:29 1419次阅读

    安装Linuxwindows在哪启动

    操作系统引导加载程序,可以管理多个操作系统的启动。它允许用户在系统启动时选择要运行的操作系统。本文将详细介绍 Linux 安装后
    的头像 发表于 11-28 15:02 1121次阅读

    linux系统备份与还原工具

    Linux系统备份与还原工具是用于备份和恢复Linux操作系统的工具。在日常使用,备份和还原是非常重要的操作,可以帮助我们保护数据并快速恢
    的头像 发表于 11-23 10:04 2548次阅读