Linux系统分析之线程

来源:互联网 发布:js 杀破狼另一个版本 编辑:程序博客网 时间:2024/06/14 18:29

什么是线程

 

Linux线程是一类特殊的进程,拥有各自的task_struct,内核并没有特别的调度算法和数据结构来表征线程,而仅仅是作为一个普通的进程,只是和其他进程共享进程空间。也就是说,如果程序运行于多线程环境,编写程序时必须检查一下项目:

  • 是否使用了不可重入的系统函数,例如字符串分割函数::strtok();
  • 是否已经对全局变量或静态变量进行了加锁;
  • 第三方库是否支持多线程。

 

注:想要从核心获取线程id,应当使用current->pid。在核心里pid对进程而言是进程号,对于线程是线程号。同一进程的不同线程的pid是不同的,但同一进程的不同线程有统一的tgid,所以像getpid(),kill()等这种系统调用返回的都是tgid的值。

 

线程的调度

 

如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间片,再将时间片分配给各个线程执行,在一个时间片的线程代码运行时,其它线程处于挂起状态,这种方式称之为并发(Concurrent)

 

因为I/O操作速度远远慢于CPU处理速度,键鼠输入、硬盘读写、网络传输等速度远慢于内存读写速度,而内存速度又远慢于CPU缓存速度,所以有效的利用I/O操作间隙时的CPU,成为早期单核并发机制的来由。在并发环境下,CPU以”挂起->执行->挂起”的异步方式以很小的时间片分别运行各个线程,既让每个线程都得到合理的CPU资源,避免等待处理速度较慢的设备,又给用户以每个线程都在运行的错觉。在这种环境中,多线程程序真正改善的是系统的响应性能和程序的友好性。

 

内核线程

 

内核线程是独立运行在内核空间的标准进程,它和普通进程的区别是内核线程没有独立的地址空间,它的代码段和数据都在内核空间里,但可以被调度,被抢占。

 

内核线程可以创建新的内核线程。一般情况下,内核线程会将它在创建时得到的函数永远执行下去,这个函数通常由一个循环构成(内核线程0)。在需要的时候,这个内核线程被唤醒,和执行,在完成任务以后,它会自动休眠。

 

注:可以把内核想象成有很多内核线程在内核空间上同时运行的集合体。

 

内核线程0

 

内核线程0是在系统初始化阶段由start_kernel()函数从无到有创建的一个内核线程,创建的内容包括进程描述符、内核态堆栈、mm、fs、files、signals等。内核线程0最后的初始化工作是创建init内核线程,此后运行cpu_idle,线程0成为idle线程。

 

进程1

 

当调度程序选择到init线程时,init线程开始执行init()函数。init()函数最后调用execve()系统调用装入可执行程序init。自此,init内核线程变成一个普通的进程,即init进程,进程号为1,是其他所有用户进程的父进程。init进程从不终止,因为它创建和监控操作系统外层的所有进程的活动。

 

 

原创粉丝点击