CS 지식 정리/라즈베리파이-C언어

Wiring Pi 파헤치기 (2) PI-Thread 알아보기

termuni 2025. 3. 12. 16:44

오늘은 Wiring Pi의 Thread를 알아볼 예정이며, 이 과정에서 C언어로 Threading을 제작하는 방법도 알아볼 예정이다.

#include <stdio.h>
#include <wiringPi.h>

// LED Pin - wiringPi pin 0 is BCM_GPIO 17.

#define	LED	0

PI_THREAD (blinky)
{
  for (;;)
  {
    digitalWrite (LED, HIGH) ;	// On
    delay (500) ;		// mS
    digitalWrite (LED, LOW) ;	// Off
    delay (500) ;
  }
}


int main (void)
{
  printf ("Raspberry Pi blink\n") ;

  wiringPiSetup () ;
  pinMode (LED, OUTPUT) ;

  piThreadCreate (blinky) ;

  for (;;)
  {
    printf ("Hello, world\n") ;
    delay (600) ;
  }

  return 0 ;
}

이 코드를 통해 Main에서는 600ms 마다 Hello World를, 그리고 Thread에서는 Blinky를 따로 돌릴 것으로 보인다.

 

digitalWrite, pinMode는 이미 보았으니 이번에는

PI_THREAD와 piThreadCreate를 살펴보자!

 

1. piThreadCreate(void *(*fn) (void *))

int piThreadCreate (void *(*fn)(void *))
{
  pthread_t myThread ;

  return pthread_create (&myThread, NULL, fn, NULL) ;
}

이 piThreadCreate 함수는 piThread.c에 정의되어 있으며, 함수 포인터로 pthread를 생성하는 역할을 한다.

 

참고로, pthread_create 함수는

int       WINPTHREAD_API pthread_create(pthread_t *th, const pthread_attr_t *attr, void *(* func)(void *), void *arg);

와 같이 정의되어 있으며, 여기서 myThread가 지역변수여도 큰 상관이 없다.

중요한 것은 func을 이어주는 Function 포인터인것!


2. PI_THREAD(X)

#define	PI_THREAD(X)	void *X (UNU void *dummy)

 

이 PI_THREAD의 근원에 좀 더 가까이 가보니, 다음과 같은 것들을 알아내었다.

#define	UNU	__attribute__((unused))
#define __attribute__(x) /* nothing */

 

사실 여기부터는 잘 모르겠어서, 우선 GPT에게 물어보았다.


#define PI_THREAD(X) void *X (UNU void *dummy)

이 매크로를 사용하면 스레드 함수의 형식을 표준화할 수 있습니다.
➡ 즉, PI_THREAD(myThread)는 다음과 동일하게 변환됩니다.

void *myThread(UNU void *dummy);

➡ 이 코드는 POSIX 스레드(pthread_create())와 함께 사용할 수 있는 함수 형태로 변환됩니다.
➡ pthread_create()는 다음과 같은 함수 포인터를 요구합니다.

void *(*start_routine) (void *);

➡ 따라서 PI_THREAD()를 사용하면 스레드 함수의 형식을 강제할 수 있습니다.


 

그래서 추측하기로는 변화는 다음과 같을 것으로 보인다.

 

1. 매크로 사용 하 PI_THREAD(blinky) 변화

void *blinky (UNU void *dummy)

 

2. 해당 과정에 있어 자동적으로 함수 내용 Follow

void *blinky(__attribute__((unused)) void *dummy) {
  for (;;) {
    digitalWrite(LED, HIGH);  // On
    delay(500);
    digitalWrite(LED, LOW);   // Off
    delay(500);
  }
}

 

이렇게 pthread의 일반적인 정의 방식대로 blinky가 정의되고, 이를 pthread_create에 들어가서 작동하게 된다.


여기까지 해서 thread가 정의되고, 작동하는 이유까지 알아보았다.

이와 관련하여

  1. thread는 무엇인지
  2. 함수 포인터는 무엇이고 어떻게 쓰이는지
  3. raspberry pi에 있어 thread는 과연 멀티 프로세싱인지 멀티쓰레드인지
  4. 쓰레드가 1개 코어에서만 돌아가는지

등 알아봐야 할 것이 더 늘었다... 

아무래도 몇개는 CS 지식을 정리하며 진행하는 것이 좋아보인다!