进程、线程与stack段

传统的UNIX进程模型,操作系统中一切皆进程或文件,Linux继承了UNIX的设计哲学,现如今,线程是非常重要的,线程只是进程中的一条执行路径(a thread is merely an execution path within a process),线程共享进程虚拟内存中除stack段的一切资源,每个线程拥有私有的stack段,因为线程的stack段保存了线程的上下文,所以线程才真正实现了并发运行。

Linux可调度的实体是线程而不是进程(the kernel schedulable entity简称KSE),这其实也是Linux系统架构的一个核心内容,Linux中的任何线程(内核线程与用户线程),都映射到内核的元数据结构stack structre(没错,这就是进程的描述符)。

另一个需要牢记的点是CPU 支持的每个特权级别,每个线程都需要一个stack段,当代操作系统包含两个CPU的特权级别,非特权的用户模式与特权的内核模式(也称作用户空间和内核空间),因此,在Linux上的每个存活的用户态线程拥有两个stack段

  • A user space stack: This stack is in play when the thread executes usermode code paths(线程执行用户太下的代码,启用用户态的stack段).
  • A kernel space stack: This stack is in play when the thread switches to kernel mode (via a system call or processor exception) and executes kernel code paths (in process context)(线程通过系统调用切换到内核态执行内核代码时,启用内核态的stack段).

当然内核线程只有一个内核空间的stack段。

通过下图这个实例来对上述的内容进一步阐述

 用户空间的虚拟内存中有三个进程,每个进程有1、3、2个线程,这些线程均拥有用户态的stack段,与这些线程相对应的是内核态的三个stack段和对应的内核态下的数据结构,除此之外是最底层只拥有内核态stack段的n个内核线程kthrd1、kthrd2、kthrdn。

通过一段bash脚本打印进程、线程、内核态线程、用户态线程

bash代码

[root@ct7_node02 tmp]# cat test.sh 
#!/bin/bash

total_prcs=$(ps -A|wc -l)
printf "\nTotal # of processes alive              = %9d\n" ${total_prcs}

# ps -LA shows all threads
total_thrds=$(ps -LA|wc -l)
printf "Total # of threads alive                = %9d\n" ${total_thrds}

# ps aux shows all kernel threads names (col 11) in square brackets; count 'em
total_kthrds=$(ps aux|awk '{print $11}'|grep "^\["|wc -l)

printf "Total # of kernel threads alive         = %9d\n" ${total_kthrds}
printf "Thus, total # of usermode threads alive = %9d\n" $((${total_thrds}-${total_kthrds}))

exit 0
[root@ct7_node02 tmp]# ./test.sh 
Total # of processes alive              =       152
Total # of threads alive                =       166
Total # of kernel threads alive         =       120
Thus, total # of usermode threads alive =        46

根据输出可以看到,当前的系统有152个进程(其实是32个进程152-120),当前操作系统一共为166个线程,其中120个线程是内核线程,剩余46个线程为32个进程以及这些进程创建的14(46-32)个线程。

那当前系统有多少个stack呢?120+46*2个(内核线程有1个stack,用户太的线程在用户态有一个stack,内核态也有一个stack)

stack是如何被创建的呢

If the process is multithreaded, it will have one user-mode thread stack per thread alive (including main()); The stacks are allocated either at the time of calling fork(2) (for main()) or pthread_create(3) (for the remaining threads within the process), which results in this code path being executed in process context within the kernel:

FYI, the pthread_create(3) library API on Linux invokes the (very Linuxspecific) clone(2) system call; this system call ends up calling _do_fork(); the clone_flags parameter passed along informs the kernel as to how exactly to create the 'custom process'; in other words, a thread!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值