여러개의 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");
'c or linux' 카테고리의 다른 글
[공부중] queue_task 함수에서 tq_immediate 사용하기 (0) | 2011.04.21 |
---|---|
[공부중] queue_task 예제 (0) | 2011.04.21 |
[공부중] blocking io 와 waiting queue (0) | 2011.04.21 |
[공부중] header 파일 -irqs.h (0) | 2011.04.20 |
CPU 구성요소 (0) | 2011.04.20 |