最全Linux 调试之 TRACE_EVENT(一),2024年最新被大佬问到自闭

为了做好运维面试路上的助攻手,特整理了上百道 【运维技术栈面试题集锦】 ,让你面试不慌心不跳,高薪offer怀里抱!

这次整理的面试题,小到shell、MySQL,大到K8s等云原生技术栈,不仅适合运维新人入行面试需要,还适用于想提升进阶跳槽加薪的运维朋友。

本份面试集锦涵盖了

  • 174 道运维工程师面试题
  • 128道k8s面试题
  • 108道shell脚本面试题
  • 200道Linux面试题
  • 51道docker面试题
  • 35道Jenkis面试题
  • 78道MongoDB面试题
  • 17道ansible面试题
  • 60道dubbo面试题
  • 53道kafka面试
  • 18道mysql面试题
  • 40道nginx面试题
  • 77道redis面试题
  • 28道zookeeper

总计 1000+ 道面试题, 内容 又全含金量又高

  • 174道运维工程师面试题

1、什么是运维?

2、在工作中,运维人员经常需要跟运营人员打交道,请问运营人员是做什么工作的?

3、现在给你三百台服务器,你怎么对他们进行管理?

4、简述raid0 raid1raid5二种工作模式的工作原理及特点

5、LVS、Nginx、HAproxy有什么区别?工作中你怎么选择?

6、Squid、Varinsh和Nginx有什么区别,工作中你怎么选择?

7、Tomcat和Resin有什么区别,工作中你怎么选择?

8、什么是中间件?什么是jdk?

9、讲述一下Tomcat8005、8009、8080三个端口的含义?

10、什么叫CDN?

11、什么叫网站灰度发布?

12、简述DNS进行域名解析的过程?

13、RabbitMQ是什么东西?

14、讲一下Keepalived的工作原理?

15、讲述一下LVS三种模式的工作过程?

16、mysql的innodb如何定位锁问题,mysql如何减少主从复制延迟?

17、如何重置mysql root密码?

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以点击这里获取!

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

TP\_ARGS(prev, next),

它不仅是TRACE_EVENT()宏所需要的,它也是下面的跟踪点基础结构所需要的。跟踪点代码在激活时将调用回调函数(可以为给定的跟踪点分配多个回调)。
创建跟踪点的宏必须同时访问原型和参数。以下是跟踪点宏完成此操作所需的说明:

struct tracepoint\_func {
	void \*func;
	void \*data;
};

struct tracepoint {
	const char \*name;		/\* Tracepoint name \*/
	struct static\_key key;
	void (\*regfunc)(void);
	void (\*unregfunc)(void);
	struct tracepoint\_func __rcu \*funcs;
};

extern struct tracepoint __tracepoint_##name;			\
static inline void trace_##name(proto)				\
{								\
	if (static\_key\_false(&__tracepoint_##name.key))		\
		\_\_DO\_TRACE(&__tracepoint_##name,		\
			TP\_PROTO(data_proto),			\
			TP\_ARGS(data_args),			\
			TP\_CONDITION(cond),,);			\
}	

2.2.4 Structure

Structure:此参数描述将存储在跟踪器环形缓冲区中的数据的结构布局。

TP\_STRUCT\_\_entry(
	\_\_array(	char,	prev_comm,	TASK_COMM_LEN	)
	\_\_field(	pid\_t,	prev_pid			)
	\_\_field(	int,	prev_prio			)
	\_\_field(	long,	prev_state			)
	\_\_array(	char,	next_comm,	TASK_COMM_LEN	)
	\_\_field(	pid\_t,	next_pid			)
	\_\_field(	int,	next_prio			)
),

此参数描述将存储在跟踪器环形缓冲区中的数据的结构布局。结构的每个元素都由另一个宏定义。这些宏用于自动创建结构,与功能不同。请注意,宏之间没有任何分隔符(没有逗号或分号)。
sched_switch跟踪点使用的宏包括:
__array(type,name,len)-这定义了一个数组项,相当于int name[len];其中类型为int,数组的名称为array,数组中的项数为len。
__field(type,name):这定义了一个普通的结构元素,比如in tvar;其中类型为int,名称为var。
还有其他元素宏将在后面的文章中描述。sched_switch跟踪点的定义将生成如下结构:

struct {
   char   prev_comm[TASK_COMM_LEN];
   pid\_t  prev_pid;
   int    prev_prio;
   long   prev_state;
   char   next_comm[TASK_COMM_LEN];
   pid\_t  next_pid;
   int    next_prio;
};

2.2.5 Assignment

Assignment:第五个参数定义了将参数中的数据保存到环形缓冲区的方式。

TP\_fast\_assign(
	memcpy(__entry->next_comm, next->comm, TASK_COMM_LEN);
	__entry->prev_pid	= prev->pid;
	__entry->prev_prio	= prev->prio;
	__entry->prev_state	= \_\_trace\_sched\_switch\_state(prev);
	memcpy(__entry->prev_comm, prev->comm, TASK_COMM_LEN);
	__entry->next_pid	= next->pid;
	__entry->next_prio	= next->prio;
),

TP_fast_assign()中的代码是正常的C代码。特殊变量__entry表示指向由TP_STRUCT__entry定义的结构类型的指针,并直接指向环形缓冲区。TP_fast_assign用于填充TP_STRUCT__entry中创建的所有字段。然后可以使用TP_PROTO和TP_ARGS定义的参数的变量名将适当的数据分配到__entry结构中。

2.2.6 Print

Print:最后一个参数定义如何使用printk()打印TP_STRUCT__entry结构中的字段。

TP\_printk("prev\_comm=%s prev\_pid=%d prev\_prio=%d prev\_state=%s%s ==> next\_comm=%s next\_pid=%d next\_prio=%d",
	__entry->prev_comm, __entry->prev_pid, __entry->prev_prio,
	__entry->prev_state & (TASK_STATE_MAX-1) ?
	  \_\_print\_flags(__entry->prev_state & (TASK_STATE_MAX-1), "|",
			{ 1, "S"} , { 2, "D" }, { 4, "T" }, { 8, "t" },
			{ 16, "Z" }, { 32, "X" }, { 64, "x" },
			{ 128, "K" }, { 256, "W" }, { 512, "P" }) : "R",
	__entry->prev_state & TASK_STATE_MAX ? "+" : "",
	__entry->next_comm, __entry->next_pid, __entry->next_prio)

变量__entry再次用于引用指向包含数据的结构的指针。格式字符串与任何其他printf格式一样。__print_flags()是TRACE_EVENT()附带的一组帮助函数的一部分。

2.3 Format file

Format file:sched_switch TRACE_EVENT()宏以/sys/kernel/debug/tracking/events/sched/sched_switch/format格式生成以下格式文件:

[root@localhost ~]# cat /sys/kernel/debug/tracing/events/sched/sched_switch/format
name: sched_switch
ID: 326
format:
        field:unsigned short common_type;       offset:0;       size:2; signed:0;
        field:unsigned char common_flags;       offset:2;       size:1; signed:0;
        field:unsigned char common_preempt_count;       offset:3;       size:1; signed:0;
        field:int common_pid;   offset:4;       size:4; signed:1;

        field:char prev_comm[16];       offset:8;       size:16;        signed:1;
        field:pid\_t prev_pid;   offset:24;      size:4; signed:1;
        field:int prev_prio;    offset:28;      size:4; signed:1;
        field:long prev_state;  offset:32;      size:8; signed:1;
        field:char next_comm[16];       offset:40;      size:16;        signed:1;
        field:pid\_t next_pid;   offset:56;      size:4; signed:1;
        field:int next_prio;    offset:60;      size:4; signed:1;

print fmt: "prev\_comm=%s prev\_pid=%d prev\_prio=%d prev\_state=%s%s ==> next\_comm=%s next\_pid=%d next\_prio=%d", REC->prev_comm, REC->prev_pid, REC->prev_prio, REC->prev_state & (1024-1) ? \_\_print\_flags(REC->prev_state & (1024-1), "|", { 1, "S"} , { 2, "D" }, { 4, "T" }, { 8, "t" }, { 16, "Z" }, { 32, "X" }, { 64, "x" }, { 128, "K" }, { 256, "W" }, { 512, "P" }) : "R", REC->prev_state & 1024 ? "+" : "", REC->next_comm, REC->next_pid, REC->next_prio

请注意,格式文件中的__entry替换为REC。第一组字段(common_*)不是来自TRACE_EVENT()宏,而是由创建此格式文件的Ftrace添加到所有事件中,其他跟踪程序可以添加不同的字段。格式文件为用户空间工具提供解析包含sched_switch项的二进制输出所需的信息。

2.3.1 tracing/events/

与进程调度有关的其他 tracepoints 点:

[root@localhost ~]# cat /sys/kernel/debug/tracing/events/sched/
enable                       sched_move_numa/             sched_process_free/          sched_stat_runtime/          sched_switch/
filter                       sched_pi_setprio/            sched_process_hang/          sched_stat_sleep/            sched_wait_task/
sched_kthread_stop/          sched_process_exec/          sched_process_wait/          sched_stat_wait/             sched_wake_idle_without_ipi/
sched_kthread_stop_ret/      sched_process_exit/          sched_stat_blocked/          sched_stick_numa/            sched_wakeup/
sched_migrate_task/          sched_process_fork/          sched_stat_iowait/           sched_swap_numa/             sched_wakeup_new/

2.3.2 perf

除了通过 debugfs 的 /tracing/events/ 查看 tracepoint点还可以通过 perf list 查看:

[root@localhost ~]# perf list tracepoint | grep sched:
  sched:sched_kthread_stop                           [Tracepoint event]
  sched:sched_kthread_stop_ret                       [Tracepoint event]
  sched:sched_migrate_task                           [Tracepoint event]
  sched:sched_move_numa                              [Tracepoint event]
  sched:sched_pi_setprio                             [Tracepoint event]
  sched:sched_process_exec                           [Tracepoint event]
  sched:sched_process_exit                           [Tracepoint event]
  sched:sched_process_fork                           [Tracepoint event]
  sched:sched_process_free                           [Tracepoint event]
  sched:sched_process_hang                           [Tracepoint event]
  sched:sched_process_wait                           [Tracepoint event]
  sched:sched_stat_blocked                           [Tracepoint event]
  sched:sched_stat_iowait                            [Tracepoint event]
  sched:sched_stat_runtime                           [Tracepoint event]
  sched:sched_stat_sleep                             [Tracepoint event]
  sched:sched_stat_wait                              [Tracepoint event]
  sched:sched_stick_numa                             [Tracepoint event]
  sched:sched_swap_numa                              [Tracepoint event]
  sched:sched_switch                                 [Tracepoint event]
  sched:sched_wait_task                              [Tracepoint event]
  sched:sched_wake_idle_without_ipi                  [Tracepoint event]
  sched:sched_wakeup                                 [Tracepoint event]
  sched:sched_wakeup_new                             [Tracepoint event]

2.3.3 bpftrace

对于支持 ebpf 的高版本Linux内核版本,可以用bpftrace查看:

yl@yl-virtual-machine:~/Desktop$ uname -r
5.19.0-23-generic
yl@yl-virtual-machine:~/Desktop$ sudo bpftrace -l tracepoint:sched:\*
tracepoint:sched:sched_kthread_stop
tracepoint:sched:sched_kthread_stop_ret
tracepoint:sched:sched_kthread_work_execute_end
tracepoint:sched:sched_kthread_work_execute_start
tracepoint:sched:sched_kthread_work_queue_work
tracepoint:sched:sched_migrate_task
tracepoint:sched:sched_move_numa
tracepoint:sched:sched_pi_setprio
tracepoint:sched:sched_process_exec
tracepoint:sched:sched_process_exit
tracepoint:sched:sched_process_fork
tracepoint:sched:sched_process_free
tracepoint:sched:sched_process_hang
tracepoint:sched:sched_process_wait
tracepoint:sched:sched_stat_blocked
tracepoint:sched:sched_stat_iowait
tracepoint:sched:sched_stat_runtime
tracepoint:sched:sched_stat_sleep
tracepoint:sched:sched_stat_wait
tracepoint:sched:sched_stick_numa
tracepoint:sched:sched_swap_numa
tracepoint:sched:sched_switch
tracepoint:sched:sched_wait_task
tracepoint:sched:sched_wake_idle_without_ipi
tracepoint:sched:sched_wakeup
tracepoint:sched:sched_wakeup_new
tracepoint:sched:sched_waking

2.3.4 bcc

使用bcc查看:

yl@yl-virtual-machine:~/Desktop$ sudo /usr/share/bcc/tools/tplist -v "sched:\*"
sched:sched_kthread_stop
    char comm[TASK_COMM_LEN];
    pid\_t pid;
sched:sched_kthread_stop_ret
    int ret;
sched:sched_kthread_work_queue_work
    void \* work;
    void \* function;
    void \* worker;
sched:sched_kthread_work_execute_start
    void \* work;
    void \* function;
sched:sched_kthread_work_execute_end
    void \* work;
    void \* function;
sched:sched_waking
    char comm[TASK_COMM_LEN];
    pid\_t pid;
    int prio;
    int target_cpu;
sched:sched_wakeup
    char comm[TASK_COMM_LEN];
    pid\_t pid;
    int prio;
    int target_cpu;
sched:sched_wakeup_new
    char comm[TASK_COMM_LEN];
    pid\_t pid;
    int prio;
    int target_cpu;
sched:sched_switch
    char prev_comm[TASK_COMM_LEN];
    pid\_t prev_pid;
    int prev_prio;
    long prev_state;
    char next_comm[TASK_COMM_LEN];
    pid\_t next_pid;
    int next_prio;
sched:sched_migrate_task
    char comm[TASK_COMM_LEN];
    pid\_t pid;
    int prio;
    int orig_cpu;
    int dest_cpu;
sched:sched_process_free
    char comm[TASK_COMM_LEN];
    pid\_t pid;
    int prio;
sched:sched_process_exit
    char comm[TASK_COMM_LEN];
    pid\_t pid;
    int prio;
sched:sched_wait_task
    char comm[TASK_COMM_LEN];
    pid\_t pid;
    int prio;
sched:sched_process_wait
    char comm[TASK_COMM_LEN];
    pid\_t pid;
    int prio;
sched:sched_process_fork
    char parent_comm[TASK_COMM_LEN];
    pid\_t parent_pid;
    char child_comm[TASK_COMM_LEN];
    pid\_t child_pid;
sched:sched_process_exec
    __data_loc char[] filename;
    pid\_t pid;
    pid\_t old_pid;
sched:sched_stat_wait
    char comm[TASK_COMM_LEN];
    pid\_t pid;
    u64 delay;
sched:sched_stat_sleep
    char comm[TASK_COMM_LEN];
    pid\_t pid;
    u64 delay;
sched:sched_stat_iowait
    char comm[TASK_COMM_LEN];
    pid\_t pid;
    u64 delay;
sched:sched_stat_blocked
    char comm[TASK_COMM_LEN];
    pid\_t pid;
    u64 delay;
sched:sched_stat_runtime
    char comm[TASK_COMM_LEN];
    pid\_t pid;
    u64 runtime;
    u64 vruntime;
sched:sched_pi_setprio
    char comm[TASK_COMM_LEN];
    pid\_t pid;
    int oldprio;
    int newprio;
sched:sched_process_hang
    char comm[TASK_COMM_LEN];
    pid\_t pid;
sched:sched_move_numa
    pid\_t pid;
    pid\_t tgid;
    pid\_t ngid;
    int src_cpu;
    int src_nid;
    int dst_cpu;
    int dst_nid;
sched:sched_stick_numa
    pid\_t src_pid;
    pid\_t src_tgid;
    pid\_t src_ngid;
    int src_cpu;
    int src_nid;
    pid\_t dst_pid;
    pid\_t dst_tgid;
    pid\_t dst_ngid;
    int dst_cpu;
    int dst_nid;
sched:sched_swap_numa
    pid\_t src_pid;
    pid\_t src_tgid;
    pid\_t src_ngid;
    int src_cpu;
    int src_nid;
    pid\_t dst_pid;
    pid\_t dst_tgid;
    pid\_t dst_ngid;
    int dst_cpu;
    int dst_nid;
sched:sched_wake_idle_without_ipi
    int cpu;

2.3.5 SystemTap

SystemTap也可以查看:

[root@localhost ~]# stap -L 'kernel.trace("sched\*")'
kernel.trace("sched:sched\_kthread\_stop") $t:struct task\_struct\*
kernel.trace("sched:sched\_kthread\_stop\_ret") $ret:int
kernel.trace("sched:sched\_migrate\_task") $p:struct task\_struct\* $dest_cpu:int
kernel.trace("sched:sched\_move\_numa") $tsk:struct task\_struct\* $src_cpu:int $dst_cpu:int
kernel.trace("sched:sched\_pi\_setprio") $tsk:struct task\_struct\* $newprio:int
kernel.trace("sched:sched\_process\_exec") $p:struct task\_struct\* $old_pid:pid\_t $bprm:struct linux\_binprm\*
kernel.trace("sched:sched\_process\_exit") $p:struct task\_struct\*
kernel.trace("sched:sched\_process\_fork") $parent:struct task\_struct\* $child:struct task\_struct\*
kernel.trace("sched:sched\_process\_free") $p:struct task\_struct\*
kernel.trace("sched:sched\_process\_hang") $tsk:struct task\_struct\*
kernel.trace("sched:sched\_process\_wait") $pid:struct pid\*
kernel.trace("sched:sched\_stat\_blocked") $tsk:struct task\_struct\* $delay:u64
kernel.trace("sched:sched\_stat\_iowait") $tsk:struct task\_struct\* $delay:u64
kernel.trace("sched:sched\_stat\_runtime") $tsk:struct task\_struct\* $runtime:u64 $vruntime:u64
kernel.trace("sched:sched\_stat\_sleep") $tsk:struct task\_struct\* $delay:u64
kernel.trace("sched:sched\_stat\_wait") $tsk:struct task\_struct\* $delay:u64
kernel.trace("sched:sched\_stick\_numa") $tsk:struct task\_struct\* $src_cpu:int $dst_cpu:int
kernel.trace("sched:sched\_swap\_numa") $src_tsk:struct task\_struct\* $src_cpu:int $dst_tsk:struct task\_struct\* $dst_cpu:int
kernel.trace("sched:sched\_switch") $prev:struct task\_struct\* $next:struct task\_struct\*
kernel.trace("sched:sched\_wait\_task") $p:struct task\_struct\*
kernel.trace("sched:sched\_wake\_idle\_without\_ipi") $cpu:int
kernel.trace("sched:sched\_wakeup") $p:struct task\_struct\* $success:int
kernel.trace("sched:sched\_wakeup\_new") $p:struct task\_struct\* $success:int

tracepoint 是由内核开发人员在代码中设置的静态 hook 点,具有稳定的 API 接口,不会随着内核版本的变化而变化,可以提高我们内核跟踪程序的可移植性。但是由于 tracepoint 是需要内核研发人员参数编写,因此在内核代码中的数量有限,并不是所有的内核函数中都具有类似的跟踪点。

三、The header file

内核中的大部分跟踪点都是定义在该目录下:

linux-3.10/include/trace/events/

在这里插入图片描述
与任务调度相关的 tracepoints 点都是在该目录下:

linux-3.10/include/trace/events/sched.h

#undef TRACE\_SYSTEM
#define TRACE\_SYSTEM sched

#if !defined(\_TRACE\_SCHED\_H) || defined(TRACE\_HEADER\_MULTI\_READ)
#define \_TRACE\_SCHED\_H

#include <linux/sched.h>
#include <linux/tracepoint.h>
#include <linux/binfmts.h>

/\*
 \* Tracepoint for calling kthread\_stop, performed to end a kthread:
 \*/
TRACE\_EVENT(sched_kthread_stop,

	TP\_PROTO(struct task\_struct \*t),

	TP\_ARGS(t),

	TP\_STRUCT\_\_entry(
		\_\_array(	char,	comm,	TASK_COMM_LEN	)
		\_\_field(	pid\_t,	pid			)
	),

	TP\_fast\_assign(
		memcpy(__entry->comm, t->comm, TASK_COMM_LEN);
		__entry->pid	= t->pid;
	),

	TP\_printk("comm=%s pid=%d", __entry->comm, __entry->pid)
);

/\*
 \* Tracepoint for the return value of the kthread stopping:
 \*/
TRACE\_EVENT(sched_kthread_stop_ret,

	TP\_PROTO(int ret),

	TP\_ARGS(ret),

	TP\_STRUCT\_\_entry(
		\_\_field(	int,	ret	)
	),

	TP\_fast\_assign(
		__entry->ret	= ret;
	),

	TP\_printk("ret=%d", __entry->ret)
);
......

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以点击这里获取!

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

* Tracepoint for the return value of the kthread stopping:
*/
TRACE_EVENT(sched_kthread_stop_ret,

TP\_PROTO(int ret),

TP\_ARGS(ret),

TP\_STRUCT\_\_entry(
	\_\_field(	int,	ret	)
),

TP\_fast\_assign(
	__entry->ret	= ret;
),

TP\_printk("ret=%d", __entry->ret)

);




**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 18
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值