「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战」
在Linux环境中使用POSIX Thread
API可以很方便的写出多线程程序,本系列将对其API进行介绍, 本文为系列的第一篇文章, 主要介绍线程的基础操作。
在Linux中同一进程中的不同线程:
共享:
- 打开的文件
- 当前的工作目录
- 用户和组
- 信号和信号句柄
拥有自己的:
- 线程Id
errno
错误码 (使用thread-local实现)- 优先级
- 独立的线程栈
API
以下API均定义在头文件pthread.h
中, 使用GCC编译时需要链接到pthread
库上, 如下所示
1 | shell复制代码gcc ./test.c -l pthread |
pthread_create
pthread_create
用于创建线程, 如果线程创建成功该函数返回0, 创建失败返回错误码,创建失败的原因可能是:
EAGAIN
系统资源不足或者进程中的线程数量达到限制, 我们可以通过cat /proc/sys/kernel/threads-max
查看当前系统对于线程数量的限制EINVAL
attr
参数中有非法的设置EPERM
attr
参数中有不被允许的设置
该函数定义了以下参数:
thread
指向线程id的指针, 创建线程成功后会通过该指针将线程id保存到其中attr
用于设置线程相关的参数, 如果想使用默认参数传NULL即可。如: 设置线程的栈大小以及栈的地址(此场景常见于嵌入式设备需要限制线程栈空间大小的场景)start_routine
线程要执行的函数, 该函数的出入参均为一个无类型指针void*
arg
传给函数的参数
1 | c复制代码#include <pthread.h> |
pthread_self
pthread_self
用于获取当前线程的id.
1 | c复制代码 pthread_t pthread_self(void); |
pthread_join
调用pthread_join
会等待目标线程执行完成之后才退出, 并获取线程的执行结果, 下文中我们将会给出Demo, 返回是否执行成功.
1 | c复制代码int pthread_join(pthread_t thread, void **retval); |
pthread_exit
终止当前线程的运行(调用此方法的线程), 并设置线程的返回值, 如果有其他线程正在阻塞等待(调用pthread_join
)此线程返回它将接收到这一返回值。
1 | c复制代码void pthread_exit(void *retval); |
pthread_detached
pthread_detached
用于分离一个线程, 调用此方法的线程在终止后资源会被回收掉,并且不可等待(即其他线程不可调用pthread_join
等待此线程)
1 | c复制代码int pthread_detach(pthread_t thread); |
Demo
创建线程并传递参数
以下Demo展示了如何创建一个线程, 并传入参数以及取得该线程的返回值并进行打印。
1 | c复制代码#include <stdio.h> |
输出如下所示:
限制线程栈空间大小
上文中提到在创建线程时,我们可以通过pthread_attr_t
结构体设置一些参数来改变线程的一些行为。 在一些特殊场景下这个功能是非常实用的, 比如:
- 如果程序运行在嵌入式设备(内存受限), 为了节约内存我们可以通过
pthread_attr_t
来调小线程栈的大小以节约内存 - 在执行一些比较复杂运算的情况下,我们也可通过此参数来调大线程的栈内存以获取更多的栈空间
操作系统的默认线程栈大小我们可以通过ulimit -s
进行查看, 效果如下
如一下Demo所示, 我们通过pthread_attr_init
来初始化pthread_attr_t
结构体, 之后调用pthread_attr_set_stacksize
来设置线程栈的大小。
注意设置线程栈大小的时候, 如果设置的栈大小小于PTHREAD_STACK_MIN
时会返回非法参数的错误, 对于部分系统如果栈大小不是系统的页大小的倍数,也会引发错误。
如以下Demo所示, 我们使用THREAD_STACK_SIZE
来表示分配给线程的栈空间大小, ALLOC_SIZE
来表示线程的要执行的方法会申请的栈空间大小.
1 | c复制代码#include <stdlib.h> |
测试用例1, THREAD_STACK_SIZE = ALLOC_SIZE = 4096 * 6
, 输出如下所示:
系统提示Segmentation fault
, 原因是栈空间不足.
测试用例2, THREAD_STACK_SIZE = 4096 * 6, ALLOC_SIZE = 4096 * 4
, 输出如下所示:
测试用例3 THREAD_STACK_SIZE = 4096 * 1, ALLOC_SIZE = 1024
输出如下所示
提示参数错误, 原因时分配给线程的栈空间小于PTHREAD_STACK_MIN
本文转载自: 掘金