BSD 버전 Linked List

Β· 1029 words Β· 3 minute read

κ°œμš” πŸ”—

μ‚¬λ‚΄μ—μ„œ μ†ŒμŠ€ νŒŒμΌμ— λŒ€ν•œ λΌμ΄μ„ΌμŠ€λ₯Ό μ •λ¦¬ν•˜κΈ° μ‹œμž‘ν•˜λ©΄μ„œ κΈ°μ‘΄ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ λ¦¬λˆ…μŠ€μ˜ pipe λ₯Ό μ΄μš©ν•˜μ—¬ κ΅¬ν˜„λœ 메세지 큐λ₯Ό μ—°κ²° 리슀트둜 μž¬μž‘μ„±ν•˜λŠ” μž‘μ—…μ„ 맑게 λ˜μ—ˆλ‹€. μ²˜μŒμ—λŠ” λ¦¬λˆ…μŠ€μ˜ μ»€λ„μ—μ„œ μ œκ³΅ν•˜λŠ” list.h λ₯Ό μ‚¬μš©ν•˜μ§€ λͺ»ν•΄μ„œ μ—°κ²° 리슀트λ₯Ό ν•™λΆ€μ‹œμ ˆμ— μ‚¬μš©ν•˜λ˜ λ°©μ‹μœΌλ‘œ 직접 κ΅¬ν˜„ν•˜κ³ μž ν•˜μ˜€λ‹€. ν•˜μ§€λ§Œ 쑰금 더 μ°Ύμ•„λ³΄λ‹ˆ BSD λ²„μ „μ˜ μ—°κ²° λ¦¬μŠ€νŠΈκ°€ <sys/queue.h> 의 ν˜•νƒœλ‘œ μ‘΄μž¬ν•˜κ³  μžˆμ—ˆκ³  ν˜„μž¬ FreeBSD에 ν¬ν•¨λ˜μ–΄ μžˆλŠ” queue.h μ™€λŠ” λ‹€λ₯΄μ§€λ§Œ 였래 μ „ κ³΅μœ ν•˜λ˜ λ ˆκ±°μ‹œ μ½”λ“œλ‘œμ„œ μ—¬μ „νžˆ λ¦¬λˆ…μŠ€ 컀널 내에 BSD 컀널 라이브러리λ₯Ό κ°„μ§ν•˜κ³  μžˆμ—ˆλ‹€. λΌμ΄μ„ΌμŠ€μ— μ „ν˜€ λ¬Έμ œκ°€ λ˜μ§€ μ•Šμ„ 뿐만 μ•„λ‹ˆλΌ ν•„μš”ν•œ λ©”μ‹œμ§€ 큐λ₯Ό κ΅¬ν˜„ν•˜κΈ° μœ„ν•œ λ§€ν¬λ‘œκ°€ μ•ŒκΈ° μ‰½κ²Œ μ •μ˜λ˜μ–΄ μžˆμ–΄ μž‘μ„±ν•˜λŠ”λ°μ—λŠ” 크게 어렡지 μ•Šμ•˜λ‹€. λŒ€μ‹ , λΆˆν•„μš”ν•˜κ²Œ 잘λͺ»λœ λ©”λͺ¨λ¦¬ μ ‘κ·ΌμœΌλ‘œ μΈν•œ μ½”λ“œλ₯Ό λ””λ²„κΉ…ν•˜λŠ”λ° μ‹œκ°„μ΄ 많이 κ±Έλ Έλ‹€.

queue.h πŸ”—

μž‘μ—…μ— μ‚¬μš©ν–ˆλ˜ queue.h 파일(https://github.com/freebsd/freebsd/blob/master/sys/sys/queue.h μ°Έκ³ )μ—λŠ” LIST와 TAILQ, CIRCLEQκ°€ κ΅¬ν˜„λ˜μ–΄ μžˆμ—ˆλ‹€. λ§ν¬λŠ” μ΅œμ‹ λ²„μ „μ˜ 라이브러리라 Circular Queueκ°€ μ‚¬λΌμ Έμžˆμ„ 것이닀. λ¦¬λˆ…μŠ€μ˜ list.h와 λ§ˆμ°¬κ°€μ§€λ‘œ BSD의 queue.h도 리슀트λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄ μž¬λ―ΈμžˆλŠ” 방법을 μ‚¬μš©ν•œλ‹€. λ¨Όμ € man-page에 κΈ°μˆ λ˜μ–΄ μžˆλŠ” μ˜ˆμ‹œλ₯Ό μ‹œμž‘μœΌλ‘œ ν•˜λ‚˜μ”© μ‚΄νŽ΄λ³΄μž.

 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
TAILQ_HEAD(tailhead, entry) head = TAILQ_HEAD_INITIALIZER(head);
struct tailhead *headp;		     /*	Tail queue head. */
struct entry {
    ...
    TAILQ_ENTRY(entry)	entries;     /*	Tail queue. */
    ...
} *n1, *n2, *n3, *np;

TAILQ_INIT(&head);			     /*	Initialize the queue. */

n1	= malloc(sizeof(struct entry));	     /*	Insert at the head. */
TAILQ_INSERT_HEAD(&head, n1, entries);

n1	= malloc(sizeof(struct entry));	     /*	Insert at the tail. */
TAILQ_INSERT_TAIL(&head, n1, entries);

n2	= malloc(sizeof(struct entry));	     /*	Insert after. */
TAILQ_INSERT_AFTER(&head, n1, n2, entries);

n3	= malloc(sizeof(struct entry));	     /*	Insert before. */
TAILQ_INSERT_BEFORE(n2, n3, entries);

TAILQ_REMOVE(&head, n2, entries);	     /*	Deletion. */
free(n2);
                    /*	Forward	traversal. */
TAILQ_FOREACH(np, &head, entries)
    np-> ...

λ¨Όμ €, TAILQ_HEADλΆ€ν„° μ‚΄νŽ΄λ³΄λ©΄ 맀크둜λ₯Ό 톡해 인자둜 λ„˜κΈ΄ μ΄λ¦„μœΌλ‘œ ꡬ쑰체λ₯Ό ν•˜λ‚˜ μ„€μ •ν•˜λŠ” 것을 μ•Œ 수 μžˆλ‹€. 예λ₯Ό λ“€μ–΄ μ•„λž˜μ™€ 같이 μ •μ˜λœ μžλ£Œν˜•μ„ TAILQ ν˜•νƒœλ‘œ μ—°κ²°ν•˜κ³  μ‹Άλ‹€λ©΄,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
struct message {
    int idx;
    TAILQ_ENTRY(message) entries;
};

TAILQ_HEAD(msg_head, message) head; // struct msg_head head 와 κ°™λ‹€.

#define	TAILQ_ENTRY(type)						\
struct {								\
	struct type *tqe_next;	/* next element */			\
	struct type **tqe_prev;	/* address of previous next element */	\
	TRACEBUF							\
}

μœ„μ˜ μ½”λ“œμ²˜λŸΌ μ •μ˜ν•˜μ—¬ μ‚¬μš©ν•  수 μžˆλ‹€. 자료ꡬ쑰 μ•ˆμ— TAILQ_ENTRYλ₯Ό μ‚¬μš©ν•¨μœΌλ‘œμ¨ 링크 객체λ₯Ό ν¬ν•¨ν•˜λŠ” λ°©μ‹μœΌλ‘œ κ΅¬ν˜„ν•œλ‹€. μœ„ μ˜ˆμ œμ—μ„œ, μ—°κ²° λ¦¬μŠ€νŠΈλŠ” struct msg_head* head λ₯Ό 톡해 μ ‘κ·Όν•  수 있으며, head에 μ—°κ²°λ˜λŠ” λ…Έλ“œλ“€μ˜ μ‹€μ œ 데이터 struct message μžμ²΄λŠ” *headκ°€ κ°–λŠ” *tqh_first, **tqh_lastλ₯Ό 톡해 얻을 수 μžˆλ‹€. μœ„μ—μ„œ TAILQ_HEAD 맀크둜λ₯Ό 톡해 얻은 ꡬ쑰체의 κ΅¬μ‘°λŠ” μ•„λž˜μ™€ κ°™λ‹€.

1
2
3
4
5
6
#define	TAILQ_CLASS_HEAD(name, type)					\
struct name {								\
	class type *tqh_first;	/* first element */			\
	class type **tqh_last;	/* addr of last next element */		\
	TRACEBUF							\
}

전체적인 연결을 λ‹€μ΄μ–΄κ·Έλž¨μœΌλ‘œ λ‚˜νƒ€λ‚΄λ©΄ μ•„λž˜μ™€ κ°™λ‹€.

TAILQ in BSD