linux-debug/process

created : Tue, 10 Nov 2020 23:51:56 +0900
modified : Wed, 09 Dec 2020 13:31:33 +0900
linux-debug process

프로세스

유저 레벨 프로세스 실행 실습

cat /sys/kernel/debug/tracing/available_filter_functions | grep sys_clone
#!/bin/bash

echo 0 > /sys/kernel/debug/tracing/tracing_on
sleep 1
echo "tracing_off"

echo 0 > /sys/kernel/debug/tracing/events/enable
sleep 1
echo "events disabled"

echo __x64_sys_clone do_exit > /sys/kernel/debug/tracing/set_ftrace_filter
sleep 1
echo "set_ftrace_filter init"

echo function > /sys/kernel/debug/tracing/current_tracer
sleep 1
echo "function tracer enabled"

echo __x64_sys_clone do_exit > /sys/kernel/debug/tracing/set_ftrace_filter
echo _do_fork copy_process* >> /sys/kernel/debug/tracing/set_ftrace_filter
sleep 1
echo "set_ftrace_filter enabled"

echo 1 > /sys/kernel/debug/tracing/events/sched/sched_switch/enable
echo 1 > /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
echo 1 > /sys/kernel/debug/tracing/events/sched/sched_process_fork/enable
echo 1 > /sys/kernel/debug/tracing/events/sched/sched_process_exit/enable

echo 1 > /sys/kernel/debug/tracing/events/signal/enable

sleep 1
echo "event enabled"

echo 1 > /sys/kernel/debug/tracing/options/func_stack_trace
echo 1 > /sys/kernel/debug/tracing/options/sym-offset
echo "function stack trace enabled"

echo 1 > /sys/kernel/debug/tracing/tracing_on
echo "tracing_on"
copy_process.part.53+0x5/0x1d40
_do_fork+0xcf/0x3a0
__x64_sys_clone+0x27/0x30
do_syscall_64+0x55/0x110
do_exit+0x5/0xbd0
do_group_exit+0x47/0xb0
get_signal+0xfe/0x7e0
do_signal+0x37/0x650
exit_to_usermode_loop+0x9b/0xb0
do_syscall_64+0x101/0x110
프로세스 실행 흐름
  1. 프로세스 생성
  2. raspbian_proc 프로세스 실행
  3. 프로세스 종료
  4. 부모 프로세스에게 시그널 전달
배운 내용

커널 스레드

커널 스레드 생성 과정
  1. kthreadd 프로세스에서 커널 스레드 생성을 요청
  1. kthreadd 프로세스가 커널 스레드를 생성
커널 내부 프로세스의 생성 과정 (_do_fork() 함수)
copy_process 함수 분석
 /* copy all the process information */
 shm_init_task(p);
 retval = security_task_alloc(p, clone_flags);
 if (retval)
   goto bad_fork_cleanup_audit;
 retval = copy_semundo(clone_flags, p);
 if (retval)
   goto bad_fork_cleanup_security;
 retval = copy_files(clone_flags, p);
 if (retval)
   goto bad_fork_cleanup_semundo;
 retval = copy_fs(clone_flags, p);
 if (retval)
   goto bad_fork_cleanup_files;
 retval = copy_sighand(clone_flags, p);
 if (retval)
   goto bad_fork_cleanup_fs;
 retval = copy_signal(clone_flags, p);
 if (retval)
   goto bad_fork_cleanup_sighand;
 retval = copy_mm(clone_flags, p);
 if (retval)
   goto bad_fork_cleanup_signal;
 retval = copy_namespaces(clone_flags, p);
 if (retval)
   goto bad_fork_cleanup_mm;
 retval = copy_io(clone_flags, p);
 if (retval)
   goto bad_fork_cleanup_namespaces;
 retval = copy_thread_tls(clone_flags, stack_start, stack_size, p, tls);
wake_up_new_task()

프로세스의 종료 과정 분석

태스크 디스크립터(task_struct 구조체)
스레드 정보 : thread_info 구조체
struct thread_info {
  struct task_struct	*task;		/* main task structure */
  unsigned long		flags;		/* low level flags */
  __u32			cpu;		/* current CPU */
  __s32			preempt_count; /* 0 => preemptable, <0 => BUG */

  mm_segment_t		addr_limit; /* thread address space:
                                 0-0x7FFFFFFF for user-thead
                                 0-0xFFFFFFFF for kernel-thread
                               */
  __u8			supervisor_stack[0];

/* saved context data */
unsigned long           ksp;
};
#endif
cpu 필드에 대한 상세 분석
thread_info 구조체 초기화 코드 분석
프로세스의 태스크 디스크립터에 접근하는 매크로 함수
 DECLARE_PER_CPU(struct task_struct *, current_task);
 static __always_inline struct task_struct *get_current(void)
 {
   return this_cpu_read_stable(current_task);
 }

 #define current get_current()
 this_cpu_write(current_task, next_p);
 this_cpu_write(cpu_current_top_of_stack, task_top_of_stack(next_p));

 /* Reload sp0. */
 update_task_stack(next_p);

 switch_to_extra(prev_p, next_p);
프로세스 디버깅