linux线程切换和进程切换的方法

进程切换分两步:

1.切换页目录以使用新的地址空间

2.切换内核栈和硬件上下文

对于linux来说,线程和进程的最大区别就在于地址空间,对于线程切换,第1步是不需要做的,第2是进程和线程切换都要做的。

切换的性能消耗:

1、线程上下文切换和进程上下问切换一个最主要的区别是线程的切换虚拟内存空间依然是相同的,但是进程切换是不同的。这两种上下文切换的处理都是通过操作系统内核来完成的。内核的这种切换过程伴随的最显著的性能损耗是将寄存器中的内容切换出。

2、另外一个隐藏的损耗是上下文的切换会扰乱处理器的缓存机制。简单的说,一旦去切换上下文,处理器中所有已经缓存的内存地址一瞬间都作废了。还有一个显著的区别是当你改变虚拟内存空间的时候,处理的页表缓冲(processor's Translation Lookaside Buffer (TLB))或者相当的神马东西会被全部刷新,这将导致内存的访问在一段时间内相当的低效。但是在线程的切换中,不会出现这个问题。

系统调用:处于进程上下文

系统调用是在进程上下文中,并没有tasklet之类的延迟运行,系统调用本身可以休眠,这些可以参见内核代码

虽然系统调用实与其他中断实现有点类似,通过IDT表查找入口处理函数,但是系统调用与其他中断最大的不同是,系统调用是代表当前进程执行的,所以current宏/task_struct是有意义的,这个休眠可以被唤醒
 
系统调用,异常,中断(其中中断是异步时钟,异常时同步时钟),也可以把系统调用成为异常

中断上下文:在中断中执行时依赖的环境,就是中断上下文(不包括系统调用,是硬件中断)

进程上下文:当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文

1、首先,这两个上下文都处于内核空间。

2、其次,两者的区别在于,进程上下文与当前执行进程密切相关,而中断上下文在逻辑上与进程没有关系。

进程上下文主要是异常处理程序和内核线程。内核之所以进入进程上下文是因为进程自身的一些工作需要在内核中做。例如,系统调用是为当前进程服务的,异常通常是处理进程导致的错误状态等。所以在进程上下文中引用current是有意义的。

内核进入中断上下文是因为中断信号而导致的中断处理或软中断。而中断信号的发生是随机的,中断处理程序及软中断并不能事先预测发生中断时当前运行的是哪个进程,所以在中断上下文中引用current是可以的,但没有意义。事实上,对于A进程希望等待的中断信号,可能在B进程执行期间发生。例如,A进程启动写磁盘操作,A进程睡眠后现在时B进程在运行,当磁盘写完后磁盘中断信号打断的是B进程,在中断处理时会唤醒A进程。

上下文这个词会让人想到进程的CPU寄存器状态,但好像进入进程上下文(异常处理系统调用)和进入中断上下文(中断处理),内核所做的工作没有太大区别。所以,这两个上下文的主要区别,我认为在于是否与进程相关。

运行于进程上下文的内核代码是可抢占的,但中断上下文则会一直运行至结束,不会被抢占。因此,内核会限制中断上下文的工作,不允许其执行如下操作:

(1) 进入睡眠状态或主动放弃CPU;

由于中断上下文不属于任何进程,它与current没有任何关系(尽管此时current指向被中断的进程),所以中断上下文一旦睡眠或者放弃CPU,将无法被唤醒。所以也叫原子上下文(atomic context)。

(2) 占用互斥体;

为了保护中断句柄临界区资源,不能使用mutexes。如果获得不到信号量,代码就会睡眠,会产生和上面相同的情况,如果必须使用锁,则使用spinlock。

(3) 执行耗时的任务;

中断处理应该尽可能快,因为内核要响应大量服务和请求,中断上下文占用CPU时间太长会严重影响系统功能。在中断处理例程中执行耗时任务时,应该交由中断处理例程底半部来处理。

(4) 访问用户空间虚拟内存。

因为中断上下文是和特定进程无关的,它是内核代表硬件运行在内核空间,所以在中断上下文无法访问用户空间的虚拟地址

(5) 中断处理例程不应该设置成reentrant(可被并行或递归调用的例程)。

因为中断发生时,preempt和irq都被disable,直到中断返回。所以中断上下文和进程上下文不一样,中断处理例程的不同实例,是不允许在SMP上并发运行的。

(6)中断处理例程可以被更高级别的IRQ中断。(不能嵌套中断)使用软中断,上部分关中断,也就是禁止嵌套,下半部分使用软中断

如果想禁止这种中断,可以将中断处理例程定义成快速处理例程,相当于告诉CPU,该例程运行时,禁止本地CPU上所有中断请求。这直接导致的结果是,由于其他中断被延迟响应,系统性能下降。

软中断是一种延时机制,代码执行的优先级比进程要高,比硬中断要低。相比于硬件中断,软中段是在开中断的环境中执行的(长时间关中断对系统的开销太大), 代码是执行在中断/线程上下文的,是不能睡眠的,虽然每个cpu都有一个对应的ksoftirqd/n线程来执行软中断,但是do_softirq这个函数也还会在中断退出时调用到,因此不能睡眠(中断上下文不能睡眠的原因是由于调度系统是以进程为基本单位的,调度时会把当前进程的上下文保存在task_struct这个数据结构中,当进程被调度重新执行时会找到执行的断点,但是中断上下文是没有特定task_struct结构体的,当然现在有所谓的线程话中断,可以满足在中断处理函数执行阻塞操作,但是实时性可能会有问题。还有就是中断代表当前进程执行的概念,个人感觉有点扯淡,毕竟整个内核空间是由所有进程共享的,不存在代表的概念)

上面我们介绍的可延迟函数运行在中断上下文中(软中断的一个检查点就是do_IRQ退出的时候),于是导致了一些问题:软中断不能睡眠、不能阻塞。由于中断上下文出于内核态,没有进程切换,所以如果软中断一旦睡眠或者阻塞,将无法退出这种状态,导致内核会整个僵死。但可阻塞函数不能用在中断上下文中实现,必须要运行在进程上下文中,例如访问磁盘数据块的函数。因此,可阻塞函数不能用软中断来实现。但是它们往往又具有可延迟的特性。

以上就是小编为大家带来的linux线程切换和进程切换的方法全部内容了,希望大家多多支持我们~

(0)

相关推荐

  • Linux中进程和线程的对比与区别

    Linux中进程和线程的对比与区别 1.概念 进程:正在运行中的程序. 线程:进程中的一条执行路径. 2.区别 (1)通常在一个进程中可以包含若干个线程,它们可以利用进程所拥有的资源.在引入线程的操作系统中,通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位. (2)线程和进程的区别在于,子进程和父进程有不同的代码和数据空间,而多个线程则共享数据空间,每个线程有自己的执行堆栈和程序计数器为其执行上下文.多线程主要是为了节约CPU时间,发挥利用,根据具体情况而定.线程的

  • Linux多线程环境下 关于进程线程终止函数总结

    pthread_kill: pthread_kill与kill有区别,是向线程发送signal.,大部分signal的默认动作是终止进程的运行,所以,我们才要用signal()去抓信号并加上处理函数. int pthread_kill(pthread_t thread, int sig); 向指定ID的线程发送sig信号,如果线程代码内不做处理,则按照信号默认的行为影响整个进程,也就是说,如果你给一个线程发送了SIGQUIT,但线程却没有实现signal处理函数,则整个进程退出. pthread

  • 浅析linux环境下一个进程最多能有多少个线程

    默认情况下: 主线程+辅助线程 +<253个自己的线程<=255 含主线程和一个辅助线程,最多255个,即你自己只能生成253个线程. 据说可以设置线程数目: 据说是可以设置的,但本人还没有验证!不知道可否. 在你的shell中键入limit命令,里面有descriptor的数目,就是你的进程可以创建的最大线程数目.可以通过修改内核文件更改该数目.

  • 深入探讨linux下进程的最大线程数、进程最大数、进程打开的文件数

    =====最大线程数====linux 系统中单个进程的最大线程数有其最大的限制 PTHREAD_THREADS_MAX这个限制可以在 /usr/include/bits/local_lim.h 中查看对 linuxthreads 这个值一般是 1024,对于 nptl 则没有硬性的限制,仅仅受限于系统的资源这个系统的资源主要就是线程的 stack 所占用的内存,用 ulimit -s 可以查看默认的线程栈大小,一般情况下,这个值是 8M可以写一段简单的代码验证最多可以创建多少个线程 复制代码

  • linux下的C\C++多进程多线程编程实例详解

    linux下的C\C++多进程多线程编程实例详解 1.多进程编程 #include <stdlib.h> #include <sys/types.h> #include <unistd.h> int main() { pid_t child_pid; /* 创建一个子进程 */ child_pid = fork(); if(child_pid == 0) { printf("child pid\n"); exit(0); } else { print

  • linux线程切换和进程切换的方法

    进程切换分两步: 1.切换页目录以使用新的地址空间 2.切换内核栈和硬件上下文 对于linux来说,线程和进程的最大区别就在于地址空间,对于线程切换,第1步是不需要做的,第2是进程和线程切换都要做的. 切换的性能消耗: 1.线程上下文切换和进程上下问切换一个最主要的区别是线程的切换虚拟内存空间依然是相同的,但是进程切换是不同的.这两种上下文切换的处理都是通过操作系统内核来完成的.内核的这种切换过程伴随的最显著的性能损耗是将寄存器中的内容切换出. 2.另外一个隐藏的损耗是上下文的切换会扰乱处理器的

  • 浅谈linux线程切换问题

    处理器总处于以下状态中的一种: 1.内核态,运行于进程上下文,内核代表进程运行于内核空间: 2.内核态,运行于中断上下文,内核代表硬件运行于内核空间: 3.用户态,运行于用户空间: 一个进程的上下文可以分为三个部分:用户级上下文.寄存器上下文以及系统级上下文. 用户级上下文:  正文.数据.用户堆栈以及共享存储区: 寄存器上下文:  通用寄存器.程序寄存器(IP).处理器状态寄存器(EFLAGS).栈指针(ESP): 系统级上下文:  进程控制块task_struct.内存管理信息(mm_str

  • 详解Linux监控重要进程的实现方法

    不管后台服务程序写的多么健壮,还是可能会出现core dump等程序异常退出的情况,但是一般情况下需要在无 人为干预情况下,能够自动重新启动,保证服务进程能够服务用户.这时就需要一个监控程序来实现能够让服务进程自动重新启动.查阅相关资料及尝试一些方法之后,总结linux系统监控重要进程的实现方法:脚本检测和子进程替换. 1.脚本检测 (1) 基本思路: 通过shell命令(ps -e | grep "$1" | grep -v "grep" | wc -l) 获取

  • linux普通用户su root切换提示没有文件或目录的解决方法

    1. 首先进入单用户模式: 1). ubuntu : 上述情况可以在grub界面选择第二项修复,但没有grub可以参考: 1.重启ubuntu,随即长按shirft进入grub菜单: 2.选择recovery mode,按"e"键进入编辑页面:如下: 非恢复模式为:   3.将ro recovery nomodeset替换为"rw single init=/bin/bash" (上述的界面中将改为rw single init=/bin/bash) 4.按ctrl+x

  • 在linux shell脚本中root切换到普通用户执行脚本或命令的方法

    需求: 安装deb包,设置程序安装后启动,不需要root权限启动程序 | 不能用root权限启动 其他开机启动选项 方法:root临时降低权限 secUser=`who am i | awk '{print $1}'` #echo $secUser su $secUser -c <指令> > /dev/null 2>&1 & #这一条命令的执行权限是临时的,只在本条语句起作用 id -u # 结果为0,还是root用户权限 附: su --help -c, --co

  • Linux下用SSH退出符切换SSH会话的实现方法

    这个技巧非常实用. 尤其是远程登陆到一台主机 A, 然后从 A 登陆到 B, 如果希望在 A 上做一些操作, 还得再开一个终 端, 很是麻烦. 当使用 ssh 从本机登录到远程主机时, 可能希望切换到本地做一些操作, 然后再重新回到远程主机. 这个时候, 不需要中 断 ssh 连接, 只需要按照如下步骤操作即可: 1.登入远程主机: localhost$ ssh 172.16.1.165 oracle@172.16.1.165's password: Last login: Fri Mar 26

  • Kotlin线程的桥接与切换使用介绍

    目录 一.线程的桥接 1.runBlocking方法 2.BlockingCoroutine类 二.线程的切换 1.withContext方法 2.startUndispatchedOrReturn方法 3.ScopeCoroutine类 4.UndispatchedCoroutine类 5.DispatchedCoroutine类 6.总结 一.线程的桥接 1.runBlocking方法 runBlocking方法用于在线程中去执行suspend方法,代码如下: @Throws(Interru

  • JS实现点击链接切换显示隐藏内容的方法

    本文实例讲述了JS实现点击链接切换显示隐藏内容的方法.分享给大家供大家参考,具体如下: 先来看看运行效果: 具体代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>www.jb51.net 点击链接切换显示隐藏内容</title> <style> a { cursor: pointer

  • javascript的tab切换原理与效果实现方法

    本文实例讲述了javascript的tab切换原理与效果实现方法.分享给大家供大家参考. 具体实现方法如下: 复制代码 代码如下: <html> <head> <style type="text/css"> #container{border:solid 1px green;width:300px;height:300px;} li{float:left;margin-left:20px;} p{float:left;} #sports,#milit

随机推荐