进程:解耦稳定,内容之间是不相关的,通信不便利,理论上进程的软硬件的切换时间以及创建开销非常大。--------》资源共享线程实现
线程的问题:本质就是不解耦,一个出问题别的就很有可能出问题,同时资源的处理也会有些混乱
线程依赖于进程而存在,在同一个进程的不同的线程中是共享代码段和数据段和堆,线程的栈是不共享的(也就是局部变量的存储位置)。
相较于父子进程,线程分为主子进程。
进程会主动创建主线程,main函数是主线程的入口逻辑,主线程(必须是通过return死掉)终止时-------》进程会终止-------》所有的线程也就会终止。
就比如说以pthread_exit方式退出的主线程,这样的话子线程不会终止。
lwp中文含义是轻量级进程,只是一个线程的标识,并不是线程的id!!
可以通过ps -elLf来查看线程的情况
usleep()就可以睡微秒
相较于父子进程是通过返回值进行判断,线程创建以后是通过自己独立的一个函数来进行实现,理解主线程的入口函数是main函数,但是子线程的入口函数是自己额外定义的函数。
信号是发送给进程的,线程和信号一般是不相容的。
对于linux操作系统而言,每一个线程都有一个task_struct(主要就是栈的信息栈的地址,其他的重要信息都是存放在进程的struct),注意进程也会维护一个大的task_struct,如果说有两个线程,那么就会有三个struct
这个时候子线程中的语句会打印两次,这个地方可以这样理解,主要是理解子线程先将数据由用户态放到内核态中,然后删除用户态中的数据,然后再将数据从内核态刷新到屏幕上。出现这种情况是因为子线程将数据复制到内核区域中,还没有来得及删除数据的时候,子线程的时间片就终止了。主线程要终止的时候就会将缓冲区中的数据放到内核缓冲区中,这样的话刷到输出屏幕中的时候就会刷新两次。
线程相关的检错不要用error_check,由专门的检错函数,因为ERROR_CHECK是通过errorno来进行判断,但是可能出现这个问题就是errorno不知道是哪个线程出现的问题。线程是通过函数的返回值来进行错误信息判断。???????????
子线程可以拿到其他线程栈上的数据,并且也可以进行修改,只要是进程中的数据都可以访问到,但是一定注意一点就是子线程和主线程的栈是独有的,而不是用来共享的。
int num = 10;
pthread_create(&pt, NULL, func, (void*) num)
传递数据:一般可以在堆上进行数据的传递,但有时候数据比较少的时候可以将数值转化为指针来实现。这个地方容易出现问题,因为可能那个线程栈中的数据会丢失当线程死亡的时候。
有时可能想要在线程之间传递信息,这个时候不想让别的线程来修改本线程中的数据,所以说用一个数据来充当一个地址来进行传递。
pthread_join是一个线程等待当前进程中的另外一个线程退出,与主线程和子线程无区分,因为有参数来指明是哪一个线程。另外一个参数是一个返回值是一个二级指针,是指向void*这个返回值一级指针的。
void *p;在用&p来实现一个二级指针。不能直接用二级指针因为这个时候返回的不是指向堆上一块区域的指针,而是指向这个存储这个指针的一个指针。
有点像wait函数waitpid函数只是这个是父进程是必须要等到子进程的。
可以有多个线程进行pthread_join来捕获线程,但是只能有一个线程可以捕获到。
线程和进程一般不会让死亡,都是让睡觉,因为再次创建的开销也是比较大的。
主动退出和被动退出,主动退出就是自己退出例如return和exit,被动推出就是ctrl+c和其他一些中断。
exit在子函数中可以退出,但是return必须要在主逻辑中使用才可以返回。
pthread_exit()和return返回值对于pthread_join而言是一样的,都是可以被pthread接收到。
pthread_exit具有资源清理能力,但是return不具有这个能力。
进程的退出主要是被动退出借助于信号进行退出,线程不能借助于信号进行退出,因为信号不知道要给哪个线程,但是知道给哪个进程。
pthread_cancel(son_id);调用这个函数,这个线程会修改另外一个线程的退出位,但是可能不会进行检查所以说这个时候线程是取消不掉的。就像是说一个线程只是用来进行计算的。
线程只有在走到取消点函数的时候才会检测退出标记位。会引发阻塞的函数和IO操作都可以认为是取消点函数,read,sleep(2), printf()
这种情况下如果想要退出一个函数就使用手打取消点pthread_testcancle();这个函数就只是检查退出位有没有被修改。
pthread_cancle是没有返回值的,还没有执行到exit返回的一个值。
线程对于资源的管理就是比较困难的,因为被动退出可能不能将资源进行清理,因为会在取消点线程就退出了,不能将相应的打开文件关闭。可以通过资源清理栈来进行实现,最后会有两种实现的方式包括1.主动退出的话,需要借助于手动出栈进行资源的清理。也就是说如果return放在手动清理之前不会清理,exit特殊会清理了解
2.被动退出的话,程序会自动执行清理工作。pthread_cleanup_push, pthread_clean_pop
push和pop之间是一个大括号,如果在这中间定义的变量相当于局部变量
框架: