线程的基本概念

线程:

1>在一个程序里的一个执行路线叫做线程,线程是一个进程内部的控制序列

2>一个进程至少都有一个执行线程

线程和进程创建过程简单图示:


线程和进程:

1.进程:程序的一次执行过程
在Linux操作系统中,系统维护了一块PCB用来描述进程,从PCB中我们可以看出来:

进程标识;
进程的代码和数据(内存指针:进程中指针指向);
进程调度;
进程状态;
进程的上下文,进程的记账信息(统计进程在CPU上执行的时间等信息;多上行语句);
文件描述符表;
描述信号和进程之间的关系;

2.线程:

1.操作系统运算调度的基本单位;
2.线程被包含在进程中,是进程中实际运作单位;
3.一条线程是进程中的一个单一顺序的控制流;
4.一个进程可以并发多个线程,每条线程并行执行不同的任务;

进程:(资源的管理和分配)
1.资源所有权:内存(虚拟地址空间)、文件、IO设备、操作系统执行保护功能防止进程间发生不必要的资源相关冲突
2.调度/执行:沿着一个或多个程序的执行路径执行;具有执行状态和优先级,是被操作系统调度和分派的实体

进程(线程组/任务):是资源竞争(分配)的基本单位

线程(Linux -- 轻量级进程(LWP)):是程序执行的最小单位


一个进程内的全部进程共享同一个全局内存空间,这使得进程间很容易共享信息,但是这种容易性也带来可同步问题。一个进程内的线程不光共享全局变量,以下信息也是它们所共享的:

1.进程指令

2.同一地址空间,即Text Segment、Data Segment都是共享的,如果定义一个函数在各个线程中都可以调用,如果定义一个全局变量,在各个线程中都可以访问。

3.打开的文件(文件描述符表)

4.每种信号的处理方式

5.当前工作目录

6.用户id和组id

每个线程也有自己独立的信息:

1.线程ID

2.寄存器集合,包括程序计数器和栈指针

3.栈 (用于存放局部变量和返回地址)

4.errno

5.信号屏蔽字

6.调度优先级

线程的优点:

1>创建一个新线程的代价要比创建一个新进程小的多   1/5
2>与进程间的切换相比,线程之间的切换需要操作系统做的工作要少的多
3>线程占用的资源要比进程少很多
4>能充分利用多处理器的并行数量
5>在等待慢速的I/O操作结束的同时,程序可执行其他的计算机任务
6>计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现

7>I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作

线程缺点:

1>编码、调试难度提高

2>缺乏访问控制,一个线程崩溃,会导致整个程序都异常终止,一个线程中调用某些函数(signal/kill/exit)会影响整个进程

POSIX线程库:

与线程有关的函数构成了一个完整的系列,绝大多数的名字都是以“pthead_”开头的
连接着写函数库时要使用编译器命令的“_lpthread” 选项。

进程和线程的操作函数对比:


线程创建:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,

                          void *(*start_routine) (void *), void *arg);

thread :新线程的标识符

attr:用于设置线程属性,一般置NULL, sart_routine和arg参数分别指定新线程运行的函数及其参数。

返回值: 成功返回0,错误返回错误码。

线程退出:

1>线程只是从启动例程中返回,返回值是线程的退出码。

2>线程可以被同一进程中的其他线程取消(pthread_cancle())。

3>线程调用pthread_exit().

void pthread_exit(void *retval);

函数执行完之后不回到调用者,且退出函数不会失败。

线程等待:调用线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或被取消。

为什么要进行线程等待?

1.线程的入口函数有返回结果,有时候会用到这个结果;

2.这个结果在线程退出时一直在内存中保存,直到有其他线程来读取,才会释放 ;

3.否则会产生类似于僵尸进程的场景,创建新的线程不会复用刚才退出线程的地址空间;

int pthread_join(pthread_t thread, void **retval);      //retval一般置为NULL

返回值:成功返回0,失败返回错误码。

线程的取消:cancel后线程不会立即退出,而是等到取消点。----------   取消点:凡是系统调用的位置都是取消点

int pthread_cancel(pthread_t thread);

返回值:成功返回0,失败返回错误编号。

void pthread_testcancel(void); 人为设置取消点

获取线程ID:

 pthread_t pthread_self(void);

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/syscall.h>


void* func(void* arg)
{
//    while(1)
//    {
//        printf("this is func thread\n");
//       sleep(1);
//    }
    while(1)
    printf("this is thread one %X %d\n", pthread_self(), 
                                        syscall(SYS_gettid));
    sleep(2);
}

int main()
{
    pthread_t tid;

    int ret = pthread_create(&tid, NULL, func, NULL);
    if(0 != ret)
    {
        fprintf(stderr, "create : %s\n", strerror(errno));
        exit(0);
    }
//    while(1)
//    {
//        printf("this is main thread\n");    
//        sleep(1);
//    }
    pthread_join(tid, NULL);

}

gdb调试线程简单步骤:

1.gdp attach + 进程ID;
2.info thread;
3.thread i 切换线程
4.bt查看调用栈

5.* --当前线程


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值