thread 연습중에 이해가 안가는 부분이 있어 질문 올립니다.
글쓴이: study / 작성시간: 월, 2022/03/28 - 1:24오전
https://kingko.tistory.com/entry/Message-Queue%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-Thread-%EA%B0%84-%EB%A9%94%EC%8B%9C%EC%A7%80-%EC%A0%84%EB%8B%AC
를 보면서 thread 프로그래밍 연습을 하고 있었는데요.
좀 이해가 안가는 부분이 있어서 질문 올립니다.
위의 링크를 참고해서 아래와 같이 예제를 만들어 보고 있었습니다. (아직 완성된 건 아닌데요..)
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdint.h>
5 #include <pthread.h>
6 #include <sys/ipc.h>
7 #include <sys/msg.h>
8 #include <sys/stat.h>
9 #include <sys/types.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12
13 #define MAX_THREAD 4
14
15 pthread_mutex_t mutex_lock;
16 pthread_cond_t sync_cond;
17
18 struct _data {
19 int32_t queue_num;
20 int32_t msgtype;
21 int32_t tid;
22 char msg[256];
23 int32_t size;
24 key_t key_id;
25 };
26 typedef struct _data data_t;
27
28 struct _doc_info {
29 int32_t tnum; /* thread number */
30 int32_t start; /* start location of the document */
31 int32_t end; /* end location of the document */
32 char name[80]; /* document file name */
33 char keyword[20]; /* string to find from the file */
34 };
35 typedef struct _doc_info doc_info_t;
36
37 int32_t search_keyword(char *string, char *word)
38 {
39 char *search;
40 const char delim[] = " -.,()\";:{}'+@/<>[]|!?#\n";
41 int32_t ret;
42 char *copy;
43
44 copy = strdup(string);
45
46 search = strtok(copy, delim);
47 while (search != NULL)
48 {
49 search = strtok(NULL, delim);
50 if (search != NULL)
51 {
52 ret = strncmp(word, search, strlen(word));
53 if (ret == 0)
54 {
55 printf("Found!! [%s - %s : %d]\n", word, search, strlen(word));
56 free(copy);
57 return ret;
58 }
59 }
60 }
61
62 free(copy);
63 return -1;
64 }
65
66 void *Tfunction(void *data)
67 {
68 data_t Data;
69 doc_info_t *DocInfo;
70 int32_t bsize;
71 int32_t ret;
72 int32_t readn = 0;
73 char line[256];
74 char *s_word;
75 char *str;
76 FILE *fp;
77
78 Data = *(data_t *)(data);
79 DocInfo = (doc_info_t *)Data.msg;
80
81 bsize = DocInfo->end - DocInfo->start;
82
83 fp = fopen(DocInfo->name, "r");
84 if (fp == NULL)
85 {
86 perror("file open error");
87 exit(-1);
88 }
89
90 lseek(fileno(fp), DocInfo->start, SEEK_SET);
91
92 pthread_mutex_lock(&mutex_lock);
93 pthread_cond_signal(&sync_cond);
94 pthread_mutex_unlock(&mutex_lock);
95
96 for (readn = 0 ; readn < bsize ; )
97 {
98 str = fgets(line, 256, fp);
99 if (str == NULL)
100 {
101 break;
102 }
103 else
104 {
105 line[strlen(line)] = '\0';
106 }
107
108 ret = search_keyword(line, DocInfo->keyword);
109 if (ret == 0) /* Found */
110 {
111 Data.queue_num = 1;
112 Data.msgtype = 1 << 1;
113 Data.size = 256;
114 strncpy(Data.msg, line, 256);
115 printf("Found!!! [%d] : %s\n", DocInfo->tnum, line);
116
117 ret = msgsnd(Data.key_id, (void *)&Data, sizeof(Data), IPC_NOWAIT);
118 if (ret < 0)
119 {
120 perror("msg send error");
121 break;
122 }
123 }
124 readn = readn + strlen(line);
125 sleep(1);
126 }
127
128 fclose(fp);
129 }
130
131 int32_t main(int32_t argc, char *argv[])
132 {
133 data_t Data;
134 doc_info_t DocInfo;
135 struct stat FileInfo;
136 pthread_t p_thread[MAX_THREAD];
137
138 int32_t fd = 0;
139 int32_t fsize = 0;
140 int32_t block_size = 0;
141 int32_t ret = 0;
142 char *fname;
143 char *search;
144 int32_t msg_type;
145 key_t key_id;
146 int32_t i;
147
148 pthread_mutex_init(&mutex_lock, NULL);
149 pthread_cond_init(&sync_cond, NULL);
150
151 fname = argv[1];
152 search = argv[2];
153
154 key_id = msgget((key_t)8888, IPC_CREAT | 0666);
155 if (key_id == -1)
156 {
157 perror("msgget error : ");
158 exit(0);
159 }
160
161 /* open a document file */
162 fd = open(fname, O_RDONLY);
163 if (fd < 0)
164 {
165 perror("File Open Error");
166 return -1;
167 }
168
169 ret = fstat(fd, &FileInfo);
170 if (ret < 0)
171 {
172 perror("fstat error");
173 return -1;
174 }
175 fsize = FileInfo.st_size;
176
177 block_size = fsize / MAX_THREAD;
178
179 for (i = 0 ; i < MAX_THREAD ; i++)
180 {
181 DocInfo.start = (i * block_size);
182 DocInfo.end = DocInfo.start + block_size;
183 sprintf(DocInfo.name, "%s", fname);
184 sprintf(DocInfo.keyword, "%s", search);
185 DocInfo.tnum = i;
186
187 if (i == (MAX_THREAD - 1))
188 {
189 DocInfo.end += fsize % MAX_THREAD;
190 }
191
192 Data.queue_num = 1;
193 Data.msgtype = 1 << 2;
194 Data.size = sizeof(DocInfo);
195 Data.key_id = key_id;
196 Data.tid = DocInfo.tnum;
197 memcpy((void *)Data.msg, (void *)&DocInfo, sizeof(DocInfo));
198
199 pthread_mutex_lock(&mutex_lock);
200 pthread_create(&p_thread[i], NULL, Tfunction, (void *)&Data);
201 pthread_cond_wait(&sync_cond, &mutex_lock);
202 pthread_mutex_unlock(&mutex_lock);
203 }
204
205 while(1)
206 {
207 ret = msgrcv(key_id, (void *)&Data, sizeof(Data), (1>>1), 0);
208 if (ret == -1)
209 {
210 perror("msg recv error");
211 }
212
213 printf("lines [%d] : %s\n", Data.tid, Data.msg);
214 }
215
216 return 0;
217 }실행을 해보면 아래와 같이 됩니다.
$ ./a.out loglog localhost Found!! [localhost - localhost : 9] Found!!! [544109898] : Jun 14 20:36:30 localhost kernel: Linux version 4.18.0-240.el8.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 8.3.1 20191121 (Red Hat 8.3.1-5) (GCC)) #1 SMP Fri Sep 25 19:48:47 UTC 2020 Found!! [localhost - localhost : 9] Found!!! [859451442] : 20:36:30 localhost kernel: BIOS-e820: [mem 0x0000000000100000-0x00000000bfeeffff] usable lines [0] : Jun 14 20:36:30 localhost kernel: Linux version 4.18.0-240.el8.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 8.3.1 20191121 (Red Hat 8.3.1-5) (GCC)) #1 SMP Fri Sep 25 19:48:47 UTC 2020 lines [3] : 20:36:30 localhost kernel: BIOS-e820: [mem 0x0000000000100000-0x00000000bfeeffff] usable Found!! [localhost - localhost : 9] Found!!! [544109898] : Jun 14 20:36:30 localhost kernel: x86/fpu: x87 FPU will use FXSAVE Found!! [localhost - localhost : 9] Found!!! [544109898] : Jun 14 20:36:30 localhost kernel: BIOS-e820: [mem 0x000000000009f800-0x000000000009ffff] reserved lines [1] : Jun 14 20:36:30 localhost kernel: x86/fpu: x87 FPU will use FXSAVE lines [2] : Jun 14 20:36:30 localhost kernel: BIOS-e820: [mem 0x000000000009f800-0x000000000009ffff] reserved Found!! [ - 14 : 0] Found!!! [544109898] : Jun 14 20:36:30 localhost kernel: BIOS-e820: [mem 0x00000000bfef0000-0x00000000bfefefff] ACPI data lines [3] : Jun 14 20:36:30 localhost kernel: BIOS-e820: [mem 0x00000000bfef0000-0x00000000bfefefff] ACPI data Found!! [ - 14 : 0] Found!!! [544109898] : Jun 14 20:36:30 localhost kernel: BIOS-provided physical RAM map: lines [1] : Jun 14 20:36:30 localhost kernel: BIOS-provided physical RAM map: Found!! [ - 14 : 0] Found!!! [544109898] : Jun 14 20:36:30 localhost kernel: BIOS-e820: [mem 0x0000000000000000-0x000000000009f7ff] usable lines [1] : Jun 14 20:36:30 localhost kernel: BIOS-e820: [mem 0x0000000000000000-0x000000000009f7ff] usable
실행예에서 Found!!! 다음에 DocInfo->tnum을 찍어보는데요.
이 값은 소스코드 185번째 줄에서 0, 1, 2, 3 중의 한 값으러 지정을 하는데, 어떻게 544109898 같은 값이 보이는지 이해가 안가서 질문을 올립니다.
혹시 제가 잘못이해하고 있는 부분이 보이시면, 코멘트 부탁드립니다.
Forums:


DocInfo, Data가 main() 함수 내에
DocInfo, Data가 main() 함수 내에 있고 (local variable), 각각의 쓰레드마다 값만 바꿔서 전달하는데 그 주소를 가지고 쓰레드에 전달하네요. 결국은 계속 바뀔수 밖에 없고 또 주소 자체가 스택 영역에 있기 때문에 별도의 스택 영역을 가지고 있는 쓰레드가 보면 의미없는 영역이 됩니다.
DocInfo, Data를 전역 변수로 선언하시고 DocInfo[Thread_num], Data[Thread_num] 등으로 바꿔서 접근해 보세요.
댓글 달기