본문 바로가기
Development/Linux

poll 을 이용한 드라이버와 어플리케이션 통신 하기

by qWooWp 2020. 12. 31.
반응형

목적

드라이버에서 특정 이벤트가 발생하였을 때 어플리케이션에 통지 하기 위한 방법으로

poll 에 원한는 이벤트를 등록을 하고 이벤트가 발생했을 때 write read ioctl 을 수행하여 드라이버와 상호 통신 수행을 하기 위함.

 

보통 스레드에서 계속 적으로 poll 을 수행하고 이벤트에 따라 read, write ioctl 을 수행하게 됩니다.

 

어플리케이션 소스

#include <poll.h>


void Thread::run()
{
    int retval = 0;
    pollfd poll_event;

/*
#define POLLIN      0x0001  // 읽을 데이타가 있다.
#define POLLPRI     0x0002  // 긴급한 읽을 데이타가 있다.
#define POLLOUT     0x0004  // 쓰기가 봉쇄(block)가 아니다.
#define POLLERR     0x0008  // 에러발생
#define POLLHUP     0x0010  // 연결이 끊겼음
#define POLLNVAL    0x0020  // 파일지시자가 열리지 않은것같은
                            // Invalid request (잘못된 요청)
POLLIN
    device file에서 data를 읽을 수 있는 상태가 되면 poll()함수가 종료되도록 설정하기 위해 event 필드에 사용하는 macro.
    반대로 poll()함수가 종료되었을때 device file을 읽을수 잇는 상태 인지 검사하기위해서는 revents filed 에 이 Macro 상수를 사용해야 한다.

POLLPRI
    device file에서 긴급하게 data를 읽을수 있는 상태가 되면 poll()함수 역시 긴급하게 종료되도록 설정하기 위해 events filed에 사용하는 Macro.
    반대로 poll()함수가 종료되었을때 device file에서 긴급하게 data를 읽어야 할 경우에 가능한 상태인지를 검사하기 위해서는 revents field에 이 Macro를 사용해야 한다.
    이 Macro는 주로 network packet의 data 수신을 처리하기 위해 사용된다.

POLLOUT
    device file에 data를 써넣을수 있는 상태가 되면 poll()함수가 종료되도록 설정하기 위해 events field에 사용하는 Macro
    반대로 poll() 함수가 종료되었을때 device file에 data를 써넣을 수 있는지 검사하기 위해서는 revents filed에 이 Macro를 사용해야 한다.

POLLERR
    device file에 error가 발생했을때 poll()함수가 종료되도록 설정하기 위해 events field에 사용하는 Macro
    반대로 poll()함수가 종료되었을때 device file에 error가 발생했는지 검사하기 위해서는 revents field에 이 Macro를 사용해야 한다.

POLLHUP
    device file에 hangup이 발생했을때 poll()함수가 종료되도록 설정하기 위해 events filed에 사용하는 Macro
    반대로 poll()함수가 종료되엇을때 device file에 hungup이 발생했는지를 검사하기 위해서는 revents filed에 이 Macro를 사용해야한다.

POLLNVAL
    등록된 file descriptor가 유효하지 않은 값일때 poll()함수가 종료되도록 설정하기 위해 events 필드에 사용하는 Macro
    반대로 poll()함수가 종료 되었을때 file descriptor가 유효한지 그렇지 않은지를 검사하기 위해서는 revents field에 이 Macro를
    사용해야 한다. 이는 주로 network 처리를 할때 socket handler가 무효화 되었는지를 검사하는 방법으로 사용된다.

poll()함수는 pollfd구조체 형식으로 등록된 사건이 발생하거나 timeout 매개변수에 전달된 시간이 지나면 잠들어 있던 process가 깨어나면서
poll()함수가 종료된다. 이때 반환된 값이 0보다 작다면 poll()함수에서 error가 발생한 경우이며, 반환된 값이 0 이라면 아무런 사건도 없이 매개변수값 timeout에 지정된 시간이 초과된 경우이다.
그리고 반환된 값이 0보다 크다면 등록된 pollfd 구조체 형식으로 사건이 발생한 개수가 반환된 것이다.
*/
    poll_event.fd = filehandle->handle(); // File Descripter 입력
    poll_event.events = POLLIN | POLLOUT | POLLERR; // 원하는 이벤트 등록
    poll_event.revents = 0;

    while(!m_bFinished)
    {
        retval  = poll( &poll_event, 1, 30000); // timeout 10 sec

        if(retval > 0)
        {
            if(poll_event.revents & POLLIN)
            {
                qDebug(DMOD" Event occure \n");
                // read data or ioctl
            }
            if(poll_event.revents & POLLOUT){
				// write data or ioctl
            }else{
                qDebug(DMOD" Unknown reason Event occure %X \n", poll_event.revents);
            }
        }else if(retval == 0)
        {
            qDebug(DMOD" poll Timeout \n");
        }
        else{
            qDebug(DMOD" poll function error! \n");
        }
    }

}

 

드라이버 소스


// 전역 변수로 wait queue 를 선언바니다. 
DECLARE_WAIT_QUEUE_HEAD(g_WaitQueue_read);
DECLARE_WAIT_QUEUE_HEAD(g_WaitQueue_write);

// probe 함수에 서 wait queue 를 초기화 합니다. 
init_waitqueue_head(&g_WaitQueue_io); // init poll wait queue

// poll 함수를 등록 및 선언해 줍니다. 

unsigned int dev_poll( struct file *file, poll_tablr *wait)
{
	int mask = 0;

	poll_wait( file, &g_WaitQueue_read, wait );
    poll_wait( file, &g_WaitQueue_write, wait );
    
    // 여기서 드라이버의 코드에 따라서 활성화할 이벤트를 지정해 줍니다. 
	if( condition == 1 ) mask |= (POLLIN | POLLRDNORM ); // 
    if( condition == 2 ) mask |= (POLLOUT | POKKWRDNORM ); // 
    
    
	return mask;
}

static struct file_operations fops = {
	.read=dev_read,
	.write=dev_write,
	.unlocked_ioctl=dev_ioctl,
	.mmap=dev_mmap,
	.open=dev_open,
	.release=dev_release,
	.poll=dev_poll, 
};


void wakeup_poll_io(int condition)
{
	if(condition == 1)
    	wake_up_interruptible(&g_WaitQueue_read);  // poll 처리 활성화
    else if(condition == 2)
    	wake_up_interruptible(&g_WaitQueue_write);  // poll 처리 활성화
}

반응형

댓글