前言
为了看懂Tinyhttpd项目, 我先是学了Linux下的Socket编程, 算是入门了,
基本的函数, 结构体能用一用了. 第二步当然就是学习多线程编程.
发展背景
- LinuxThreads:
- Linux 2.6之前所使用的, 实际上这时候并没有真的线程的概念, 在Linux内核看来所有的”线程”都是进程, 通过轻量级进程(LWP)模拟线程, 所有的线程操作都是内核外的函数完成的.
- 在LinuxThreads中,专门为每一个进程构造了一个管理线程,负责处理线程相关的管理工作。当进程第一次调用 pthread_create()创建一个线程的时候就会创建并启动管理线程。然后管理线程再来创建用户请求的线程。也就是说,用户在调用 pthread_create后,先是创建了管理线程,再由管理线程创建了用户的线程。
- LinuxThreads模型对于POSIX标准提出的要求几乎都不满足, 但是满足了最重要的一条: “当”进程”收到一个致命信号(比如由于段错误收到SIGSEGV信号), 对应的这一组task_struct将全部退出”.
- LinuxThreads线程毕竟是通过轻量级进程模拟出来的, 存在大量问题, 众所周知, 模拟题可是相当费劲的.
- NPTL:
- 到了Linux 2.6(2003年发布)之后, 有了新的pthread线程库–NPTL, 由红帽子公司牵头研发, 通过大量开发者的努力, 算是成功了
- 在linux 2.6中, 内核有了线程组的概念, task_struct结构中增加了一个tgid(thread group id)字段.
- 虽然依然是一个LWP的实现机制, 但是已经比较符合POSIX的标准了, 一直
- NGPT:
- IBM投资开发的项目, 早就失败了.
多线程编译支持
按照POSIX 1003.1c 标准编写的程序与Linuxthread 库相链接即可支持Linux平台上的多线程,在程序中需包含头文件pthread. h,在编译链接时使用命令:
1 | gcc -D -REENTRANT -lpthread xxx. c |
其中-REENTRANT宏使得相关库函数(如stdio.h、errno.h中函数) 是可重入的、线程安全的(thread-safe),-lpthread则意味着链接库目录下的libpthread.a或libpthread.so文件。
在一个多线程程序里,默认情况下,只有一个errno变量供所有的线程共享。在一个线程准备获取刚才的错误代码时,该变量很容易被另一个线程中的函数调用所改变。类似的问题还存在于fputs之类的函数中,这些函数通常用一个单独的全局性区域来缓存输出数据。
为解决这个问题,需要使用可重入的例程。可重入代码可以被多次调用而仍然工作正常。编写的多线程程序,通过定义宏_REENTRANT来告诉编译器我们需要可重入功能,这个宏的定义必须出现于程序中的任何#include语句之前。
- 它会对部分函数重新定义它们的可安全重入的版本,这些函数名字一般不会发生改变,只是会在函数名后面添加_r字符串,如函数名gethostbyname变成gethostbyname_r。
- stdio.h中原来以宏的形式实现的一些函数将变成可安全重入函数。
- 在error.h中定义的变量error现在将成为一个函数调用,它能够以一种安全的多线程方式来获取真正的errno的值。