본문 바로가기

Linux(Centos or RHEL)/RHEL 기초

인터럽트 핸들러?

하드웨어 인터럽트의 처리 과정은?

아래의 블로그를 통해 인터럽트 핸들러에 대해 공부해 보았습니다. 제가 공부할 때 참조한 커널 버전은 v2.6.39.4입니다.

http://rousalome.egloos.com/10012152

 

[리눅스커널] 인터럽트: 리눅스 커널이 처리하는 인터럽트의 주요 개념

앞에서 인터럽트에 대해 소개했으니 리눅스 커널에서 인터럽트를 처리하는 방식을 이해하기 위해 알아야 할 주요 개념을 소개합니다.  인터럽트 핸들러  인터럽트 벡터   인터럽트 디스크립터   인터럽트 컨텍스트 인터럽트 핸들러란? 인터럽트가 발생하면 이를 핸들링하기 위한 함수가 호출되는데 이를 인터럽트 핸들러라고 합니다. 예를 들어

rousalome.egloos.com

 

앞에서 인터럽트에 대해 소개했으니 리눅스 커널에서 인터럽트를 처리하는 방식을 이해하기 위해 알아야 할 주요 개념을 소개합니다.

 

인터럽트 핸들러

인터럽트 벡터

인터럽트 디스크립터

인터럽트 컨텍스트

 

위의 개념들 중 먼저 인터럽트 핸들러에 대해서 공부해 보았습니다.

 

 

인터럽트 핸들러란?

 

인터럽트가 발생하면 이를 핸들링하기 위한 함수가 호출되는데 이를 인터럽트 핸들러라고 합니다. 예를 들어, 키보드 자판을 눌러서 인터럽트가 발생하면 키보드 인터럽트를 처리하는 키보드 인터럽트 핸들러가 호출됩니다. 마찬가지로 스마트폰에서 화면을 손으로 만지면 터치 인터럽트가 발생하고, 터치 인터럽트를 처리하는 터치 인터럽트 핸들러가 호출됩니다.

 

그림 1  디바이스 별로 실행되는 인터럽트 핸들러

 

위의 그림에서 볼 수 있듯이 인터럽트 종류별로 인터럽트 핸들러가 있습니다. 인터럽트 핸들러는 함수 형태로 존재하며, 커널 내의 인터럽트 함수에서 호출합니다. 이처럼 인터럽트가 발생해 지정한 인터럽트 핸들러가 동작하려면 request_irq() 함수를 적절한 인자와 함께 호출해서 미리 인터럽트 핸들러를 등록해 주어야 합니다.

 

이해를 돕기 위한 예시로 컴퓨터에서 마우스를 움직였을 때 인터럽트를 처리하는 코드를 보겠습니다.

 

[https://elixir.bootlin.com/linux/v2.6.39.4/source/drivers/input/mouse/amimouse.c#L75]

static int amimouse_open(struct input_dev *dev)
{
	unsigned short joy0dat;
	int error;

	joy0dat = amiga_custom.joy0dat;

	amimouse_lastx = joy0dat & 0xff;
	amimouse_lasty = joy0dat >> 8;

	error = request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse",
			    dev);
	if (error)
		dev_err(&dev->dev, "Can't allocate irq %d\n", IRQ_AMIGA_VERTB);

	return error;
}

 

 

위의 코드를 보면 request_irq()함수의 두 번째 인자로 amimouse_interrupt() 인터럽트 핸들러 함수를 등록합니다.

 

 

이후, 마우스가 움직여서 인터럽트가 발생하면, request_irq() 함수에서 지정한 amimouse_interrupt() 함수가 호출됩니다.

 

[https://elixir.bootlin.com/linux/v2.6.39.4/source/drivers/input/mouse/amimouse.c#L39]

static irqreturn_t amimouse_interrupt(int irq, void *data)
{
	struct input_dev *dev = data;
	unsigned short joy0dat, potgor;
	int nx, ny, dx, dy;

	joy0dat = amiga_custom.joy0dat;

	nx = joy0dat & 0xff;
	ny = joy0dat >> 8;

	dx = nx - amimouse_lastx;
	dy = ny - amimouse_lasty;

	if (dx < -127) dx = (256 + nx) - amimouse_lastx;
	if (dx >  127) dx = (nx - 256) - amimouse_lastx;
	if (dy < -127) dy = (256 + ny) - amimouse_lasty;
	if (dy >  127) dy = (ny - 256) - amimouse_lasty;

	amimouse_lastx = nx;
	amimouse_lasty = ny;

	potgor = amiga_custom.potgor;

	input_report_rel(dev, REL_X, dx);
	input_report_rel(dev, REL_Y, dy);

	input_report_key(dev, BTN_LEFT,   ciaa.pra & 0x40);
	input_report_key(dev, BTN_MIDDLE, potgor & 0x0100);
	input_report_key(dev, BTN_RIGHT,  potgor & 0x0400);

	input_sync(dev);

	return IRQ_HANDLED;
}

 

인터럽트 핸들러에서는 마우스에서 입력한 데이터 정보를 참고해 유저 공간에 알리는 동작을 수행합니다.

 

 

코드는 조금 복잡해 보일 수 있지만 다음 그림을 보면 인터럽트 처리 과정을 쉽게 이해할 수 있습니다.

그림2 마우스를 움직였을 때 마우스 인터럽트 핸들러를 호출하는 과정