Re: File access

From: Richard B. Johnson
Date: Tue Aug 19 2003 - 10:18:43 EST


On Tue, 19 Aug 2003, Simon Haynes wrote:

> Thanks I have looked at the attached file and I would really not like to
> access a file from the kernel but I cannot seem to get the user land app to
> work with writing. If you consider a kernel module which, in some event,
> needs to save some information in a file. The usr app is blocked in a read
> with interruptible_sleep_on. When the first write occurs the module calls
> wake_up_interruptible to write the data. Before the module can write the next
> chunk of data it needs to stall until the user process has finished.
> I can not find a method of stalling the module so it seems my only solution
> is to write the file from the kernel or dump the data somewhere manually.
>
> Cheers

No. SOP in user mode:
pf.fd = fd;
pf.revents = 0;
pr.events = POLLIN|OTHER_STUFF;
if(poll(&pf, 1, NR) > 0)
if(pf.revents & POLLIN))
read(fd, buf, BUF_LEN);

In the kernel module:

static wait_queue_head_t pwait;
static size_t global_poll;
static spinlock_t mylock;

// Remember to initialize both pwait and mylock;

static size_t poll(struct file *fp, struct poll_table_struct *wait)
{
size_t poll_flag;
size_t flags;
poll_wait(fp, &pwait, wait);
spin_lock_irqsave(&mylock, flags);
poll_flag = global_poll | POLLRDNORM|POLLWRNORM;
global_poll = 0;
spin_lock_irqrestore(&mylock, flags);
return poll_flag;
}

static void ISR(int irq, void *v, struct pt_regs *sp)
{
spin_lock(&mylock);
do_stuff_to_read_data_into_a_buffer();
spin_unlock(&mylock);
global_poll = POLLIN;
wake_up_interruptible(&pwait);
}


So. You have a user-task sleeping in poll() or select().
The kernel is interrupted. It calls your ISR where
you take data from wherever and put it into a buffer.
Then your ISR code, which knows that data are now available,
signals the sleeping task via wake_up_interruptible() and
then returns. The kernel scheduler now knows that your
task should be put into the run-queue and your task gets
the CPU via a return from poll(). You read the status
and now your task knows that data are available. Your
task calls read() to get the data.


There are no 'stalls'. You can be interrupted at any time.
Any time you switch buffers or manipulate pointers within
the module-code, where your code could get 'confused'
if an interrupt occurred, you use a spin-lock. This
prevents an interrupt from occurring at that time. You
release the lock as soon as it is safe to do so.

If data are streaming, you may need several buffers. You
need to synchronize your read() and the data source (the
ISR) so that old data are never overwritten. This, too, is
SOP. Just do it. It works. It's the basic stuff that makes
Unix work. There are lots of examples in the modules
supplied with the kernel sources.


Cheers,
Dick Johnson
Penguin : Linux version 2.4.20 on an i686 machine (797.90 BogoMips).
Note 96.31% of all statistics are fiction.


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/