pidhash_init()

PID 테이블을 해쉬로 구현하여 빠르게 검색하고 처리할 수 있도록 하는데 이 함수를 사용하여 초기화 한다.

pidhash_init-1

pidhash_init()

kernel/pid.c

/*
 * The pid hash table is scaled according to the amount of memory in the
 * machine.  From a minimum of 16 slots up to 4096 slots at one gigabyte or
 * more.
 */
void __init pidhash_init(void)
{
        unsigned int i, pidhash_size;

        pid_hash = alloc_large_system_hash("PID", sizeof(*pid_hash), 0, 18,
                                           HASH_EARLY | HASH_SMALL,
                                           &pidhash_shift, NULL,
                                           0, 4096);
        pidhash_size = 1U << pidhash_shift;

        for (i = 0; i < pidhash_size; i++)
                INIT_HLIST_HEAD(&pid_hash[i]);
}

pid용 해쉬 테이블을 할당하고 초기화한다.

  • pid_hash = alloc_large_system_hash(“PID”, sizeof(*pid_hash), 0, 18, HASH_EARLY | HASH_SMALL, &pidhash_shift, NULL, 0, 4096);
    • 커널 초기화 중이므로 early를 사용하여 memblock에 pid용 해쉬테이블 공간을 할당받는다.
    • low_limit와 high_limit는 0과 4096개로 제한한다.
    • 세 번째 인수로 0이 주어진 경우 커널의 lowmem free 페이지 공간을 확인하여 최대 수의 해시 엔트리 수를 계산해낸다.
    •  HASH_EARLY
      • memblock에 할당 요청
    • HASH_SMALL
      • 최소 엔트리 수인 경우 확대하도록 한다.
      • 해시 엔트리가 최소 2^pidhash_shift 이상 그리고 PAGE_SIZE / pid_hash 사이즈 갯 수 보다 크도록 확대 한다.
    • pid_hash_shift
      • 초기 값은 4
    • rpi2 정보 출력 예)
      • PID hash table entries: 4096 (order: 2, 16384 bytes)
  • pidhash_size = 1U << pidhash_shift;
    • pidhash_size를 2^pidhash_shift로 재조정 한다
    • alloc_large_system_hash()를 수행하면서 결정한 해시 엔트리 수에 따라 전역 pidhash_shift 변수가 재조종된다.
      • rpi2 예)
        • 재조정되어 pidhash_shift=12
  • for (i = 0; i < pidhash_size; i++) INIT_HLIST_HEAD(&pid_hash[i]);
    • pidhash_size 만큼 pid_hash[]를 초기화한다.

 

kernel/pid.c

static struct hlist_head *pid_hash;

 

다음 그림은 pid_hash가 pid 구조체 내부에 있는 upid 구조체들과 연결되는 모습을 보여준다.

pidhash_init-2

 

구조체

pid 구조체

include/linux/pid.h

/*
 * What is struct pid?
 *
 * A struct pid is the kernel's internal notion of a process identifier.
 * It refers to individual tasks, process groups, and sessions.  While
 * there are processes attached to it the struct pid lives in a hash
 * table, so it and then the processes that it refers to can be found
 * quickly from the numeric pid value.  The attached processes may be
 * quickly accessed by following pointers from struct pid.
 *
 * Storing pid_t values in the kernel and referring to them later has a
 * problem.  The process originally with that pid may have exited and the
 * pid allocator wrapped, and another process could have come along
 * and been assigned that pid.
 *
 * Referring to user space processes by holding a reference to struct
 * task_struct has a problem.  When the user space process exits
 * the now useless task_struct is still kept.  A task_struct plus a
 * stack consumes around 10K of low kernel memory.  More precisely
 * this is THREAD_SIZE + sizeof(struct task_struct).  By comparison
 * a struct pid is about 64 bytes.
 *
 * Holding a reference to struct pid solves both of these problems.
 * It is small so holding a reference does not consume a lot of
 * resources, and since a new struct pid is allocated when the numeric pid
 * value is reused (when pids wrap around) we don't mistakenly refer to new
 * processes.
 */
struct pid
{
        atomic_t count;
        unsigned int level;
        /* lists of tasks that use this pid */
        struct hlist_head tasks[PIDTYPE_MAX];
        struct rcu_head rcu;
        struct upid numbers[1];
};

 

upid 구조체

include/linux/pid.h

/*
 * struct upid is used to get the id of the struct pid, as it is
 * seen in particular namespace. Later the struct pid is found with
 * find_pid_ns() using the int nr and struct pid_namespace *ns.
 */
struct upid {
        /* Try to keep pid_chain in the same cacheline as nr for find_vpid */
        int nr;
        struct pid_namespace *ns;
        struct hlist_node pid_chain;
};

 

pid_link 구조체

struct pid_link
{
        struct hlist_node node;
        struct pid *pid;
};

 

pid_type

enum pid_type
{
        PIDTYPE_PID,
        PIDTYPE_PGID,
        PIDTYPE_SID,
        PIDTYPE_MAX
};

 

참고

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.