Linux(线程基础)学习笔记

线程(thread)

  1. 为什么需要引入线程?
    多进程的频繁切换,切换进程上下文。每次上下文切换都要做这些事,还是很耗资源的。
    想用一种机制能”减少进程切换带来的资源消耗“,所以很多操作系统中都引入了轻量级的进程的概念。
    也称之为线程。
  2. 什么是线程?
    线程(thread),被称为轻量级进程(Lightweight Process Lwp), “是程序执行调度的最小单位”。
    线程,是在进程中活动的对象。传统的系统中,一个进程只包含有一个线程。但在现代操作系统中,允许一个进程里面可以
    同时运行多个线程,这类程序就被称为多线程程序。一个进程内的各个线程之间共享程序的内存空间以及其他的资源(如打开的文件和信号等)。
    Linux实现线程的机制非常特别,从内核角度来说并没有线程的概念,Linux将线程仅仅视作一个
    与其他进程共享某些资源的特殊进程。所以Linux并没有特别的数据结构来描述线程,依然沿用
    task_struct结构来描述线程。
  3. 查看线程
    1)ps 命令,-L参数显示进程,并尽量显示其LWP(线程ID)和NLWP(线程的个数)。
    ps -eLF | grep ^syslog
    UID PID PPID LWP C NLWP STIME TTY TIME CMD
    syslog 599 1 599 0 4 Jun20 ? 00:00:02 rsyslogd -c5 主线程
    syslog 599 1 602 0 4 Jun20 ? 00:00:00 rsyslogd -c5
    syslog 599 1 612 0 4 Jun20 ? 00:00:00 rsyslogd -c5
    syslog 599 1 613 0 4 Jun20 ? 00:00:00 rsyslogd -c5

2)pstree命令, 查看进程和线程的树形结构关系
pstree -p | grep syslog
|-rsyslogd(599)-±{rsyslogd}(602)
| |-{rsyslogd}(612)
| `-{rsyslogd}(613)

  1. 线程库的历史
    New POSIX Thread Library (NPTL)
    (1)是早期Linux Threads的改进
    早期Linux线程的实现机制,完全在用户空间模拟对线程的支持。不幸的是,这种方法有一些缺点,尤其
    是在信号处理、调度和进程间同步原语方面都存在问题。另外,这个线程模型也不符合 POSIX 的要求。
    所以要改进 LinuxThreads,非常明显我们需要内核的支持,并且需要重写线程库。
    有两个相互竞争的项目开始来满足这些要求。IBM 的开发人员的团队开展了 NGPT(Next-Generation POSIX Threads)
    项目。Red Hat 的一些开发人员开展了 NPTL (Native POSIX Thread Library)项目。NGPT 在 2003 年中期被放弃了。
    最终NPTL,成功克服了LinuxThread的缺点。与 LinuxThreads 相比,它在性能和稳定性方面都提供了重大的改进。
    从Linux内核2.6开始它被纳入内核。目前它完全被结合入GNU C 库。
    (2)采用1:1的线程模型
    意思是说当你用pthread_create()创建一个线程后,在内核里就相应创建一个调度实体,也就是
    task_struct结构。
    (3)显著的提高了运行效率
    性能上举个例子:在同样的硬件条件下,在32位机下,NPTL启动100000个线程只用了2秒,而相比
    不利用NPTL的则花费了15s~。
    (4)信号处理效率更高

  2. 线程的访问权限
    (1)一个进程中的多个线程共享以下资源
    可执行的指令(text)
    静态数据(全局变量和静态变量)
    堆区
    进程中打开的文件描述符
    信号处理函数
    当前工作目录
    用户ID
    用户组ID
    (2)每个线程私有的资源如下
    线程ID (TID)
    PC(程序计数器)和相关寄存器
    堆栈(函数栈)
    局部变量
    返回地址
    错误号 (errno)
    信号掩码和优先级
    执行状态和属性

  3. 线程的API
    【1】pthread_create 创建线程
    #include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
函数功能:
在当前进程中创建新的线程
函数参数:
[1] thread 保存线程的ID
[2] attr 线程的属性(NULL 使用默认属性)
[3] start_routine : 线程执行函数
[4] arg : 用于给线程执行函数传参
返回值:
成功 返回 0
失败 返回 error number
注意:
1)编译时需要链接库 -lpthread
2)pthread_create 仅仅只是创建线程,至于线程何时运行取决于操作系统的调度。
3)主线终止表示整个进程终止,因此当主线程终止时,该进程内还有其他运行的线程也会随着主线的终止而终止。
问题:
标准线程创建接口只留了 一个参数传递。如果想给线程函数传递多个参数,该怎么解决呢? 结构体
【2】pthread_exit 终止线程
#include <pthread.h>

void pthread_exit(void *retval);
函数功能:
终止当前线程
函数参数:
retval : 线程函数的返回值(线程的退出状态),同一进程内的其他线程可以调用pthread_join去回收这个值

注意:
retval 不能是局部变量地址
可以返回的地址
全局变量
静态变量
堆区
代码段

【3】pthread_join 等待线程终止,并回收线程退出状态
#include <pthread.h>

int pthread_join(pthread_t thread, void **retval);
函数功能:
等待线程终止,并回收线程退出状态
函数参数:
[1] thread : 指定线程ID
[2] retval :
!NULL 用于保存目标线程的退出状态
NULL 只等待线程终止,不保存相乘退出状态
返回值:
成功 返回 0
失败 返回 error number

【4】pthread_cancel 取消线程
#include <pthread.h>

int pthread_cancel(pthread_t thread);
函数功能:
请求取消一个线程
函数参数:
[1] thread : 指定线程ID
函数返回值:
成功 返回 0
失败 返回 error number
注意:
1)如果一个线程被取消,那pthread_join接受的线程返回值为PTHREAD_CANCELED(#define PTHREAD_CANCELED ((void *) -1));
2)pthread_cancel并不等待线程终止,仅提出请求,线程可以选择忽略取消或控制如何被取消。

#include <pthread.h>

int pthread_setcancelstate(int state, int *oldstate);
函数功能:
设置线程是否接收取消请求
函数参数:
[1] state : 设置是否接收请求
PTHREAD_CANCEL_ENABLE 接收请求
PTHREAD_CANCEL_DISABLE 拒绝请求
[2] oldstate : 用于保存原先的设置
返回值:
成功 返回 0
失败 返回 error number

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值