pthread_create에 argument를 여러 개 넣고 싶다면?

AlwaysEden·2023년 12월 26일
0

CS

목록 보기
2/7
post-thumbnail

Posix library의 pthread_create를 사용할 때 가끔 argument를 여러 개 넘겨야 할 상황에 부딪힐 수 있습니다. 이때 Global variable로 넘길 수 있겠지만, 이는 Data race를 발생 시킬 수 있으므로 argument로 넘기는 게 더 안정적일 거 같다는 생각입니다.

pthread_create의 문법 상 하나의 argument만 넘길 수 있으니 메모리가 연속적으로 이어져있는 데이터 구조를 넘기는 게 방법인 거 같습니다. C를 기준으로 구조체라고 생각합니다.

int pthread_create(pthread_t *restrict thread,
                          const pthread_attr_t *restrict attr,
                          void *(*start_routine)(void *),
                          void *restrict arg);

구조체를 넘기고 싶을 때는 Structure Padding을 주의해야합니다. Structure Padding은 간단히 설명하고 넘어가겠습니다.

예를 들어 아래의 structure가 있다고 가정하겠습니다.

struct test{
	char a;
    int b;
};

char는 1byte이고 int는 4byte를 할당 받기에 이러한 구조체를 pass했다면 1byte와 4byte로 쪼개면 되겠지라는 생각을 할 것입니다. 하지만 우리의 컴퓨터는 흔히 알듯이 32bit or 64bit mechine입니다. 즉, 하나의 instruction이 4byte or 8byte라는 겁니다(해당 글은 4byte 기준으로 설명하겠습니다). 그래서 한번의 CPU cycle 당 4byte 씩 읽게 되는데, 이렇게 되면 char 1byte랑 int는 3byte만 읽게 되어서 문제가 생깁니다. 이러한 배경에서 char의 크기는 Padding에 힘입어 instruction의 크기ㅔ 맞춰지게 됩니다. 즉, char는 4byte(1byte+empty 3byte), int도 4byte로 총 8byte가 되는 것이죠. 그래서 pass받은 곳에서 데이터를 쪼갤 때는 4byte씩 접근해야하는 것입니다. 이러한 Memory Level의 이해가 필요합니다. padding을 피하는 방법도 있는데, 이 이상의 자세한 사항을 추가적으로 찾아보시기를 바랍니다.

Anyway, Stucture Padding에 주의하며 pass하였다면 해당 routine에서 다시 parsing하는 것이 중요합니다. parameter의 data type은 void*입니다. 그렇기 때문에 위 test구조체를 예로 들자면,

char a = (char)*((int *)a)

이렇게 parsing해야합니다. 이를 위해서는 당연히 pointer에 대한 이해가 있어야합니다. 그리고 int와 char와 같은 data type은 그저 box, 즉 문자열이니 정수이니 그런 해석이 아니라, 메모리에서 1byte와 4byte 단위로 읽겠다면 box같은 개념이라는 것도 이해해야 합니다. 저도 이거 처음 parsing할 때는 애 많이 먹었습니다,,,

+글 쓰다가 32bit과 64bit mechine의 word size가 다른데 과연 int size 어떻게 될까? 여전히 4byte인가?라는 의문이 생겼는데 추후에 공부해서 작성해보겠습니다.

오늘도 읽어주셔서 감사합니다. 지적과 훈수는 저를 성장하게 합니다. 감사합니다!

profile
컴퓨터 공학생입니다. 공부 하면서 겪은 문제들과 떠오르는 생각들을 써보려고합니다. 태클은 언제나 환영입니다. https://github.com/AlwaysEden

0개의 댓글