Blog

查看软中断和内核线程

Content #

proc 文件系统中:

  1. /proc/softirqs 提供了软中断的运行情况;
  2. /proc/interrupts 提供了硬中断的运行情况。

运行下面的命令,查看 /proc/softirqs 文件的内容,你就可以看到各种类型软中断在不同 CPU 上的累积运行次数:

$ cat /proc/softirqs
                    CPU0       CPU1
          HI:          0          0
       TIMER:     811613    1972736
      NET_TX:         49          7
      NET_RX:    1136736    1506885
       BLOCK:          0          0
    IRQ_POLL:          0          0
     TASKLET:     304787       3691
       SCHED:     689718    1897539
     HRTIMER:          0          0
         RCU:    1330771    1354737

在查看 /proc/softirqs 文件内容时,你要特别注意以下这两点。

第一,要注意软中断的类型,也就是这个界面中第一列的内容。从第一列你可以看到,软中断包括了 10 个类别,分别对应不同的工作类型。比如 NET_RX 表示网络接收中断,而 NET_TX 表示网络发送中断。

第二,要注意同一种软中断在不同 CPU 上的分布情况,也就是同一行的内容。正常情况下,同一种中断在不同 CPU 上的累积次数应该差不多。比如这个界面中,NET_RX 在 CPU0 和 CPU1 上的中断次数基本是同一个数量级,相差不大。

不过你可能发现,TASKLET 在不同 CPU 上的分布并不均匀。TASKLET 是最常用的软中断实现机制,每个 TASKLET 只运行一次就会结束 ,并且只在调用它的函数所在的 CPU 上运行。

...

硬中断与软中断

Content #

事实上,为了解决中断处理程序执行过长和中断丢失的问题,Linux 将中断处理过程分成了两个阶段,也就是上半部和下半部:

  1. 上半部用来快速处理中断,它在中断禁止模式下运行,主要处理跟硬件紧密相关的或时间敏感的工作。
  2. 下半部用来延迟处理上半部未完成的工作,通常以内核线程的方式运行。

网卡接收到数据包后,会通过硬件中断的方式,通知内核有新的数据到了。这时,内核就应该调用中断处理程序来响应它。这种情况下的上半部和下半部分别负责什么工作呢?

对上半部来说,既然是快速处理,其实就是要把网卡的数据读到内存中,然后更新一下硬件寄存器的状态(表示数据已经读好了),最后再发送一个软中断信号,通知下半部做进一步的处理。

而下半部被软中断信号唤醒后,需要从内存中找到网络数据,再按照网络协议栈,对数据进行逐层解析和处理,直到把它送给应用程序。

所以,这两个阶段你也可以这样理解:

  1. 上半部直接处理硬件请求,也就是我们常说的硬中断,特点是快速执行;
  2. 而下半部则是由内核触发,也就是我们常说的软中断,特点是延迟执行。

实际上,上半部会打断 CPU 正在执行的任务,然后立即执行中断处理程序。而下半部以内核线程的方式执行,并且每个 CPU 都对应一个软中断内核线程,名字为 “ksoftirqd/CPU 编号”,比如说, 0 号 CPU 对应的软中断内核线程的名字就是 ksoftirqd/0。

不过要注意的是,软中断不只包括了刚刚所讲的硬件设备中断处理程序的下半部,一些内核自定义的事件也属于软中断,比如内核调度和 RCU 锁(Read-Copy Update 的缩写,RCU 是 Linux 内核中最常用的锁之一)等。

Viewpoints #

From #

09 | 基础篇:怎么理解Linux软中断?

进程组和会话

Content #

进程组和会话。它们用来管理一组相互关联的进程。

  1. 进程组表示一组相互关联的进程,比如每个子进程都是父进程所在组的成员;

  2. 而会话是指共享同一个控制终端的一个或多个进程组。

比如,我们通过 SSH 登录服务器,就会打开一个控制终端(TTY),这个控制终端就对应一个会话。而我们在终端中运行的命令以及它们的子进程,就构成了一个个的进程组,其中,在后台运行的命令,构成后台进程组;在前台运行的命令,构成前台进程组。

Viewpoints #

From #

07 | 案例篇:系统中出现大量不可中断进程和僵尸进程怎么办?(上)

进程运行状态

Content #

进程运行状态:

  1. R 是 Running 或 Runnable 的缩写,表示进程在 CPU 的就绪队列中,正在运行或者正在等待运行。

  2. D 是 Disk Sleep 的缩写,也就是不可中断状态睡眠(Uninterruptible Sleep),一般表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断。

不可中断状态是为了保证进程数据与硬件状态一致,并且正常情况下,不可中断状态在很短时间内就会结束。所以,短时的不可中断状态进程,我们一般可以忽略。

但如果系统或硬件发生了故障,进程可能会在不可中断状态保持很久,甚至导致系统中出现大量不可中断进程。这时,你就得注意下,系统是不是出现了 I/O 等性能问题。

  1. Z 是 Zombie 的缩写,它表示僵尸进程,也就是进程实际上已经结束了,但是父进程还没有回收它的资源(比如进程的描述符、PID 等)。

正常情况下,当一个进程创建了子进程后,它应该通过系统调用 wait() 或者 waitpid() 等待子进程结束,回收子进程的资源;而子进程在结束时,会向它的父进程发送 SIGCHLD 信号,所以,父进程还可以注册 SIGCHLD 信号的处理函数,异步回收资源。

如果父进程没这么做,或是子进程执行太快,父进程还没来得及处理子进程状态,子进程就已经提前退出,那这时的子进程就会变成僵尸进程。换句话说,父亲应该一直对儿子负责,善始善终,如果不作为或者跟不上,都会导致“问题少年”的出现。

通常,僵尸进程持续的时间都比较短,在父进程回收它的资源后就会消亡;或者在父进程退出后,由 init 进程回收后也会消亡。

一旦父进程没有处理子进程的终止,还一直保持运行状态,那么子进程就会一直处于僵尸状态。大量的僵尸进程会用尽 PID 进程号,导致新进程不能创建,所以这种情况一定要避免。

  1. S 是 Interruptible Sleep 的缩写,也就是可中断状态睡眠,表示进程因为等待某个事件而被系统挂起。当进程等待的事件发生时,它会被唤醒并进入 R 状态。

  2. I 是 Idle 的缩写,也就是空闲状态,用在不可中断睡眠的内核线程上。前面说了,硬件交互导致的不可中断进程用 D 表示,但对某些内核线程来说,它们有可能实际上并没有任何负载,用 Idle 正是为了区分这种情况。要注意,D 状态的进程会导致平均负载升高, I 状态的进程却不会。

  3. T 或者 t,也就是 Stopped 或 Traced 的缩写,表示进程处于暂停或者跟踪状态。

向一个进程发送 SIGSTOP 信号,它就会因响应这个信号变成暂停状态(Stopped);再向它发送 SIGCONT 信号,进程又会恢复运行(如果进程是终端里直接启动的,则需要你用 fg 命令,恢复到前台运行)。

...

从脑海中的想法到具体目标

Content #

我们来看,这个长长的弧线代表了人们通常的做法:从他们脑海中的想法一步跨越到你的目标。对大部分人来说,这一步迈得太大了。你应该反其道而行之,回去先搞清楚对方脑海中的想法,然后再通过提问的方式确认这些想法。你想达成协议吗?你想与对方会谈吗?这些问题一经确认,就要向你的目标一步一步迈进。

因此,你的目标在右边,对方在左边,说服对方的办法就是一步一步走,以循序渐进的方式带领他们从左边走到右边。

From #

沃顿商学院最受欢迎的谈判课

劝说女儿去医院缝伤口

Content #

在哥伦比亚大学商学院我的班上,有一位名叫丽萨·斯蒂芬斯(Lisa Stephens)的女士,她有一个5岁的女儿。一个星期六的早上,她女儿在厨房里摔了一跤,额头被餐桌的尖角划了一道深深的伤口。这个名叫奥布丽的孩子情绪激动,暴躁不安。孩子的外公——丽萨的父亲——也情绪激动,暴躁不安。

显然,奥布丽必须去医院缝几针,但她就是不肯去,她拼命抱住桌子不放,没人能将她的小手指从餐桌上掰开。

丽萨也快情绪失控了,这时,她突然停了下来。她对自己说:“等等,我正在学习谈判课程,我要用谈判来解决这个问题。”

于是丽萨走到女儿身边,轻轻地摸了一下女儿的手臂。“妈妈爱你吗?”丽萨问。“爱。”她女儿抽了抽鼻子,平静了下来。

“妈妈会做任何伤害你的事吗?”丽萨问。“不会。”女儿说。

“在我们长成大人的过程中,有时候我们是不是必须做一些我们不喜欢做的事呢?”丽萨问。“是。”奥布丽说。

“妈妈就接受过手术,”丽萨说,她让女儿看自己的伤疤,“外公也接受过手术。”丽萨的父亲也让奥布丽看了看自己的伤疤。不到5分钟,丽萨的女儿就松开了桌子,自己朝汽车走去。

在这个事例中,有几点情况很清楚。首先,奥布丽拒绝去医院完全是一种不理智的行为。她应该去医院,而且应该迅速去医院,这是为她好。但是,正如每天都在进行的无数谈判中的情形一样,她表现得不理智。

这个事例说明的第二点是,开始谈判时,我们必须仔细思考对方脑海中的画面。丽萨的目的是让奥布丽去医院,但不会对奥布丽造成进一步的伤害。妈妈意识到奥布丽脑海中的画面是:“我很疼,我是一个人,我需要爱。”

于是,丽萨经过一番考虑,明白了自己的目标是什么。丽萨想,有什么办法可以说服奥布丽呢?于是,丽萨问:“妈妈爱你吗?”这个问题让女儿看到,妈妈明白女儿需要爱。丽萨引导女儿回答了这个问题。

接着,丽萨意识到女儿也许在想:“好吧,妈妈是爱我的,但我还是很疼。”于是,妈妈又问:“妈妈会做任何伤害你的事吗?”奥布丽意识到妈妈也知道自己此时很疼。

整个过程是循序渐进的,从妈妈思考孩子脑海中的画面开始,一直到实现妈妈的目标。这个过程并不需要很长时间——它是一步一步进行的。最后,还不到5分钟,奥布丽就心甘情愿地朝汽车走去,而不是一边乱踢一边尖叫着被拖向汽车——这种方式更常见,也更容易伤害到孩子。

总之,丽萨给了奥布丽一系列的情感补偿,这些情感补偿直接消除了奥布丽的恐惧,让她看到妈妈完全理解她。在其他情况下,情感补偿可以是一个道歉、几句同情抚慰的话,或一个让步,也可能只是听某个心情烦闷的人把话说完。

情感补偿可以让对方平静下来,让对方去倾听,让对方愿意更多地思考自己的利益。情感补偿可以使对方从一开始的非理性状态,一点一点地,向一个更理想的(可能不是理性的)结果靠拢。

From #

沃顿商学院最受欢迎的谈判课

不要说“你不接我的电话”

Content #

有很多种措辞方式。你不要说“我们不相信你”,而要改为,“我们怎样开始建立互信关系?”不要说“你不接我的电话”,改成这句怎么样:“你接到我们的电话了吗?我们非常想跟你谈几件事。”勤加练习,你就会越来越擅长措辞技巧。

From #

沃顿商学院最受欢迎的谈判课

给客服代表写感谢信

Content #

大部分人都没想过要给客服代表写感谢信,为其人事档案增光添彩。事实上,这样的感谢信对推销员或客服代表意义非常大。一封满是真情流露的感谢信是感谢工作人员的极好方式,一定会让他喜出望外——是否写感谢信完全取决于你。对旅游业的客服代表而言,这样的感谢信于他们不啻一大福音,尤其是在公司大幅裁员、经济低迷的不景气时期。对航空公司的员工而言,来自乘客的一封真情流露的感谢信,有可能决定他们是否能保住饭碗,或者是否能从临时员工转为正式员工。

From #

沃顿商学院最受欢迎的谈判课

情感补偿

Content #

要想加强一段关系,最强有力的方法就是进行情感补偿。没有情感补偿,任何关系都无法维系。

情感补偿是某种能令对方感觉更舒服的行为:一个同情、一个道歉、一个让步。它还包括各种无形的东西,如尊重、给对方面子、对对方价值的肯定评价。

情感补偿几乎总能化解人们不合理的需求,它是日常生活的一部分。几乎每一个人都会在某个时刻感到紧张、心烦、恐慌、愤怒、沮丧、悲伤或失望。我们所有人都会在事后对自己的行为懊悔不已。在一段关系中,你的任务是去帮助对方消除这些消极负面的感受。

你也许不得不忍受对方对你说出刻薄、伤人的话,他们这样说并非出于本意,而是因为你是他们身边唯一的人,他们需要发泄。如果事实如此,你必须保持冷静,满足他们的需求。必须对情感补偿进行具体调整,以使其符合相关个体的需求,情感补偿可以是谈心开导,也可以是保持沉默。

此外,你必须全部接受他们的无礼言论或情绪,以此作为切入点。因为需要情感补偿的人几乎不会去倾听别人说话。只有借助一扇小小的窗口才能让他们去倾听:与他们的情绪感受有关的信息。你必须小心谨慎,不要让他们更加心烦意乱。一言不当就会令窗口关闭,伤害彼此的关系,因为你没有满足他们的情感需求。

From #

沃顿商学院最受欢迎的谈判课

要信任,但也要核实

Content #

在商业关系中,我建议将一切记录下来。这听起来似乎过于偏执,但我曾看过太多这样的例子。在这些例子中,人们不顾自己的事业和家庭安全,冒险与对方建立商业关系,最后却沦为政治或其他人攫取私利的牺牲品。需要记录的内容包括:重要的会议、你做了什么、对方做了什么和说了什么。将其视为一种对未来保障的投资。每天花5~10分钟将自己所做的工作写下来,提升自己对公司的价值。任何人所做的任何事,只要与你有关,都将其记录在案。

美国前总统罗纳德·里根有一句关于限制核武器的名言:“要信任,但也要核实。”这句话在商业关系中也不失为一条很好的建议。在商场中,不要毫无怀疑地奋勇向前,问问自己,这能为他们带来什么;问问自己,每一个人放弃了什么;问问自己,是否令自己陷入了一种容易受伤害的境地。

From #

沃顿商学院最受欢迎的谈判课