线程概念
在Linux下使用pcb描述实现了程序调度,并且这些pcb共用同一个地址空间,相较于传统的pcb更加轻量化一点,因此也把Linux下的pcb称之为轻量级进程。
进程是系统资源分配的基本单位
线程是cpu调度的基本单位
线程间的独有与共享
独有: 栈,寄存器,信号屏蔽字,errno,标识符
**共享:**虚拟地址空间(代码段,数据段),文件描述符表
,信号处理方式,工作路径,用户ID ,组ID
多进程/多线程进行多任务处理:
多线程:
线程间通信更加方便灵活(全局变量,函数传参)而且还有进程间通信的那些方式都可以。
线程的创建/销毁的成本更低。
线程间的调度成本更低。
异常和某些系统调用是针对的是整个进程
多进程:
因为具有独立性,因此更加的稳定,健壮
例如:对主功能程序安全性稳定性要求更高的最好使用多进程,剩下的多线程。
共同优点:
CPU密集型程序/IO密集型程序 : 并行压缩cpu处理/IO等待时间。
线程控制
线程控制:线程创建/线程终止/线程等待/线程分离
线程控制的接口都是库函数(操作系统并没有向用户提供创建一个轻量级进程的接口,因此大佬们才封装了一套线程控制接口)
线程创建:
int pthread_create(pthread_t *tid, pthread_attr attr,void * (thread_routine)(voidarg),void * arg );
tid 用于获取线程id,通过这个id可以找到线程的描述信息,进而访问pcb(轻量级进程完成调度)
线程地址空间的首地址,进而可以找到线程的描述信息。
attr: 线程属性,通常置NULL,
thread_routine :线程入口函数,创建一个线程就是为了运行这个函数,函数运行完毕后,则线程退出。
arg:通过线程入口函数,传递给线程的参数。
返回值:成功返回0,失败返回一个非0值。-error
ps -efL 选项的功能是查看轻量级进程信息。
pcb -> pid 轻量级进程ID
pcb -> tgid 线程组ID --进程ID 就是外面命令所能看到的进程ID,而这个ID的值等于主线程的pcb -》 pid
#include<unistd.h>
#include<pthread.h>
#include<error.h>
void * thread_start(void *arg){
while(1){
printf("主线程传递了一个参数:%s\n",(char*)arg);
sleep(1);
}
return NULL;
}
int main(){
pthread_t tid;
char buf[]="今天真开心~\n";
int ret=pthread_create(&tid,NULL,thread_start,(void*)buf); //创建一个线程 。
if(ret!=0){
printf("thread create error:%d\n",ret);
return -1;
}
while(1){
printf("i am main thread\n");
sleep(1);
}
return 0;
}
运行结果
线程终止
1.普通线程入口函数中的return(main 函数中的return退出的是进程)
2. void pthread_exit(void * retval)退出一个线程,谁调用,谁退出。retval - 线程返回值。
3. int pthread_cancel(pthread_t tid) 退出指定的线程,
4. pthread_t pthread_self(void) 获取当前调用的线程id
5
注意 线程退出,与不会完成释放资源,需要被其他线程等待
取消自己是一种违规操作。
主线程退出,其他线程正常退出,这不是主流做法
主线程退出,并不影响整个进程的运行,只有所有的线程退出,进程才会退出。
线程分离
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<error.h>
void * thread_start(void *arg){
// pthread_detach(pthread_self());
char buf[1024]="nihao\n";
sleep(3);
pthread_exit(buf);
while(1){
printf("主线程传递了一个参数:%s\n",(char*)arg);
sleep(1);
}
return NULL;
}
int main(){
pthread_t tid;
char buf[]="今天真开心~\n";
int ret=pthread_create(&tid,NULL,thread_start,(void*)buf);
if(ret!=0){
printf("thread create error:%d\n",ret);
return -1;
}
void *retval=NULL;
pthread_join(tid,&retval);
printf("retval:%s\n",retval);
while(1){
printf("i am main thread,child tid:%p/\n",tid);
sleep(1);
}
return 0;
}