2026/1/7 5:46:38
网站建设
项目流程
文章目录 线程标准 POSIX标准 POSIX线程(Pthreads) 线程属性(POSIX.1标准) Linux下线程实现演变 LinuxThreads NPTL (Native POSIX Threads Library) 确定线程实现的方式 Pthreads函数特点 线程标准 POSIX标准 一套接口规范,定义了操作系统(尤其是类Unix系统)应该提供哪些功能、以及如何调用这些功能 核心目的:可移植性。在遵循POSIX的不同系统(如Linux, BSD, macOS, VxWorks, QNX等)上都能编译运行,无需大量修改 嵌入式Linux中的意义:系统调用(如read, write, fork)、文件操作、进程线程API,其行为规范大都源于POSIX POSIX线程(Pthreads) POSIX标准中定义的线程编程接口Pthreads,是一组C语言函数(以pthread_开头)、数据类型(如pthread_t)和常量 核心思想:在单个进程内,创建多个并发执行流,它们共享进程的大部分资源,但各自拥有独立的执行上下文(如栈、寄存器) 线程属性(POSIX.1标准) 类别 具体属性/资源 说明 嵌入式开发中的意义 共享属性 (进程级)全局内存 (数据段、堆段) 线程间通信最直接的渠道。全局变量、malloc 分配的内存所有线程可见 需要同步机制(互斥锁)保护 ,否则会导致数据竞争文件描述符 一个线程打开的文件,其他线程可直接读写 需注意文件偏移量的共享,以及close的时机 信号处置方式 信号处理函数(signal /sigaction设置)被所有线程继承 多线程下信号处理复杂,通常建议用专门的信号处理线程 进程ID(PID)、用户ID等 整个进程只有一个身份 权限管理以进程为单位 独有属性 (线程级)线程ID pthread_t类型,系统内唯一标识一个线程。用于pthread_join,pthread_cancel等操作。 独立的栈 用于存放自动变量(局部变量)、函数调用链 栈大小有限 (默认几MB),嵌入式开发需注意深度递归可能导致的栈溢出errno变量每个线程有自己的errno ,避免一个线程的错误影响另一个 这是Pthreads对传统errno 的重要改进 调度策略与优先级 每个线程可独立设置 嵌入式实时系统中至关重要 ,用于控制关键线程的响应性
Linux下线程实现演变 LinuxThreads 是原始的 Pthreads 实现,从 glibc 2.4 开始,不再支持此实现 LinuxThreads 线程被实现为共享比平常更多的信息的进程 偏离 POSIX.1 规范的实现:LinuxThreads 线程(包括管理器线程)使用 ps() 显示为单独的进程 对 getpid() 的调用在每个线程中返回不同的值 在主线程以外的线程中调用 getppid() 会返回管理器线程的进程 ID 当一个线程使用 fork() 创建新的子进程时, 只允许创建子线程的线程在其上wait() 进程与调用 execve() 的线程具有相同的 PID 线程不共享用户 ID 和组 ID 线程不共享公共会话 ID 和进程组 ID … NPTL (Native POSIX Threads Library) 现代 Pthreads 实现与 LinuxThreads 相比,NPTL 更符合 POSIX.1 规范的要求,并且在创建大量线程时具有更好的性能 NPTL 从 glibc 2.3.2 开始提供,并且需要 Linux 2.6 内核中存在的功能 使用 NPTL 时,进程中的所有线程都放置在同一个线程组中 线程组的所有成员共享同一个 PID … 任何主流嵌入式Linux发行版(如Buildroot, Yocto, OpenWrt等构建的),默认都是NPTL
可以认为线程就是POSIX标准的实现
确定线程实现的方式 getconf GNU_LIBPTHREAD_VERSION$( ldd /bin/ls| grep libc.so| awk '{print $3}' ) | egrep -i 'threads|nptl' Pthreads函数特点 关于返回值 返回值惯例:Pthreads与大多数Linux系统调用的重要区别 成功:返回 0。 失败:返回 正的错误号(如EAGAIN, EINVAL),返回的错误号与errno中返回的错误号具有相同的含义 但是不设置errno:错误号直接通过返回值给出,所以不能用perror()直接输出错误,需要用strerror()转换 // 错误示例:perror(“pthread_create”); // 这行不通! // 正确做法: int ret= pthread_create ( & tid, NULL , func, NULL ) ; if ( ret!= 0 ) { fprintf ( stderr , “pthread_create error: % s\n”, strerror ( ret) ) ; } 关于EINTR错误 EINTR表示系统调用被信号中断 对于每个可能返回错误的pthreads函数,POSIX.1-2001指定该函数永远不会因错误EINTR而失败 但普通的系统调用(如read, sleep, write)可能会被中断并返回EINTR 对可能阻塞的系统调用,在循环中处理EINTR是健壮性编程的常见做法 while ( ( n= read ( fd, buf, size) ) == - 1 && errno== EINTR) ; // 什么也不做,只是重启read if ( n== - 1 ) // 处理其他错误 perror ( “read”) ;