개요

예전 블로그 자료에 오래된 커널 버전에서 동작하는 커널 타이머 API를 작성했었다.

 

https://pak-j.tistory.com/33

 

리눅스 커널 타이머, Linux Kernel Timer (Kernel 3.18.44)

개요 리눅스 Eth MAC 디바이스 드라이버에서 Link Down 이벤트가 발생하지 않는 현상이 있었다. 확인해보니 PHY 칩이 Switch 구조로 되어있어 CPU 쪽으로 직접적인 인터럽트가 발생하지 않는 구조였기

pak-j.tistory.com

 

언젠가는 최신 커널에 같은 기능을 포팅할 수도 있겠다 생각하여,

최신 리눅스 커널에서 동작하는 커널 타이머 API 예제를 새롭게 추가해주었다.

 

해당 페이지에 올리는 커널 타이머 API 들은 최소 4.14.x 버전에서 동작한다.

 

https://elixir.bootlin.com/linux/latest/source 리눅스 커널 소스를 보여주는 해당 링크에서 확인해보았을 때 4.14.x 부터 setup_timer 등과 같이 최신 리눅스 커널에서 사용되는 API들을 확인할 수 있었다.

 

그리고 아래에 작성한 예제 소스는 Kernel 5.18.x에서 정상적으로 동작하는 것을 확인할 수 있었다.

 

예제 소스

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/time.h>
#include <linux/spinlock.h>

/**
 * ===================================================
 *  
 *  Global Variable
 * 
 * ===================================================
 */
#define TIMER_SEC (1 * HZ)

struct timer_data {
	int value;
	spinlock_t lock;
	struct timer_list timer;
	bool isActive;
};
struct timer_data my_timer = {};


/**
 * ===================================================
 *  
 *  Timer Functions
 * 
 * ===================================================
 */
void timer_callback(struct timer_list *timer)
{
	struct timer_data *priv = from_timer(priv, timer, timer);
	int i;

	priv->value++;
	printk("timer_callback() : timer cnt : %d\n", priv->value);

	spin_lock(&priv->lock);
	if(priv->isActive)
	{
		// Timer Restart
		mod_timer(timer, jiffies + TIMER_SEC);
	}
	spin_unlock(&priv->lock);
}

void timer_init(void)
{
	printk("timer_init()\n");

	my_timer.led_toggle = true;
	my_timer.isActive = true;
	spin_lock_init(&my_timer.lock);
	timer_setup(&my_timer.timer, timer_callback, 0);

	// Timer Start
	mod_timer(&my_timer.timer, jiffies + TIMER_SEC);
}

void timer_exit(void)
{
	printk("timer_exit()\n");

	spin_lock(&my_timer.lock);
	my_timer.isActive = false;
	del_timer(&my_timer.timer);
	spin_unlock(&my_timer.lock);
}


/**
 * ===================================================
 *  
 *  Register Driver in Kernel
 * 
 * ===================================================
 */
int __init init_(void)
{
	timer_init();

	return 0;
}

void __exit exit_(void)
{
	timer_exit();
}

module_init(init_);
module_exit(exit_);

 

 

References

https://hyeyoo.com/90

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기