在线程的概念一文中,有提到在Linux下的线程的实现是通过NPTL线程库实现的。即每一个用户态的线程对应于内核中的一个调度实体(一个PCB/一个内核级线程)。可以说,一个Linux下的线程包含两部分组成:一个用户级的线程,一个内核级的线程(PCB)。
之前有提到过,操作系统并不知道用户级线程的存在。而Linux中的线程又包含一个用户级的线程。所以该用户级线程的实现是通过用户级线程库POSIX来完成的。有关线程的一些函数实现也是封装在该用户级别的库中。因此:
(1)与线程有关的大多数函数都是以“pthread”打头的
(2)要使用这些函数,就要引入头文件“<pthread.h>”
(3)链接这些线程函数库时要加上“-pthread”选项,指定要链接的库名。可以通过以下方式来查找该库:
find /usr/lib -name libpthread.*
创建线程
int pthread_create(pthread_t* thread,const pthread_attr_t* attr,void*(*start_routine)(void*),void* arg);
参数:
thread:引用该函数创建的线程ID存放在thread指针指向的空间中,关于用户级线程id类型可以通过以下方式查找:
grep -ER "pthread_t" /usr/include
/usr/include/bits/pthreadtypes.h:typedef unsigned long int pthread_t;
结果显示,pthread_t类型是一个无符号长整型。 attr:设置线程的属性,一般设置为BULL(默认属性)
start_routine:是一函数指针,该函数的返回值和参数都是void*类型的。当新线程创建好后,就去执行该函数指针指向的函数
arg:上述start_routine函数指针指向的函数的参数
返回值:成功返回0,失败返回错误码
注意:
(1)传统的一些函数,成功返回0,失败返回-1,错误码赋给errno以指示错误。比如对于open函数,文件成功打开,返回值为0。打开失败,返回值为-1。我们一般会通过perror或strerror函数先显示错误信息,而perror函数就是通过errno的取值(错误码)来显示错误信息。strerror的参数也是errno(错误码)。
(2)大多数POSIX函数(包含pthreads类型)不会设置全局变量errno,而是将错误码以返回值的形式给出。
(3)pthreads函数也设置了线程内得errno变量,以支持其他使用errno的代码。但是建议通过返回值来判断错误码,因为读取返回值比读取errno的开销更小。因此,可以通过将返回值传参给strerror函数,来显示错误信息。
下面通过该函数来创建一个新线程:
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
//新线程创建成功后执行的函数
void* run(void* arg)
{
while(1)
{
printf("%s\n",(char*)arg);
sleep(1);