线程基础(一)

线程的概念

每个用户进程有自己的虚拟地址空间。

系统为每个用户进程创建一个 task_struct 来描述该进程 struct task_struct。

task_struct 和地址空间映射表一起用来表示一个进程。

由于进程的虚拟地址空间是私有的,因此进程切换开销很大。

为了提高系统的性能,linux 引入轻量级进程,起名为线程。

在同一个进程中创建的线程共享该进程的地址空间。

Linux里同样用 task_struct 来描述一个线程。

总结:

  1. 通常线程指的是共享相同虚拟地址空间的多个任务。

  2. 使用多线程,大大提高了任务切换的效率。

  3. 每个进程中至少有一个线程,就是主线程,还可以产生多个线程。

  4. 共享4G内存空间,线程切换只需要虚拟CPU(寄存器)。

  5. 进程代表资源分配的最小单位 线程是最小的调度单位。


一个进程中的多个线程共享以下资源:

  1. 可执行的指令。

  2. 静态数据。

  3. 进程中打开的文件描述符。

  4. 信号处理函数。

  5. 当前工作目录。

  6. 用户ID。

  7. 用户组ID。


每个线程私有的资源如下:

  1. 线程ID(TID)。

  2. PC(程序计数器)和相关寄存器。

  3. 堆栈(局部变量、返回地址)。

  4. 错误号(errno)。

  5. 信号掩码和优先级。

  6. 执行状态和属性。


创建线程

#include <pthread.h>

 

pthread_t tid; //线程号

 

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

 
功能:创建线程

参数:
        thread: &tid  线程号的地址
        attr: NULL 线程函数默认的属性  
        start_routine: 线程函数的函数名  
        arg: 给线程函数传递的参数 NULL

返回值:
        成功:0
        失败:-1


回收线程资源

int pthread_join(pthread_t thread, void **retval);

 
功能:主线程等待子线程结束,然后回收资源
参数:
        thread: tid 
        retval: NULL   (接收子线程结束的返回值)
返回值:
        成功:0
        失败:-1

 

---------------------------------------------------------------------------------

 
int pthread_detach(pthread_t thread);

 
功能:主线程和子线程分离开来,系统自动回收资源(非阻塞)
参数:
        thread: tid
返回值:
        成功:0
        失败:-1  


结束当前子线程

void pthread_exit(void *retval);

 
功能:结束当前进程并返回值
参数:
        retval:void *

retval 是 void* 类型的指针,可以指向任何类型的数据,它指向的数据将作为线程退出时的返回值。如果线程不需要返回任何数据,将 retval 参数置为 NULL 即可。 

通过在主线程(main() 函数)调用 pthread_join() 函数,可以获取线程返回的 retval 数据。

#include <stdio.h>
#include <pthread.h>

// 线程要执行的函数,arg 用来接收线程传递过来的数据
void *ThreadFun(void *arg)
{
    // 终止线程的执行,将“abc”返回
    pthread_exit("abc"); //返回的字符串存储在常量区,并非当前线程的私有资源
    printf("*****************"); //此语句不会被线程执行
}

int main()
{
    int res;
    // 创建一个空指针
    void * thread_result;
    // 定义一个表示线程的变量
    pthread_t myThread;

    res = pthread_create(&myThread, NULL, ThreadFun, NULL);
    if (res != 0) {
        printf("线程创建失败");
        return 0;
    }

    // 等待 myThread 线程执行完成,并用 thread_result 指针接收该线程的返回值
    res = pthread_join(myThread, &thread_result);
    if (res != 0) {
        printf("等待线程失败");
    }
    
    // 打印子线程的返回值
    printf("%s", (char*)thread_result);
    return 0;
}

pthread_exit() 函数只会终止当前线程,不会影响其它线程的执行。此外,pthread_exit() 函数还会自动调用线程清理程序(本质是一个由 pthread_cleanup_push() 指定的自定义函数),而 return 不具备这个能力。 


关闭其他子线程

int pthread_cancel(pthread_t thread);

 

功能:结束其他子线程
参数:
        thread:thread

一个线程还可以向另一个线程发送“终止执行”的信号,这时就需要调用 pthread_cancel() 函数。

对于接收 Cancel 信号后结束执行的目标线程,等同于该线程自己执行如下语句:

pthread_exit(PTHREAD_CANCELED);

也就是说,当一个线程被强制终止执行时,它会返回 PTHREAD_CANCELED 这个宏。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值