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] 등으로 바꿔서 접근해 보세요.
댓글 달기