여러개의 fd를 사용하는데, 둘 이상 의 fd에서 io에서 일어나면 처리되는 것
int poll 함수를  입출력 다중화 함수라고 한다.


write를 하려고 할때, 데이터가 모든 것이 올때까지 기다린 다음에 write를 해야 한다.
이때 poll을 쓰는 것이다.


어플 코드


   struct pollfd Events[2];

    Events[0].fd = fd_fnd;
    Events[0].events = POLLIN; //waiting read
    Events[1].fd = fd_dot;
    Events[1].events = POLLOUT; //waiting write


    retval = poll(Events, 2, 7000);    // Event waiting


    ioctl(fd_fnd, 3, timerPeriod);
    ioctl(fd_dot, 2, timerPeriod);

    if(retval < 0) {
            perror("Poll_Test");
            exit(EXIT_FAILURE);
        }
        if(retval == 0) {
            printf("[APP]Wakeup_Poll_Event:No Event!!\n");
            continue;
            //exit(EXIT_FAILURE);
        }


// compare expected event with returned event
        if(Events[0].revents & POLLIN)
        {
            if(read(Events[0].fd, (void *)&data, sizeof(data)) > 0) 
                printf("[APP]Wakeup_Poll_Event:Event_FND(%x)!!\n", data);
            else 
                printf("[APP]Wakeup_Poll_Event:Event_FND(Data Read Error)!!\n");
        }

        if(Events[1].revents & POLLOUT)
        {
            dot_data = 1;    // dot_show_no
            if(write(Events[1].fd, (void *)&dot_data, sizeof(dot_data)) > 0) 
                printf("[APP]Wakeup_Poll_Event:Event_DOT!!\n");
            else 
                printf("[APP]Wakeup_Poll_Event:Event_DOT(Data Write Error)!!\n");
        }





커널모듈 소스


ssize_t fnd_read (struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
    short data;
    printk("OST1 Int. Waiting(%d)...\n", flag_ost1Int);

    if(!flag_ost1Int) {
        if(!(filp->f_flags & O_NONBLOCK)) {
            interruptible_sleep_on(&WaitQueue_Read); // waiting..
            printk("[DD]FND_Read_WakeUp!!\n");
        } else {
            return -EAGAIN;
        }
    }

data = FND_CS0;

        printk("OST1 Int Happened(%04x)...\n", data);
copy_to_user((void *)buf, (void *)&data, count);
flag_ost1Int = 0;
return(count);
}




DECLARE_WAIT_QUEUE_HEAD(WaitQueue_Read);

void ost1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
    OST1_TIMER_OFF;
    flag_ost1Int = 1;
    wake_up_interruptible(&WaitQueue_Read); // wakeup..
}



unsigned int fnd_poll(struct file *filp, struct poll_table_struct *pt) {
int mask;
poll_wait(filp, &WaitQueue_Read, pt); // interruptible_sleep_on..
if (flag_ost1Int == 1) {
mask |= POLLIN | POLLRDNORM;
}
return mask;
}



그러면, OS_TIMER는 언제 넣지??
app에서 사용될 경우를 살펴본다.
ioctl 3으로 쓰고, poll 함수를 쓴다.


        ioctl(fd_fnd, 3, timerPeriod);
        retval = poll(Events, 2, 7000);    // Event waiting




따라서,  ioctl cmd를 3을 넘겼을 때, 처리할 OST1_TIMER_ON을 사용하도록 한다.



int fnd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
... 
switch(cmd)
{
 
        case 3:  
            printk("\ncmd = 3\n");
            timerPeriod = arg;
            timerClkVal = timerPeriod*SEC_CLK;
            OST1_TIMER_ON;
            break;
}
... 
}





*참고


아래 두 코드는 동일하다..


if (flag_dotInt) {
printk("                              [DD]DOT_Write_Wait...\n");
     retstate = interruptible_sleep_on(&WaitQueue_Write);
     if(retstate) return retstate;
     printk("                              [DD]DOT_Write_Wakeup...\n");
}

  

wait_event_interruptible 함수는 sleep을 시킬 수 있는, 조건문이 있는 매크로이다


printk("                              [DD]DOT_Write_Wait...\n");
retstate = wait_event_interruptible(WaitQueue_Write, flag_dotInt);
if(retstate) return retstate;
     printk("                              [DD]DOT_Write_Wakeup...\n");



 


Posted by '김용환'
,