1.进程与线程联系 线程:线程也是一个执行流,线程在进程内部运行 1.对一个进程来讲,每个进程都有个PCB,且每个进程均有自己的独立地址空间,进程的地址空间是00-FF,4G(32位下),再从地址空间由MMU和页表转化为物理内存--> 环境变量区 栈区 堆区 静态区 进程强调资源独占,进程间不受影响(fork的子进程和父进程代码共享数据独立;vfork子进程和父进程共享地址空间)。而线程强调资源共享 2. 线程是操作系统调度的基本单位,进程是承担分配系统资源的基本单位。 3.进程能共享地址空间,让他们使用这份地址空间的一部分资源,此时这两个进程就是在同一份地址空间下的两个线程 4.进程刚创建时只有一个执行流,一个PCB,地址空间也分配好,线程就不用再分配,直接使用进程分配好的资源。 linux下,一个进程就是一个独占资源的线程,即在这个地址空间仅有一个执行流,linux下的进程均为轻量级进程(进程可以理解为是线程,可以理解为linux下均为线程),进程和线程均叫做pcb (windows下,TCB(线程控制块))
2.线程独有部分 1.由于线程是调度的基本单位,线程必须要有自己独立的硬件上下文信息,方便上下文的切换 2.栈空间。每个线程都会执行各个分支,会出现各种临时变量(栈),所以每个线程都有自己的私有栈,这样线程之间的临时变量就不会相互影响 3.信号屏蔽字私有 4.调度优先级 5.线程id 6.errno变量
3.线程共享部分 1.文件描述符表 2.每种信号的处理方式 3.当前工作目录 4.用户id和组id
二、线程控制 1、创建控制
返回值:成功返回0,失败返回错误号创建线程示例 *注意:打印出的线程号仅在这个函数有效*命令 ps -al可打印出当前所有线程
2.终止线程终止线程有三种方式:
- 从线程函数return,如果在主线程调用return相当调用exit,终止进程
- 线程调用pthread_exit(退出码)终止自己
- 线程可以调用pthread_cancel(id)终止同一进程的另一个线程。
②pthread_cancel函数
*注意:pthread_exit或者return返回的指针所指向的内存单元必须是全局或者用malloc分配的,不能再线程函数的栈上分配,因为线程的栈私有,且其他线程得到这个返回指针时线程函数已经退出。
3.线程等待 在pthread_exit函数的参数中retval是void*类型,其他线程可以调用pthread_join获得这个指针。pthread_join函数: 调用该函数的线程将挂起等待,知道id为thread的线程终止。
返回值:成功返回0,失败返回错误号1.如果thread线程通过return返回,value_ptr所指向的单元存放的是thread线程函数的返回值。2.如果thread线程被别的线程调用pthread_cancel异常终止,value_ptr所指向的单元存放常数PTHREAD_CANCELED。3.如果thread线程是自己调用pthread_exit终止,value_ptr所指向的单元存放传给pthread_exit的参数。线程等待
心得:1,线程的等待只有阻塞,进程等待有阻塞和非阻塞2.进程的退出码在0-255之间,线程的退出码可以在255以上不过最好和进程保持一致3.线程必须等待(内存泄漏),进程里也需要等待(僵尸进程)4.如果一个线程是被取消的,退出码为-1(定义为宏PTHREAD_CANCEL),如果是exit或return的退出码为自己设定的值三、线程分离 在任何一个时间点上,线程是可结合的或者可分离的,一个可结合的线程能够被其他线程收回其资源和杀死。在其他线程回收之前,它的存储资源时不释放的。相反,一个分离的线程是不能被其他线程回收或者杀死的,它的存储资源在它终止时自动释放 一般情况下,线程终止后,其终止状态一直保留到其他线程调用pthread_join获取它的状态为止。但是线程可以被设置为detach状态,这样线程一旦终止就立即回收它占用的所有资源,而不是保留终止状态。不能对一个已经detach的线程调用pthread_join,这样调用将返回EINVAL。 对一个尚未detach的线程调用pthread_join或pthread_detach都可以把线程置为detach状态。对一个线程不能同时调用两次pthread_join。同样,如果对一个线程调用了pthread_join也就不能调用pthread_join了
成功返回0,失败返回错误号注意:
- 默认情况下,线程被创建成可结合的。为了避免存储器泄漏,每个可结合的线程都需要显式的回收,即调用pthread_join或者pthread_detach
- 调用pthread_join后,如果线程没有运行结束,调用者会被堵塞。在子线程加入代码pthread_detach(pthread_self())或者父线程调用pthread_detach(thread_id)(非阻塞,可立即返回),这将子线程的状态设为分离,这样,该线程运行结束后会自动释放所有资源