金华市网站建设_网站建设公司_PHP_seo优化
2026/1/7 5:46:38 网站建设 项目流程

文章目录

  • 线程标准
    • POSIX标准
    • POSIX线程(Pthreads)
    • 线程属性(POSIX.1标准)
  • Linux下线程实现演变
    • LinuxThreads
    • NPTL (Native POSIX Threads Library)
    • 确定线程实现的方式
  • Pthreads函数特点
    • 关于返回值
    • 关于EINTR错误

线程标准

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等整个进程只有一个身份权限管理以进程为单位
独有属性(线程级)线程IDpthread_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命令
getconf GNU_LIBPTHREAD_VERSION
  • 对于较旧的 glibc 版本:
$(ldd /bin/ls|greplibc.so|awk'{print $3}')|egrep-i'threads|nptl'

Pthreads函数特点

关于返回值

  • 返回值惯例:Pthreads与大多数Linux系统调用的重要区别
  • 成功:返回 0。
  • 失败:返回 正的错误号(如EAGAIN, EINVAL),返回的错误号与errno中返回的错误号具有相同的含义
  • 但是不设置errno:错误号直接通过返回值给出,所以不能用perror()直接输出错误,需要用strerror()转换
// 错误示例:perror(“pthread_create”); // 这行不通!// 正确做法:intret=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而失败
    • 即Pthreads函数本身不会被信号中断而失败
  • 但普通的系统调用(如read, sleep, write)可能会被中断并返回EINTR
  • 对可能阻塞的系统调用,在循环中处理EINTR是健壮性编程的常见做法
while((n=read(fd,buf,size))==-1&&errno==EINTR);// 什么也不做,只是重启readif(n==-1)// 处理其他错误perror(“read”);

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询