【Linux C | 多线程编程】线程的创建、线程ID、线程属性

这篇具有很好参考价值的文章主要介绍了【Linux C | 多线程编程】线程的创建、线程ID、线程属性。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
⏰发布时间⏰:2024-03-22 09:05:41

本文未经允许,不得转发!!!


【Linux C | 多线程编程】线程的创建、线程ID、线程属性,Linux系统编程🏆,linux,c语言,pthread_create,多线程,线程创建

🎄一、概述

Linux线程库接口包括线程的创建、 退出、 取消和分离, 以及连接已经终止的线程, 互斥量, 读写锁,线程的条件等待等。

POSIX 函数 函数功能描述
pthread_create 创建一个线程
pthread_exit 退出线程
pthread_self 获取线程ID
pthread_equal 检查两个线程ID是否相等
pthread_join 等待线程退出
pthread_detach 设置线程状态为分离状态
pthread_cancel 线程的取消
pthread_cleanup_push、pthread_cleanup_pop 线程退出,清理函数注册和执行

在代码里使用到上述接口函数时,使用gcc编程过程中需要加-pthread选项。

本文将介绍线程创建相关的一些知识,从pthread_create开始,然后依次介绍该函数第一个参数相关的线程ID,以及第二个函数相关的线程属性。


【Linux C | 多线程编程】线程的创建、线程ID、线程属性,Linux系统编程🏆,linux,c语言,pthread_create,多线程,线程创建

🎄二、线程的创建 pthread_create

程序开始启动的时候, 产生的进程只有一个线程, 我们称之为主线程或初始线程。 对于单线程的进程而言, 只存在主线程一个线程。 如果想在主线程之外, 再创建一个或多个线程, 就需要 pthread_create 函数。

pthread_create 函数原型:

#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
   					void *(*start_routine) (void *), void *arg);

Compile and link with -pthread.
  • 函数描述:函数 pthread_create 在调用过程中启动一个新线程。新线程通过调用 start_routine 参数指向的函数开始执行;arg参数作为 start_routine 的唯一参数传递。
  • 函数参数:
    • thread:传出参数,thread参数是 pthread_t 类型的指针,线程创建成功的话,会将分配的线程ID填入该指针指向的地址。线程的后续操作将使用该值作为线程的唯一标识。
    • attr:传入参数,第二个参数是 pthread_attr_t 类型,通过该参数可以定制线程的属性,比如可以指定新建线程栈的大小、调度策略等。 如果创建线程无特殊的要求, 该值也可以是NULL, 表示采用默认属性。
    • start_routine:传入参数,第三个参数是线程需要执行的函数。创建线程,是为了让线程执行一定的任务。线程创建成功之后,该线程就会执行start_routine函数,该函数之于线程,就如同 main 函数之于主线程。
    • arg:第四个参数是新建线程执行的 start_routine 函数的入参。新建线程如果想要正常工作,则可能需要入参,那么主线程在调用 pthread_create 的时候,就可以将入参的指针放入第四个参数以传递给新建线程。如果多个入参,可以使用结构体指针。
  • 函数返回值:如果成功,则 pthread_create 返回0;如果不成功,则 pthread_create 返回一个非0的错误码。pthread_create函数有点不同, 它会将errno作为返回值, 而不是一个负值。
    • EAGAIN:系统资源不够,或者创建线程的个数超过系统对一个进程中线程总数的限制
    • EINVAL:第二个参数attr值不合法
    • EPERM:没有合适的权限来设置调度策略或参数

通过上面的描述可以看到,pthread_create 是一个"四针"函数,也就是说它四个参数都是指针。下面是这个函数的简单使用示例:

// 02_pthread_create
// 编译:gcc 02_pthread_create.c -l pthread
#include <stdio.h>
#include <pthread.h>
void *func(void *arg)
{
	int *parg = arg;
	printf("this thread arg is %d \n", *parg);
	return NULL;
}
int main()
{
	int arg=10;
	pthread_t threadId;
	pthread_create(&threadId, NULL, func, &arg);
	while(1); // 让主线程不退出
	return 0;
}

【Linux C | 多线程编程】线程的创建、线程ID、线程属性,Linux系统编程🏆,linux,c语言,pthread_create,多线程,线程创建

🎄三、线程ID

通过 pthread_create 成功创建线程后,第一个参数会返回所创建线程的线程ID,这个线程ID不同于使用系统调用函数syscall(SYS_gettid)获得的线程ID。syscall(SYS_gettid)的ID是进程调度的范畴;而这里返回的线程ID是操作系统调度器用来标识线程的。

pthread_t到底是个什么样的数据结构呢? 因为POSIX标准并没有限制pthread_t的数据类型, 所以该类型取决于具体实现。 对于Linux目前使用的NPTL实现而言, pthread_t类型的线程ID, 本质就是一个进程地址空间上的一个地址。

typedef unsigned long int pthread_t;

pthread_t类型在Linux系统中定义在 <bits/pthreadtypes.h>头文件中,在Ubuntu可以使用命令vi /usr/include/bits/pthreadtypes.h 来查看,其完整定义如上,是unsigned long int类型的。

✨2.1 线程ID相关函数

关于线程ID,线程库NPTL提供了pthread_selfpthread_equal 两个函数来操作线程ID,它们的函数原型如下:

#include <pthread.h>
pthread_t pthread_self(void);
int pthread_equal(pthread_t t1, pthread_t t2);

Compile and link with -pthread.

pthread_self函数用于在线程指向函数中获取自身线程ID,这个函数不会调用失败,返回值就是线程ID;

pthread_equal函数用于比较两个线程ID是否相等,返回值是0的时候, 表示两个线程是同一个线程, 非零值则表示不是同一个线程。注意,比较线程ID只有在同一个进程中才有意义。

🌰举例子:

// 03_pthreadID.c
// gcc 03_pthreadID.c -l pthread
#include <stdio.h>
#include <pthread.h>
void *func1(void *arg)
{
	int *parg = arg;
	printf("this thread arg is %d, my threadID is %lx \n", *parg, (unsigned long)pthread_self());
	while(1); // 让线程不退出
}
void *func2(void *arg)
{
	pthread_t *parg = arg;
	printf("other threadId is %lx, my threadID is %lx \n", (unsigned long)*parg, (unsigned long)pthread_self());
	while(1); // 让线程不退出
}
int main()
{
	int arg=10;
	pthread_t threadId_1;
	pthread_create(&threadId_1, NULL, func1, &arg);
	pthread_t threadId_2;
	pthread_create(&threadId_2, NULL, func2, &threadId_1);
	if(0 == pthread_equal(threadId_1,threadId_1))
		printf("same threads\n");
	else
		printf("different threads\n");
	while(1); // 让主线程不退出
	return 0;
}

✨2.2 线程ID复用

在满足下列条件时, 线程ID就有可能会被复用:
1) 线程退出。
2) 线程组的其他线程对该线程执行了pthread_join, 或者线程退出前将分离状态设置为已分离。
3) 再次调用pthread_create创建线程。

看例子:

// 04_pthreadID_reuse.c
// gcc 04_pthreadID_reuse.c -l pthread
#include <stdio.h>
#include <pthread.h>
void *func(void *arg)
{
	int *parg = arg;
	printf("this thread arg is %d, my threadID is %lx \n", *parg, (unsigned long)pthread_self());
	return NULL;
}

int main()
{
	int arg=10;
	pthread_t threadId;
	pthread_create(&threadId, NULL, func, &arg);
	pthread_join(threadId,NULL); // 等待线程退出
	pthread_create(&threadId, NULL, func, &arg);

	while(1); // 让主线程不退出
	return 0;
}

运行结果,可以看到两次的线程ID是一样的:
【Linux C | 多线程编程】线程的创建、线程ID、线程属性,Linux系统编程🏆,linux,c语言,pthread_create,多线程,线程创建


【Linux C | 多线程编程】线程的创建、线程ID、线程属性,Linux系统编程🏆,linux,c语言,pthread_create,多线程,线程创建

🎄四、线程属性

pthread_create 的第二个参数是线程属性,先看看 pthread_attr_t 结构体的定义:

typedef struct
{
    int						detachstate;		//线程的分离状态
    int						schedpolicy;		//线程调度策略
    struct sched_param		schedparam;			//线程的调度参数
    int						inheritsched;		//线程的继承性
    int						scope;				//线程的作用域(竞争范围)
    size_t					guardsize;			//线程栈末尾的警戒缓冲区大小
    int						stackaddr_set;		//线程的栈设置
    void *                  stackaddr;			//线程栈的位置
    size_t					stacksize;			//线程栈的大小
}pthread_attr_t;


int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);   
功能:初始化/销毁线程的属性结构体
  • detachstate:分离状态

    • PTHREAD_CREATE_JOINABLE(默认值):线程执行完函数后不会自行释放资源;
    • PTHREAD_CANCEL_DEFERRED:线程执行完函数后,会自行终止并释放占用的资源。

    系统提供两个函数获取、设置分离状态。另外,pthread_detach函数也可以设置线程分离。

    int pthread_attr_getdetachstate(const pthread_attr_t * attr,int * detachstate);
    int pthread_attr_setdetachstate(pthread_attr_t *sttr,int detachstate);
    
  • schedpolicy:调度策略

    • SCHED_OTHER(默认值):普通策略(分时调度算法),按照优先级调度
    • SCHED_FIFO:先进先出。一个FIFO会持续执行,直到线程阻塞、结束、有更高优先级的线程就绪
    • SCHED_RR:轮转策略。给每个线程分配执行时间(时间片),当一个线程的时间片耗尽时,下一个线程执行

    其中,SCHED_OTHER 调度算法不支持为线程设置优先级,而另外两种调度算法支持。获取、设置的函数如下:

    int pthread_attr_getschedpolicy(const pthread_attr_t *, int * policy)
    int pthread_attr_setschedpolicy(pthread_attr_*, int policy)
    
  • schedparam:调度参数
    用于设置线程的优先级(默认值为 0),该属性仅当线程的 schedpolicy 属性为 SCHED_FIFO 或者 SCHED_RR 时才能发挥作用。

    int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);
    int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);
    struct sched_param param; // sched_param 只有一个字段 sched_priority 
    param.sched_priority = 99;
    
  • inheritsched:继承性

    • PTHREAD_INHERIT_SCHED 调度属性(schedpolicy、schedparam)继承自创建者的
    • PTHREAD_EXPLICIT_SCHED 使用attr创建的线程,从attr指定的值中获取其调度属性(schedpolicy、schedparam)。

    获取、设置函数如下:

    int pthread_attr_setinheritsched(pthread_attr_t *attr,int inheritsched);
    int pthread_attr_getinheritsched(pthread_attr_t *attr,int *inheritsched);
    
  • scope:作用域(竞争范围)

    • PTHREAD_SCOPE_SYSTEM:在系统范围内竞争资源
    • PTHREAD_SCOPE_PROCESS:在进程范围内竞争资源

    线程执行过程中,可以只和同进程内的其它线程争夺 CPU 资源,也可以和系统中所有的其它线程争夺 CPU 资源,scope 属性用于指定目标线程和哪些线程抢夺 CPU 资源。获取、设置函数如下:

    int pthread_attr_setscope(pthread_attr_t *attr, int scope);
    int pthread_attr_getscope(pthread_attr_t *attr, int *scope);
    
  • guardsize:线程栈末尾的警戒缓冲区大小
    每个线程中,栈内存的后面都紧挨着一块空闲的内存空间,我们通常称这块内存为警戒缓冲区,它的功能是:一旦我们使用的栈空间超出了额定值,警戒缓冲区可以确保线程不会因“栈溢出”立刻执行崩溃。

    int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
    int pthread_attr_getguardsize(pthread_attr_t *attr, size_t *guardsize);
    
  • stackaddr_set:线程的栈设置

    int pthread_attr_setstack(pthread_attr_t *attr,void *stackaddr, size_t stacksize);
    int pthread_attr_getstack(pthread_attr_t *attr,void **stackaddr, size_t *stacksize);
    
  • stackaddr:线程栈的位置

    int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr);
    int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stackaddr);
    
  • stacksize:线程栈的大小

    int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
    int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);
    

🌰举例子:

// 05_dispaly_attr.c  这是man手册的一个展示线程属性的例子,可以仔细研究以下
// gcc 05_dispaly_attr.c -l pthread
#define _GNU_SOURCE     /* To get pthread_getattr_np() declaration */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

#define handle_error_en(en, msg) \
	   do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

static void
display_pthread_attr(pthread_attr_t *attr, char *prefix)
{
   int s, i;
   size_t v;
   void *stkaddr;
   struct sched_param sp;

   s = pthread_attr_getdetachstate(attr, &i);
   if (s != 0)
	   handle_error_en(s, "pthread_attr_getdetachstate");
   printf("%sDetach state        = %s\n", prefix,
		   (i == PTHREAD_CREATE_DETACHED) ? "PTHREAD_CREATE_DETACHED" :
		   (i == PTHREAD_CREATE_JOINABLE) ? "PTHREAD_CREATE_JOINABLE" :
		   "???");

   s = pthread_attr_getscope(attr, &i);
   if (s != 0)
	   handle_error_en(s, "pthread_attr_getscope");
   printf("%sScope               = %s\n", prefix,
		   (i == PTHREAD_SCOPE_SYSTEM)  ? "PTHREAD_SCOPE_SYSTEM" :
		   (i == PTHREAD_SCOPE_PROCESS) ? "PTHREAD_SCOPE_PROCESS" :
		   "???");

   s = pthread_attr_getinheritsched(attr, &i);
   if (s != 0)
	   handle_error_en(s, "pthread_attr_getinheritsched");
   printf("%sInherit scheduler   = %s\n", prefix,
		   (i == PTHREAD_INHERIT_SCHED)  ? "PTHREAD_INHERIT_SCHED" :
		   (i == PTHREAD_EXPLICIT_SCHED) ? "PTHREAD_EXPLICIT_SCHED" :
		   "???");

   s = pthread_attr_getschedpolicy(attr, &i);
   if (s != 0)
	   handle_error_en(s, "pthread_attr_getschedpolicy");
   printf("%sScheduling policy   = %s\n", prefix,
		   (i == SCHED_OTHER) ? "SCHED_OTHER" :
		   (i == SCHED_FIFO)  ? "SCHED_FIFO" :
		   (i == SCHED_RR)    ? "SCHED_RR" :
		   "???");

   s = pthread_attr_getschedparam(attr, &sp);
   if (s != 0)
	   handle_error_en(s, "pthread_attr_getschedparam");
   printf("%sScheduling priority = %d\n", prefix, sp.sched_priority);

   s = pthread_attr_getguardsize(attr, &v);
   if (s != 0)
	   handle_error_en(s, "pthread_attr_getguardsize");
   printf("%sGuard size          = %ld bytes\n", prefix, v);

   s = pthread_attr_getstack(attr, &stkaddr, &v);
   if (s != 0)
	   handle_error_en(s, "pthread_attr_getstack");
   printf("%sStack address       = %p\n", prefix, stkaddr);
   printf("%sStack size          = 0x%lx bytes\n", prefix, v);
}

static void *
thread_start(void *arg)
{
   int s;
   pthread_attr_t gattr;

   /* pthread_getattr_np() is a non-standard GNU extension that
	  retrieves the attributes of the thread specified in its
	  first argument */

   s = pthread_getattr_np(pthread_self(), &gattr);
   if (s != 0)
	   handle_error_en(s, "pthread_getattr_np");

   printf("Thread attributes:\n");
   display_pthread_attr(&gattr, "\t");

   exit(EXIT_SUCCESS);         /* Terminate all threads */
}

int main(int argc, char *argv[])
{
   pthread_t thr;
   pthread_attr_t attr;
   pthread_attr_t *attrp;      /* NULL or &attr */
   int s;

   attrp = NULL;

   /* If a command-line argument was supplied, use it to set the
	  stack-size attribute and set a few other thread attributes,
	  and set attrp pointing to thread attributes object */

   if (argc > 1) {
	   int stack_size;
	   void *sp;

	   attrp = &attr;

	   s = pthread_attr_init(&attr);
	   if (s != 0)
		   handle_error_en(s, "pthread_attr_init");

	   s = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	   if (s != 0)
		   handle_error_en(s, "pthread_attr_setdetachstate");

	   s = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
	   if (s != 0)
		   handle_error_en(s, "pthread_attr_setinheritsched");

	   stack_size = strtoul(argv[1], NULL, 0);

	   s = posix_memalign(&sp, sysconf(_SC_PAGESIZE), stack_size);
	   if (s != 0)
		   handle_error_en(s, "posix_memalign");

	   printf("posix_memalign() allocated at %p\n", sp);

	   s = pthread_attr_setstack(&attr, sp, stack_size);
	   if (s != 0)
		   handle_error_en(s, "pthread_attr_setstack");
   }

   s = pthread_create(&thr, attrp, &thread_start, NULL);
   if (s != 0)
	   handle_error_en(s, "pthread_create");

   if (attrp != NULL) {
	   s = pthread_attr_destroy(attrp);
	   if (s != 0)
		   handle_error_en(s, "pthread_attr_destroy");
   }

   pause();    /* Terminates when other thread calls exit() */
}

运行结果,打印一些默认值:
【Linux C | 多线程编程】线程的创建、线程ID、线程属性,Linux系统编程🏆,linux,c语言,pthread_create,多线程,线程创建


【Linux C | 多线程编程】线程的创建、线程ID、线程属性,Linux系统编程🏆,linux,c语言,pthread_create,多线程,线程创建

🎄五、总结

本文介绍了线程创建相关的内容,包括pthread_create函数的详细介绍和使用例子,然后依次介绍该函数第一个参数相关的线程ID知识以及第二个参数相关的线程属性知识。读完完整地了解线程的创建。

补充:
进程的地址空间:
1、Linux系统中,/proc/sys/vm/legacy_va_layout文件的值会影响进程地址空间的布局。默认值是0,表示mmap区域的基地址在栈的下面, mmap区域从高地址向低地址扩展;若值为1, 那么mmap的基地址mmap_base变小(约在128T的三分之一处),mmap区域从低地址向高地址扩展。

2、使用命令 pmap PIDcat /proc/PID/maps 可以查看进程的地址空间:
【Linux C | 多线程编程】线程的创建、线程ID、线程属性,Linux系统编程🏆,linux,c语言,pthread_create,多线程,线程创建

【Linux C | 多线程编程】线程的创建、线程ID、线程属性,Linux系统编程🏆,linux,c语言,pthread_create,多线程,线程创建
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

参考资料:
https://blog.csdn.net/qq_41854911/article/details/118719001
《Linux环境编程:从应用到内核》文章来源地址https://www.toymoban.com/news/detail-843519.html

到了这里,关于【Linux C | 多线程编程】线程的创建、线程ID、线程属性的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux】C语言中多线程的创建、退出、回收、分离

    线程是轻量级的进程(LWP:light weight process),在 Linux 环境下线程的本质仍是进程。在计算机上运行的程序是一组指令及指令参数的组合,指令按照既定的逻辑控制计算机运行。操作系统会以进程为单位,分配系统资源,可以这样理解, 进程是资源分配的最小单位,线程是操

    2024年02月09日
    浏览(33)
  • Linux系统编程5(线程概念详解)

    线程同进程一样都是OS中非常重要的部分,线程的应用场景非常的广泛,试想我们使用的视频软件,在网络不是很好的情况下,通常会采取下载的方式,现在你很想立即观看,又想下载,于是你点击了下载并且在线观看。学过进程的你会不会想,视频软件运行后在OS内形成一个

    2024年02月10日
    浏览(30)
  • 【Linux】详解线程控制 -- 线程用法 | 线程等待 | 线程ID及地址空间布局

    (关于 用户 → 库 → OS :具体可看下面线程地址空间布局) 这个 clone 我们不用,这是OS提供给第三方库所用的接口 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“ pthread_ ”开头的,要使用这些函数库,要通过引入头文 pthread.h ,链接这些线程函数库时要

    2024年02月15日
    浏览(43)
  • 【关于Linux中----多线程(二)线程终止、分离与封装、线程库以及线程id的解析】

    上一篇文章中已经讲述了两种终止线程的方式,这里介绍第三种方式: 这里对上篇文章中的代码稍作修改: 运行结果如下: 根据记过可知,线程如果是被取消的,它的退出码是-1. 这里需要注意, 线程可以被取消的前提是该线程已经运行起来了 。 上一篇文章中以及这篇文章

    2023年04月08日
    浏览(33)
  • Linux系统下C语言的编程技巧

    Linux系统能够为人们提供更加安全实用的效果,保证计算机系统能够稳定的运行。利用Linux系统下首先要进行C语言的编程,掌握编程的技巧能够更好的发挥计算机的作用。如何掌握Linux系统下计算机C语言的编程技巧是计算机发展的关键要素。本文对Linux系统下计算机C语言的编程技

    2024年02月07日
    浏览(31)
  • Linux系统编程,使用C语言实现简单的FTP(服务器/客户端)

    前言 跟着上官社长 陈哥花了一个月的时间终于把Linux系统编程学的差不多了,这一个月真的是头疼啊,各种bug,调的真心心累,不过好在问题都解决掉了,在此也感谢一下答疑老师,给我提供了很多的思路,本文章是对前段时间学习Linux,做一个小小的总结,才疏学浅,只学

    2024年02月12日
    浏览(51)
  • linux_设置线程属性-pthread_attr_t结构体-设置线程分离态-修改线程栈的大小-NPTL

    接上一篇:linux_线程分离pthread_detach函数-线程取消pthread_cancel函数-线程相等pthread_equal函数   本次来分享linux线程的属性设置,线程属性主要是一个结构体 pthread_attr_t ,这个结构体中的成员就是线程的属性了,需要通过一系列的函数来修改,话不多说,上菜: 此博主在CSD

    2024年02月02日
    浏览(30)
  • 【linux 多线程并发】线程属性设置与查看,绑定CPU,线程分离与可连接,避够多线程下的内存泄漏

    ​ 专栏内容 : 参天引擎内核架构 本专栏一起来聊聊参天引擎内核架构,以及如何实现多机的数据库节点的多读多写,与传统主备,MPP的区别,技术难点的分析,数据元数据同步,多主节点的情况下对故障容灾的支持。 手写数据库toadb 本专栏主要介绍如何从零开发,开发的

    2024年02月03日
    浏览(35)
  • Linux 【C编程】 引入线程,线程相关函数

    代码演示: 效果如下: 需要注意到的一点是: 使用了pthread库,因此编译时需要链接 -lpthread 在Linux系统中,线程是一种轻量级的执行单元,与进程共享相同的地址空间。 一个进程中可以有多个线程 线程是参与内核调度的最小单元 并发执行: 线程使得程序可以同时执行多个

    2024年01月20日
    浏览(25)
  • [Linux]多线程编程

    Linux操作系统下,并没有真正意义上的线程,而是由进程中的轻量级进程(LWP)模拟的线程,因此Linux操作系统中只会提供进程操作的系统接口。但是为了用户操作方便,Linux操作系统提供了用户级的原生线程库,原生线程库将系统接口进行封装,让用户可以像使用操作真正的

    2024年02月08日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包