티스토리 뷰
5-16 kernel/fork.c copy_process 3
clone 플래그에 따라 자원을 새로 할당하거나 공유
// clone 인 경우 부모것을 공유
if (clone_flags & CLONE_FILES) {
atomic_inc(&oldf->count);
goto out;
}
// clone 이 아닌경우 복사해서 새로 생성
newf = dup_fd(oldf, &error);
if (!newf)
goto out;
5-17 kernel/fork.c copy_process 4
pid 구조체 & 정수형 pid 할당
// global pid
static inline pid_t pid_nr(struct pid *pid)
{
pid_t nr = 0;
if (pid)
nr = pid->numbers[0].nr;
return nr;
}
// init task 를 사용중인 경우
static inline bool is_child_reaper(struct pid *pid)
{
return pid->numbers[pid->level].nr == 1;
}
// swapper process 인 경우 idle thread 를 생성하는데, 이때는 pid 를 할당하지 않음. (init_struct_pid 를 공유)
if (pid != &init_struct_pid) {
pid = alloc_pid(p->nsproxy->pid_ns_for_children);
}
// global pid
p->pid = pid_nr(pid)
init_task_pid(p, PIDTYPE_PID, pid); // p->pids[PIDTYPE_PID].pid =pid
if (is_child_reaper(pid)) { // init task 가 사용중이라면
ns_of_pid(pid)->child_reaper = p;
p->signal->flags |= SIGNAL_UNKILLABLE;
}
if (thread_group_leader(p)) { // 새 프로세스 생성시
attach_pid(p, PIDTYPE_SID);
attach_pid(p, PIDTYPE_PID);
} else { // 이미 있는 쓰레드 그룹에 추가시 (쓰레드 생성)
// 기존 쓰레드와 동일한걸 사용해서 처리 이미 clone 한듯하다
}
attach_pid(p, PIDTYPE_PGID); // pid 구조체와 task 들을 연결
5-18 kernel/fork.c copy_process 5
태스크 계층 구조 설정
if (clone_flags & CLONE_THREAD) { // 쓰레드 생성 중일때
p->exit_signal = -1;
p->group_leader = current->group_leader;
p->tgid = current->tgid;
} else { // 쓰레드 생성이 아니라 메인 태스크 생성중일때 인듯하다 (유저 프로세스 & 커널 쓰레드)
if (clone_flags & CLONE_PARENT)
p->exit_signal = current->group_leader->exit_signal;
else
p->exit_signal = (clone_flags & CSIGNAL);
p->group_leader = p;
p->tgid = p->pid;
}
// 조부모를 실제 부모로 설정
if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) {
p->real_parent = current->real_parent;
p->parent_exec_id = current->parent_exec_id;
} else {
p->real_parent = current;
p->parent_exec_id = current->self_exec_id;
}
if (thread_group_leader(p)) { // 새 프로세스 생성시
// children 리스트에 sibling 연결
list_add_tail(&p->sibling, &p->real_parent->children);
// 모든 task 가 연결되는 init_task.tasks 에 연결
list_add_tail_rcu(&p->tasks, &init_task.tasks);
} else { // 이미 있는 쓰레드 그룹에 추가시 (쓰레드 생성)
current->signal->nr_threads++;
atomic_inc(¤t->signal->live);
atomic_inc(¤t->signal->sigcnt);
list_add_tail_rcu(&p->thread_group,
&p->group_leader->thread_group);
list_add_tail_rcu(&p->thread_node,
&p->signal->thread_head);
}
5-19 kernel/fork.c copy_process 6
기타 정보 초기화
if ((clone_flags & (CLONE_VM|CLONE_VFORK)) == CLONE_VM) // VM : 쓰레드 생성, (VFORK 부모를 멈추고 부모것 사용?)
p->sas_ss_sp = p->sas_ss_size = 0; // signal stack
// 태스크가 처리해야할 시그널이 있다면 fork 실패처리
if (signal_pending(current)) {
goto bad_fork_cancel_cgroup;
}
5-20 kernel/fork.c dup_task_struct
task_struct 구조체 할당받고, 대부분 부모것을 상속
struct task_struct {
void *stack;
}
// 왜 thread_info 를 stack 으로 사용한걸까..? 이렇게 사용중이라서 그런가보다
#define task_thread_info(task) ((struct thread_info *)(task)->stack)
#define task_stack_page(task) ((task)->stack)
static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org)
{
*task_thread_info(p) = *task_thread_info(org);
task_thread_info(p)->task = p;
}
tsk->stack = ti;
setup_thread_stack(tsk, orig); // 부모 구조체의 thread_info 내용으로 설정. 단 ti->task 는 내 task 로 설정
clear_tsk_need_resched(tsk); // 부모가 resched 되어야 하는 설정이 되어있기 때문에, 나는 제거
atomic_set(&tsk->usage, 2); // 쓰레드가 종료되더라도, 스케줄러에 의해 1 감소 후 task_struct 감소하기때문에 2로 설정
5-21 kernel/sched/core.c sched_fork
fork 된 태스크의 스케줄링 정보 입력하기
get_cpu() // cpu 를 선점
// struct sched_entity {} 값 초기화
// prio 설정
static inline int rt_prio(int prio) // prio 를 가지고 어떤 task 인지도 파악 가능
{
if (unlikely(prio < MAX_RT_PRIO))
return 1;
return 0;
}
put_cpu(); // cpu 선점 해제
5-22 kernel/sched/fair.c task_fork_fair
normal 태스크를 위한 초기화
// runqueue 시간을 동기화
// task 의 cpu 설정
// vruntime 을 current 가 있다면 동일하게 맞춰줌, 이후 조정 과정 거침
if (curr) se->vruntime = (u64)curr->vruntime
// 자식을 먼저 실행하는 옵션도 있음
if (sysctl_sched_child_runs_first && curr && entity_before(curr, se)) {
swap(curr->vruntime, se->vruntime);
resched_curr(rq);
}
5.6 태스크 종료하기
할일이 종료되거나 syscall 에 의해 태스크 종료
자원 해제 작업 진행
5.6.1 do_exit
5-23 kernel/exit.c do_exit
// 종료는 한번만 실행되어야함
// PF = Per process flags
if (unlikely(tsk->flags & PF_EXITING)) {
pr_alert("Fixing recursive fault but reboot is needed!\n"); // 현재 종료중인 process 는 좀비가 되고 reboot 까지 남게됨
tsk->flags |= PF_EXITPIDONE;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule();
}
group_dead = atomic_dec_and_test(&tsk->signal->live); // 쓰레드 그룹내 쓰레드 개수를 1감소하고, 0이되면 group_dead 를 1로 반환
exit_mm, exit_files, exit_fs 등 ref 카운트를 1감소시키고 0이 되면 해당 내용을 해제
tsk->state = TASK_DEAD;
schedule(); // 다른 task 한태 양보하니까 context_switch 불림. 이때 TASK_DEAD 상태라면 task_struct 를 해제
// static struct rq *finish_task_switch(struct task_struct *prev) <-- kernel/sched/core.c
5.7 idle 쓰레드 (swapper)
swapper 는 부팅을 수행하며 시스템을 초기화 하는 역할의 태스크
초기화를 마무리하 면 idle 쓰레드로 변함. cpu 별로 1개씩 존재
idle 쓰레드는 cpu 가 실행할 task 가 없을때 실행됨
5.7.1 idle 쓰레드가 실행되는 과정
우선순위가 높은 class 부터 loop 를 돌며 Task 를 찾을때, 맨 끝가지 가면 idle 쓰레드를 리턴
5.7.2 idle 쓰레드가 하는 일
cpu 를 저전력 상태로 만들어 소모 전류를 줄이고자 함
5-24 kernel/sched/idle.c cpu_idle_loop
idle enter 하는 tick 끄기 (타이머가 발생하면 task 상태가 IDLE->RUNNING 으로 변경됨
#define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED)0
static __always_inline bool need_resched(void)
{
return unlikely(tif_need_resched());
}
static void cpu_idle_loop(void)
{
// idle 쓰레드는 계속 while 문을 돌고있고, 아무 task 도 없을때 다시 이 while 문으로 돌아옴
while (1) {
// idle tick 끄기 : 주기적으로 tick 이 돌고있는데, 이를 비활성화.
// idle 상태로 가기위해 RUNNING 을 만드는데 이를 IDLE 상태에서는 동작하지 않게하기 위함. (IDLE->RUNNING->IDLE-> ...)
while (!need_resched) {
}
// 여기부터 resched 가 필요해진 상황
// idle tick 켜기
}
}
'개발 > 코드로 알아보는 ARM 리눅스 커널 TIL' 카테고리의 다른 글
20250104 5.2.2 PID 할당 ~ 5.5 테스크 생성하기 (0) | 2025.01.11 |
---|---|
20241221 4.9.5 per-cpu 동적 할당 (1) | 2025.01.04 |
20241214 4.9.3 per-cpu first_chunk 구성 & 초기화 & 동적할당 (1) | 2024.12.21 |
20241207 4.9.2 per-cpu (p516) first_chunk 할당 과정 (0) | 2024.12.07 |
20241130 4.8 kmalloc 과 vmalloc (p487) ~ 4.9 per-cpu 할당자 (0) | 2024.12.07 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- 코어 남기기
- shared_from_this
- 면접
- Quest2
- RVO
- 영상 픽셀화 하기
- 에러 위치 찾기
- Golang
- vrpit
- Visual Studio
- C++
- 우리는 vr핏이라고 부릅니다
- print shared_ptr class member variable
- 클래스 맴버 변수 출력하기
- chrome-extension
- mysql
- 잘못된 빨간줄
- SuffixArray
- it's called a vrpit
- vr핏
- 봄날에 스케치
- red underline
- 카카오
- Obstacle Avoidance
- boost
- Reciprocal n-body Collision Avoidance
- cockroach db
- set value
- ad skip
- hole-punching
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함