Linux Process States 与Systrace 中thread states

2022-05-13 17:33:16 浏览数 (1)

我们知道Linux进程分为下面几种状态。

  • TASK_RUNNING: The process is either running on CPU or waiting in a run queue to get scheduled.
  • TASK_INTERRUPTIBLE: The process is sleeping, waiting for some event to occur. The process is open to be interrupted by signals. Once signalled or awoken by explicit wake-up call, the process transitions to TASK_RUNNING.
  • TASK_UNINTERRUPTIBLE: The process state is similar to TASK_INTERRUPTIBLE except that in this state it does not process signals. It may not be desirable even to interrupt the process while in this state since it may be in the middle of completing some important task. When the event occurs that it is waiting for, the process is awaken by the explicit wake-up call.
  • TASK_KILLABLE:The process is sleeping killably.It works like TASK_UNINTERRUPTIBLE with the bonus that it can respond to fatal signals.TASK_UNINTERRUPTIBLE TASK_WAKEKILL = TASK_KILLABLE
  • TASK_STOPPED: The process execution is stopped, it's not running, and not able to run. On receipt of signals like SIGSTOP, SIGTSTP, and so on, the process arrives at this state. The process would be runnable again on receipt of signal SIGCONT.
  • TASK_TRACED: A process arrives at this state while it is being monitored by other processes such as debuggers.
  • EXIT_ZOMBIE: The process has terminated. It is lingering around just for its parent to collect some statistical information about it.
  • EXIT_DEAD: The final state (just like it sounds). The process reaches this state when it is being removed from the system since its parent has just collected all statistical information by issuing the wait4() or waitpid() system call.

Process sleep

The Linux kernelprovides two ways to put a process to sleep.

The normal way to put a process to sleep is to set the process's state to either TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE and call the scheduler's function schedule(). This results in the process getting moved off from the CPU run queue. If the process is sleeping in interruptible mode (by setting its state to TASK_INTERRUPTIBLE), it can be awakened either by an explicit wake-up call (wakeup_process()) or by signals needing processing.

However, if the process is sleeping in uninterruptible mode (by setting its state to TASK_UNINTERRUPTIBLE), it can only be awakened by an explicit wake-up call. It is advised to put the processes into interruptible sleep mode rather than uninterruptible sleep mode unless you really, really need to (such during device I/O when processing signals is difficult).

Systrace 中线程的状态

在Systrace 中我们常见的状态有R,R ,S ,D ,D|K,R 和R+都是running 或runnable 状态。其他都是sleep 状态。S 是INTERRUPTIBLE的sleep。,D 是UNINTERRUPTIBLE的sleep。D|K 是UNINTERRUPTIBLE的但是可以被killable的sleep。

AudioOut_2-1558 ( 621) [005] d..3 26071.007774: sched_switch: prev_comm=AudioOut_2 prev_pid=1558 prev_prio=101 prev_state=R ==> next_comm=FastMixer next_pid=1557 next_prio=96

AudioOut_2-1558 ( 621) [004] d..3 26071.368342: sched_switch: prev_comm=AudioOut_2 prev_pid=1558 prev_prio=101 prev_state=S ==> next_comm=ims_rtp_daemon next_pid=1148 next_prio=120

AudioOut_2-1558 ( 621) [007] d..3 26071.389107: sched_switch: prev_comm=AudioOut_2 prev_pid=1558 prev_prio=101 prev_state=R ==> next_comm=cfinteractive next_pid=279 next_prio=0

AudioOut_2-1558 ( 621) [006] d..3 26071.427973: sched_switch: prev_comm=AudioOut_2 prev_pid=1558 prev_prio=101 prev_state=D ==> next_comm=logd.writer next_pid=368 next_prio=130

AudioOut_2-1558 ( 621) [006] d..3 26073.468035: sched_switch: prev_comm=AudioOut_2 prev_pid=1558 prev_prio=101 prev_state=D|K ==> next_comm=qmuxd next_pid=757 next_prio=120

Systrace 状态解析

  • Running 从一个process call sched_switch function 到目标process call sched_switch为此pid 运行时间。 如: ndroid.launcher-584 [001] d..3 12622.506890: sched_switch: prev_comm=ndroid.launcher prev_pid=584 prev_prio=120 prev_state=R ==> next_comm=Binder_1 next_pid=217 next_prio=120' 表示即将在cpu1上运行pid 217的binder_1 process。而pid为584的launcher 将sleep。 Binder_1-217 [001] d..3 12622.506918: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=D ==> next_comm=ndroid.launcher next_pid=584 next_prio=120 表示即将在cpu1上运行launcher,而pid为217的binder_1将sleep。这样pid 217的binder_1便运行了(12622.506918-12622.506890)s.
  • Runnable 从sched_wakeup 开始到sched_switch 结束。 如: ndroid.launcher-584 [001] d..4 12622.506936: sched_wakeup: comm=Binder_1 pid=217 prio=120 success=1 target_cpu=001 其表示PID为584的launcher 在.936wakeup 进程号为217的Binder_1进程,其将运行在cpu1上。此后pid为217的binder_1进程处于runnable 状态。

ndroid.launcher-584 [001] d..3 12622.506950: sched_switch: prev_comm=ndroid.launcher prev_pid=584 prev_prio=120 prev_state=R ==> next_comm=Binder_1 next_pid=217 next_prio=120

表示即将在cpu1上运行pid 217的binder_1 process。而pid为584的launcher 将sleep。此后PID 为217的process 变为running状态,其runnable的时间为(950-936)ms.

  • Sleep 从该PID call sched_switch 到其他PID,此PID process 进入sleep状态,当其他PID 的进程sched_switch 到此进程时,该进程的sleep状态结束。 如: ndroid.launcher-584 [001] d..3 12622.506890: sched_switch: prev_comm=ndroid.launcher prev_pid=584 prev_prio=120 prev_state=R ==> next_comm=Binder_1 next_pid=217 next_prio=120' 表示即将在cpu1上运行pid 217的binder_1 process。而pid为584的launcher 将sleep。 Binder_1-217 [001] d..3 12622.506918: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=D ==> next_comm=ndroid.launcher next_pid=584 next_prio=120 表示即将在cpu1上运行launcher,而pid为217的binder_1将sleep。这样pid 为584的进程sleep了(12622.506918-12622.506890)s. 根据被sched 的进程的最近状态确定sleep的状态。
  • INTERRUPTIBLE Sleep 如果prev_state=R 或S 则其实INTERRUPTIBLE sleep。
  • UNINTERRUPTIBLE Sleep 如果prev_state=D 则其实UNINTERRUPTIBLE sleep。
  • UNINTERRUPTIBLE|KILLABLE Sleep 如果prev_state=D|K则其实UNINTERRUPTIBLE KILLABLE sleep。

Systrace 解析示例

test('importOneSequenceWithSchedWakeUp', function() { var lines = [ 'ndroid.launcher-584 [001] d..3 12622.506890: sched_switch: prev_comm=ndroid.launcher prev_pid=584 prev_prio=120 prev_state=R ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck ' Binder_1-217 [001] d..3 12622.506918: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=D ==> next_comm=ndroid.launcher next_pid=584 next_prio=120', // @suppress longLineCheck 'ndroid.launcher-584 [001] d..4 12622.506936: sched_wakeup: comm=Binder_1 pid=217 prio=120 success=1 target_cpu=001', // @suppress longLineCheck 'ndroid.launcher-584 [001] d..3 12622.506950: sched_switch: prev_comm=ndroid.launcher prev_pid=584 prev_prio=120 prev_state=R ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck ' Binder_1-217 [001] ...1 12622.507057: tracing_mark_write: B|128|queueBuffer', // @suppress longLineCheck ' Binder_1-217 [001] ...1 12622.507175: tracing_mark_write: E', ' Binder_1-217 [001] d..3 12622.507253: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=S ==> next_comm=ndroid.launcher next_pid=584 next_prio=120' // @suppress longLineCheck ];

var m = new tr.Model(lines.join('n'), false); assert.isFalse(m.hasImportWarnings);

var thread = m.findAllThreadsNamed('Binder_1')[0]; var timeSlices = thread.timeSlices; assert.equal(timeSlices.length, 4);

var runningSlice = timeSlices[0]; assert.equal(runningSlice.title, 'Running'); assert.closeTo(12622506.890, runningSlice.start, 1e-5); assert.closeTo(.918 - .890, runningSlice.duration, 1e-5);

var sleepSlice = timeSlices[1]; assert.equal(sleepSlice.title, 'Uninterruptible Sleep'); assert.closeTo(12622506.918, sleepSlice.start, 1e-5); assert.closeTo(.936 - .918, sleepSlice.duration, 1e-5);

var wakeupSlice = timeSlices[2]; assert.equal(wakeupSlice.title, 'Runnable'); assert.closeTo(12622506.936, wakeupSlice.start, 1e-5); assert.closeTo(.950 - .936, wakeupSlice.duration, 1e-5); assert.equal(wakeupSlice.args['wakeup from tid'], 584);

var runningSlice2 = timeSlices[3]; assert.equal(runningSlice2.title, 'Running'); assert.closeTo(12622506.950, runningSlice2.start, 1e-5); assert.closeTo(7.253 - 6.950, runningSlice2.duration, 1e-5); });

0 人点赞